From 387af977bcb8aa8e5e26e5c6295aad8de6f26283 Mon Sep 17 00:00:00 2001 From: Hugh Rawlinson Date: Wed, 22 May 2019 14:58:42 +0200 Subject: [PATCH 1/2] chore: update node-gyp to mitigate a security advisory node-gyp@3.8.0 uses fstream@1.0.11, which has this advisory: https://www.npmjs.com/advisories/886 node-gyp@4.0.0 uses fstream@1.0.12, which has resolved the issue --- node_modules/.cache/esm/.data.blob | Bin 0 -> 4721272 bytes node_modules/.cache/esm/.data.json | 1 + node_modules/.cache/esm/01261cd2db2fb243.js | 384 ++ node_modules/fstream/.npmignore | 5 - node_modules/fstream/lib/writer.js | 2 +- node_modules/fstream/package.json | 16 +- node_modules/node-gyp/CHANGELOG.md | 8 + node_modules/node-gyp/lib/configure.js | 2 +- node_modules/node-gyp/lib/install.js | 38 +- .../node-gyp/node_modules/tar/.npmignore | 5 - node_modules/node-gyp/package.json | 37 +- .../npm-lifecycle/node_modules/.bin/node-gyp | 1 + .../npm-lifecycle/node_modules/.bin/nopt | 1 + .../npm-lifecycle/node_modules/.bin/semver | 1 + .../node-gyp/.github/ISSUE_TEMPLATE.md | 26 + .../node-gyp/.github/PULL_REQUEST_TEMPLATE.md | 17 + .../node_modules/node-gyp/CHANGELOG.md | 227 + .../node_modules/node-gyp/CONTRIBUTING.md | 34 + .../node_modules/node-gyp/LICENSE | 24 + .../node_modules/node-gyp/README.md | 244 ++ .../node_modules/node-gyp/addon.gypi | 147 + .../node_modules/node-gyp/bin/node-gyp.js | 148 + .../node_modules/node-gyp/gyp/AUTHORS | 13 + .../node_modules/node-gyp/gyp/DEPS | 24 + .../node_modules/node-gyp/gyp/LICENSE | 27 + .../node_modules/node-gyp/gyp/OWNERS | 1 + .../node_modules/node-gyp/gyp/PRESUBMIT.py | 139 + .../node-gyp/gyp/codereview.settings | 10 + .../node-gyp/gyp/data/win/large-pdb-shim.cc | 12 + .../node_modules/node-gyp/gyp/gyp | 8 + .../node_modules/node-gyp/gyp/gyp.bat | 5 + .../node_modules/node-gyp/gyp/gyp_main.py | 16 + .../node-gyp/gyp/pylib/gyp/MSVSNew.py | 340 ++ .../node-gyp/gyp/pylib/gyp/MSVSProject.py | 208 + .../node-gyp/gyp/pylib/gyp/MSVSSettings.py | 1096 +++++ .../gyp/pylib/gyp/MSVSSettings_test.py | 1483 +++++++ .../node-gyp/gyp/pylib/gyp/MSVSToolFile.py | 58 + .../node-gyp/gyp/pylib/gyp/MSVSUserFile.py | 147 + .../node-gyp/gyp/pylib/gyp/MSVSUtil.py | 270 ++ .../node-gyp/gyp/pylib/gyp/MSVSVersion.py | 443 ++ .../node-gyp/gyp/pylib/gyp/__init__.py | 548 +++ .../node-gyp/gyp/pylib/gyp/common.py | 612 +++ .../node-gyp/gyp/pylib/gyp/common_test.py | 72 + .../node-gyp/gyp/pylib/gyp/easy_xml.py | 162 + .../node-gyp/gyp/pylib/gyp/easy_xml_test.py | 103 + .../node-gyp/gyp/pylib/gyp/flock_tool.py | 54 + .../gyp/pylib/gyp/generator/__init__.py | 0 .../gyp/pylib/gyp/generator/analyzer.py | 741 ++++ .../gyp/pylib/gyp/generator/android.py | 1095 +++++ .../node-gyp/gyp/pylib/gyp/generator/cmake.py | 1221 ++++++ .../gyp/generator/dump_dependency_json.py | 99 + .../gyp/pylib/gyp/generator/eclipse.py | 425 ++ .../node-gyp/gyp/pylib/gyp/generator/gypd.py | 94 + .../node-gyp/gyp/pylib/gyp/generator/gypsh.py | 56 + .../node-gyp/gyp/pylib/gyp/generator/make.py | 2263 ++++++++++ .../node-gyp/gyp/pylib/gyp/generator/msvs.py | 3494 ++++++++++++++++ .../gyp/pylib/gyp/generator/msvs_test.py | 37 + .../node-gyp/gyp/pylib/gyp/generator/ninja.py | 2422 +++++++++++ .../gyp/pylib/gyp/generator/ninja_test.py | 47 + .../node-gyp/gyp/pylib/gyp/generator/xcode.py | 1300 ++++++ .../gyp/pylib/gyp/generator/xcode_test.py | 23 + .../node-gyp/gyp/pylib/gyp/input.py | 2902 +++++++++++++ .../node-gyp/gyp/pylib/gyp/input_test.py | 90 + .../node-gyp/gyp/pylib/gyp/mac_tool.py | 610 +++ .../node-gyp/gyp/pylib/gyp/msvs_emulation.py | 1087 +++++ .../node-gyp/gyp/pylib/gyp/ninja_syntax.py | 160 + .../node-gyp/gyp/pylib/gyp/ordered_dict.py | 289 ++ .../node-gyp/gyp/pylib/gyp/simple_copy.py | 46 + .../node-gyp/gyp/pylib/gyp/win_tool.py | 314 ++ .../node-gyp/gyp/pylib/gyp/xcode_emulation.py | 1653 ++++++++ .../node-gyp/gyp/pylib/gyp/xcode_ninja.py | 270 ++ .../node-gyp/gyp/pylib/gyp/xcodeproj_file.py | 2927 +++++++++++++ .../node-gyp/gyp/pylib/gyp/xml_fix.py | 69 + .../node_modules/node-gyp/gyp/samples/samples | 81 + .../node-gyp/gyp/samples/samples.bat | 5 + .../node_modules/node-gyp/gyp/setup.py | 19 + .../node_modules/node-gyp/gyp/tools/README | 15 + .../node-gyp/gyp/tools/Xcode/README | 5 + .../tools/Xcode/Specifications/gyp.pbfilespec | 27 + .../tools/Xcode/Specifications/gyp.xclangspec | 226 + .../node-gyp/gyp/tools/emacs/README | 12 + .../node-gyp/gyp/tools/emacs/gyp-tests.el | 63 + .../node-gyp/gyp/tools/emacs/gyp.el | 275 ++ .../gyp/tools/emacs/run-unit-tests.sh | 7 + .../gyp/tools/emacs/testdata/media.gyp | 1105 +++++ .../tools/emacs/testdata/media.gyp.fontified | 1107 +++++ .../node-gyp/gyp/tools/graphviz.py | 100 + .../node-gyp/gyp/tools/pretty_gyp.py | 155 + .../node-gyp/gyp/tools/pretty_sln.py | 169 + .../node-gyp/gyp/tools/pretty_vcproj.py | 329 ++ .../node_modules/node-gyp/lib/Find-VS2017.cs | 273 ++ .../node_modules/node-gyp/lib/build.js | 270 ++ .../node_modules/node-gyp/lib/clean.js | 22 + .../node_modules/node-gyp/lib/configure.js | 524 +++ .../node-gyp/lib/find-node-directory.js | 61 + .../node_modules/node-gyp/lib/find-vs2017.js | 46 + .../node_modules/node-gyp/lib/install.js | 475 +++ .../node_modules/node-gyp/lib/list.js | 33 + .../node_modules/node-gyp/lib/node-gyp.js | 216 + .../node-gyp/lib/process-release.js | 155 + .../node_modules/node-gyp/lib/rebuild.js | 14 + .../node_modules/node-gyp/lib/remove.js | 52 + .../node_modules/node-gyp/package.json | 85 + .../node-gyp/src/win_delay_load_hook.cc | 36 + .../node_modules/node-gyp/test/docker.sh | 164 + .../node-gyp/test/fixtures/ca-bundle.crt | 40 + .../node-gyp/test/fixtures/ca.crt | 21 + .../node-gyp/test/fixtures/server.crt | 19 + .../node-gyp/test/fixtures/server.key | 28 + .../node-gyp/test/fixtures/test-charmap.py | 22 + .../node-gyp/test/process-exec-sync.js | 138 + .../node-gyp/test/simple-proxy.js | 24 + .../node_modules/node-gyp/test/test-addon.js | 113 + .../node-gyp/test/test-configure-python.js | 74 + .../node-gyp/test/test-download.js | 102 + .../test/test-find-accessible-sync.js | 86 + .../node-gyp/test/test-find-node-directory.js | 115 + .../node-gyp/test/test-find-python.js | 339 ++ .../node-gyp/test/test-install.js | 37 + .../node-gyp/test/test-options.js | 25 + .../node-gyp/test/test-process-release.js | 637 +++ .../gyp/generator/compile_commands_json.py | 115 + .../node_modules/nopt/.npmignore | 1 + .../node_modules/nopt/.travis.yml | 9 + .../npm-lifecycle/node_modules/nopt/LICENSE | 15 + .../npm-lifecycle/node_modules/nopt/README.md | 211 + .../node_modules/nopt/bin/nopt.js | 54 + .../node_modules/nopt/examples/my-program.js | 30 + .../node_modules/nopt/lib/nopt.js | 415 ++ .../node_modules/nopt/package.json | 57 + .../node_modules/nopt/test/basic.js | 273 ++ .../npm-lifecycle/node_modules/semver/LICENSE | 15 + .../node_modules/semver/README.md | 350 ++ .../node_modules/semver/bin/semver | 133 + .../node_modules/semver/package.json | 54 + .../node_modules/semver/range.bnf | 16 + .../node_modules/semver/semver.js | 1203 ++++++ .../node_modules/tar/.travis.yml | 0 .../node_modules/tar/LICENSE | 0 .../node_modules/tar/README.md | 0 .../tar/coverage/lcov-report/base.css | 212 + .../tar/coverage/lcov-report/index.html | 106 + .../tar/coverage/lcov-report/prettify.css | 1 + .../tar/coverage/lcov-report/prettify.js | 1 + .../lcov-report/sort-arrow-sprite.png | Bin 0 -> 209 bytes .../tar/coverage/lcov-report/sorter.js | 158 + .../tar/coverage/lcov-report/tar/index.html | 93 + .../coverage/lcov-report/tar/index.js.html | 119 + .../lcov-report/tar/lib/create.js.html | 380 ++ .../lcov-report/tar/lib/extract.js.html | 401 ++ .../lcov-report/tar/lib/header.js.html | 881 ++++ .../tar/lib/high-level-opt.js.html | 152 + .../coverage/lcov-report/tar/lib/index.html | 314 ++ .../lcov-report/tar/lib/large-numbers.js.html | 341 ++ .../coverage/lcov-report/tar/lib/list.js.html | 449 ++ .../lcov-report/tar/lib/mkdir.js.html | 686 +++ .../coverage/lcov-report/tar/lib/pack.js.html | 1268 ++++++ .../lcov-report/tar/lib/parse.js.html | 1310 ++++++ .../coverage/lcov-report/tar/lib/pax.js.html | 500 +++ .../lcov-report/tar/lib/read-entry.js.html | 347 ++ .../lcov-report/tar/lib/replace.js.html | 722 ++++ .../lcov-report/tar/lib/types.js.html | 197 + .../lcov-report/tar/lib/unpack.js.html | 1604 +++++++ .../lcov-report/tar/lib/update.js.html | 173 + .../lcov-report/tar/lib/warn-mixin.js.html | 107 + .../lcov-report/tar/lib/winchars.js.html | 134 + .../lcov-report/tar/lib/write-entry.js.html | 1268 ++++++ .../node_modules/tar/coverage/lcov.info | 3690 +++++++++++++++++ .../node_modules/tar/examples/extracter.js | 0 .../node_modules/tar/examples/packer.js | 0 .../node_modules/tar/examples/reader.js | 0 .../node_modules/tar/lib/buffer-entry.js | 0 .../node_modules/tar/lib/entry-writer.js | 0 .../node_modules/tar/lib/entry.js | 0 .../tar/lib/extended-header-writer.js | 0 .../node_modules/tar/lib/extended-header.js | 0 .../node_modules/tar/lib/extract.js | 0 .../tar/lib/global-header-writer.js | 0 .../node_modules/tar/lib/header.js | 0 .../node_modules/tar/lib/pack.js | 0 .../node_modules/tar/lib/parse.js | 6 + .../node_modules/tar/package.json | 18 +- .../node_modules/tar/tar.js | 0 .../tar/test/00-setup-fixtures.js | 0 .../tar/test/cb-never-called-1.0.1.tgz | Bin .../tar/test/dir-normalization.js | 0 .../tar/test/dir-normalization.tar | Bin .../node_modules/tar/test/error-on-broken.js | 0 .../node_modules/tar/test/extract-move.js | 0 .../node_modules/tar/test/extract.js | 0 .../node_modules/tar/test/fixtures.tgz | Bin .../node_modules/tar/test/header.js | 0 .../tar/test/link-file-entry-collision.js | 39 + .../link-file-entry-collision/bad-link.hex | 25 + .../link-file-entry-collision/bad-link.tar | Bin 0 -> 3584 bytes .../tar/test/pack-no-proprietary.js | 0 .../node_modules/tar/test/pack.js | 0 .../node_modules/tar/test/parse-discard.js | 0 .../node_modules/tar/test/parse.js | 0 .../node_modules/tar/test/zz-cleanup.js | 0 package-lock.json | 69 +- package.json | 2 +- .../07/8db5f6377f6321fceaaedf497de124dc9465 | Bin 0 -> 4025 bytes .../43/09dadee6b54cc0b8d247e8d7c7a0975bdc9b | Bin 0 -> 1519 bytes .../56/8a2b1efaeb95bec4d9e59e5301fc63339866 | Bin 0 -> 4733 bytes ...ff9a8695bdd5cae7ce03bbf1e94e93613a00f25f21 | 1 + ...22c6b860203eb4853ce85f15f26b96c84b8d9e7320 | 1 + ...f66d3a01cb2789b2cf614aeb292dbeb4afe0b206cc | Bin 0 -> 4733 bytes ...6deb04a85cc226987f32f6abcea8d4427c3aad50eb | Bin 0 -> 5787 bytes ...6133732d6459066a46c5cf7c83bb5eed08c8061973 | 1 + ...e08430c92b8e6040232ed7e7587249a5777214fce6 | 1 + ...56e1333ed74cd0f33fd00f401aa912a07a2a138d41 | Bin 0 -> 15106 bytes ...11ee631e15017eecbf67401b468259d52f790d1249 | Bin 0 -> 27637 bytes ...d6fc97011bebe11fc8e308eaff2d4224c21477d1d5 | 2 + ...c20ec3ebdaa0e12382c5c6badfa30fb7b376f6a580 | 2 + ...9eb38d07610e8ad7007ffc3f0f3b25da20b9af281d | 2 + ...6f7e1fce3892c4e717a9379d4ad43a7111b5dc8cc2 | 3 + ...d9e42f3ca7ad942331f73dd73c3e6f5549e910679b | 3 + ...1cc7f9caf4f3e654df7abd1fc8279dde9f935c76aa | 2 + ...51111ddb9fa636ef144ff9fad15784c1e9620b0dac | 2 + ...2f5a63b3d871adc66f517669450807aec3b62e71b2 | 2 + ...6ed2b2019e46a63cff8cbb76981a37eac2100c8e55 | 3 + ...70bd1392d702e19e29ee41c85a315fd7e717f8373c | 2 + ...4407f0d9cae19a4d56f253f7746786597a52daa76d | 2 + ...0c54baee7ae9bec37f513387665b57ac2bcd167b70 | 2 + ...e13f61bb768d7cbf82072f798d17071572ab3943f2 | 2 + test/npm_cache/anonymous-cli-metrics.json | 1 + 227 files changed, 57566 insertions(+), 91 deletions(-) create mode 100644 node_modules/.cache/esm/.data.blob create mode 100644 node_modules/.cache/esm/.data.json create mode 100644 node_modules/.cache/esm/01261cd2db2fb243.js delete mode 100644 node_modules/fstream/.npmignore delete mode 100644 node_modules/node-gyp/node_modules/tar/.npmignore create mode 120000 node_modules/npm-lifecycle/node_modules/.bin/node-gyp create mode 120000 node_modules/npm-lifecycle/node_modules/.bin/nopt create mode 120000 node_modules/npm-lifecycle/node_modules/.bin/semver create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/.github/ISSUE_TEMPLATE.md create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/.github/PULL_REQUEST_TEMPLATE.md create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/CHANGELOG.md create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/CONTRIBUTING.md create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/LICENSE create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/README.md create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/addon.gypi create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/bin/node-gyp.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/AUTHORS create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/DEPS create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/LICENSE create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/OWNERS create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/PRESUBMIT.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/codereview.settings create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp.bat create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp_main.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/__init__.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common_test.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input_test.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ordered_dict.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples.bat create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/setup.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/README create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/README create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.pbfilespec create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.xclangspec create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/emacs/README create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/emacs/gyp-tests.el create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/emacs/gyp.el create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/emacs/run-unit-tests.sh create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/emacs/testdata/media.gyp create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/emacs/testdata/media.gyp.fontified create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/graphviz.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_gyp.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_sln.py create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_vcproj.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/Find-VS2017.cs create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/build.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/clean.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/configure.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-node-directory.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-vs2017.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/install.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/list.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/node-gyp.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/process-release.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/rebuild.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/remove.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/package.json create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/src/win_delay_load_hook.cc create mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/test/docker.sh create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca-bundle.crt create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca.crt create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.crt create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.key create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/test-charmap.py create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/process-exec-sync.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/simple-proxy.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-addon.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-configure-python.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-download.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-accessible-sync.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-node-directory.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-python.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-install.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-options.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-process-release.js create mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/tools/gyp/pylib/gyp/generator/compile_commands_json.py create mode 100644 node_modules/npm-lifecycle/node_modules/nopt/.npmignore create mode 100644 node_modules/npm-lifecycle/node_modules/nopt/.travis.yml create mode 100644 node_modules/npm-lifecycle/node_modules/nopt/LICENSE create mode 100644 node_modules/npm-lifecycle/node_modules/nopt/README.md create mode 100755 node_modules/npm-lifecycle/node_modules/nopt/bin/nopt.js create mode 100755 node_modules/npm-lifecycle/node_modules/nopt/examples/my-program.js create mode 100644 node_modules/npm-lifecycle/node_modules/nopt/lib/nopt.js create mode 100644 node_modules/npm-lifecycle/node_modules/nopt/package.json create mode 100644 node_modules/npm-lifecycle/node_modules/nopt/test/basic.js create mode 100644 node_modules/npm-lifecycle/node_modules/semver/LICENSE create mode 100644 node_modules/npm-lifecycle/node_modules/semver/README.md create mode 100755 node_modules/npm-lifecycle/node_modules/semver/bin/semver create mode 100644 node_modules/npm-lifecycle/node_modules/semver/package.json create mode 100644 node_modules/npm-lifecycle/node_modules/semver/range.bnf create mode 100644 node_modules/npm-lifecycle/node_modules/semver/semver.js rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/.travis.yml (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/LICENSE (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/README.md (100%) create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/base.css create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/index.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.css create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.js create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/sort-arrow-sprite.png create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/sorter.js create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/create.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/extract.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/header.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/high-level-opt.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/index.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/large-numbers.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/list.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/mkdir.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pack.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/parse.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pax.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/read-entry.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/replace.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/types.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/unpack.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/update.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/warn-mixin.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/winchars.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/write-entry.js.html create mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov.info rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/examples/extracter.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/examples/packer.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/examples/reader.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/lib/buffer-entry.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/lib/entry-writer.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/lib/entry.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/lib/extended-header-writer.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/lib/extended-header.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/lib/extract.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/lib/global-header-writer.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/lib/header.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/lib/pack.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/lib/parse.js (98%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/package.json (68%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/tar.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/00-setup-fixtures.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/cb-never-called-1.0.1.tgz (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/dir-normalization.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/dir-normalization.tar (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/error-on-broken.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/extract-move.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/extract.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/fixtures.tgz (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/header.js (100%) create mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision.js create mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.hex create mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.tar rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/pack-no-proprietary.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/pack.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/parse-discard.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/parse.js (100%) rename node_modules/{node-gyp => npm-lifecycle}/node_modules/tar/test/zz-cleanup.js (100%) create mode 100644 test/npm_cache/_cacache/content-v2/sha1/07/07/8db5f6377f6321fceaaedf497de124dc9465 create mode 100644 test/npm_cache/_cacache/content-v2/sha1/ca/43/09dadee6b54cc0b8d247e8d7c7a0975bdc9b create mode 100644 test/npm_cache/_cacache/content-v2/sha1/ee/56/8a2b1efaeb95bec4d9e59e5301fc63339866 create mode 100644 test/npm_cache/_cacache/content-v2/sha512/0b/61/241d7c17bcbb1baee7094d14b7c451efecc7ffcbd92598a0f13d313cc9ebc2a07e61f007baf58fbf94ff9a8695bdd5cae7ce03bbf1e94e93613a00f25f21 create mode 100644 test/npm_cache/_cacache/content-v2/sha512/21/82/eac4f83e50f3b6aa8bea561c5dfebdc1d66941e2da785af406e045de56a0fc422034ca7fa2ab5fa99022c6b860203eb4853ce85f15f26b96c84b8d9e7320 create mode 100644 test/npm_cache/_cacache/content-v2/sha512/2e/36/48f976830aeaba0724b382a09a6a6736dfd4c755963a4f462f963f9ecb211c2258f00766dc3aa68664f66d3a01cb2789b2cf614aeb292dbeb4afe0b206cc create mode 100644 test/npm_cache/_cacache/content-v2/sha512/55/a3/cb2911b2e84215a5d93c85438bac8f76cdf605a4ebb8bcc45a615a178ec498e4006d8b05e7569d3dc46deb04a85cc226987f32f6abcea8d4427c3aad50eb create mode 100644 test/npm_cache/_cacache/content-v2/sha512/7d/fa/5dbc56b117403ce140a22b56adad0b0caf15ccdc5249bca0360abdc2fab38100903a6de54f3f8597746133732d6459066a46c5cf7c83bb5eed08c8061973 create mode 100644 test/npm_cache/_cacache/content-v2/sha512/af/32/9b49da433ab139a3043f204d7d79baddbe094f6b61cbd3da374dd4fb838cd1b7085e57237e1fd02846e08430c92b8e6040232ed7e7587249a5777214fce6 create mode 100644 test/npm_cache/_cacache/content-v2/sha512/d0/9a/edf7b49ad59ad630957608c01609c61ecc2eb3ce20ef7f9020ae8673aa278352399dbfdb23a742d07556e1333ed74cd0f33fd00f401aa912a07a2a138d41 create mode 100644 test/npm_cache/_cacache/content-v2/sha512/d1/ec/7bfbe036d289d705e16f7ec05b81c09a432e45e177773f0918e5acf8fd88a0b2559e35c1829ce0cb0c11ee631e15017eecbf67401b468259d52f790d1249 create mode 100644 test/npm_cache/_cacache/index-v5/21/90/97d7c2a8081808dcd3d6fc97011bebe11fc8e308eaff2d4224c21477d1d5 create mode 100644 test/npm_cache/_cacache/index-v5/2d/22/47328dfeb3a9f00c15c20ec3ebdaa0e12382c5c6badfa30fb7b376f6a580 create mode 100644 test/npm_cache/_cacache/index-v5/61/41/453946604fdfa210a19eb38d07610e8ad7007ffc3f0f3b25da20b9af281d create mode 100644 test/npm_cache/_cacache/index-v5/89/eb/a7a81ab3eeec3076546f7e1fce3892c4e717a9379d4ad43a7111b5dc8cc2 create mode 100644 test/npm_cache/_cacache/index-v5/93/4e/425c049345ed549becd9e42f3ca7ad942331f73dd73c3e6f5549e910679b create mode 100644 test/npm_cache/_cacache/index-v5/9b/03/54636aae9cb55a079d1cc7f9caf4f3e654df7abd1fc8279dde9f935c76aa create mode 100644 test/npm_cache/_cacache/index-v5/b7/1c/f06201305985169fc251111ddb9fa636ef144ff9fad15784c1e9620b0dac create mode 100644 test/npm_cache/_cacache/index-v5/b8/16/bf6e49afbd1323783f2f5a63b3d871adc66f517669450807aec3b62e71b2 create mode 100644 test/npm_cache/_cacache/index-v5/be/6a/458105f31e845d57376ed2b2019e46a63cff8cbb76981a37eac2100c8e55 create mode 100644 test/npm_cache/_cacache/index-v5/cf/e4/3df81895eebe708ef970bd1392d702e19e29ee41c85a315fd7e717f8373c create mode 100644 test/npm_cache/_cacache/index-v5/d0/a2/9b5933a9df317b031c4407f0d9cae19a4d56f253f7746786597a52daa76d create mode 100644 test/npm_cache/_cacache/index-v5/fe/7e/e4d136986019ebc5360c54baee7ae9bec37f513387665b57ac2bcd167b70 create mode 100644 test/npm_cache/_cacache/index-v5/ff/d3/eca629ba696cac5a91e13f61bb768d7cbf82072f798d17071572ab3943f2 create mode 100644 test/npm_cache/anonymous-cli-metrics.json diff --git a/node_modules/.cache/esm/.data.blob b/node_modules/.cache/esm/.data.blob new file mode 100644 index 0000000000000000000000000000000000000000..4129ea5998e1a3d3e71621b3834faef91bb4eb0f GIT binary patch literal 4721272 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�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

X?itF1`f(8F}Vp? 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

f?vt03(>4u%y@KJ+j<#LGN& zMdfDLxwmG&N51v=@esIQy0>P0Mb=~|JiBk=6!F5gPM{>N;Mt{{&>{Rra2$5lZ zPk#0o<14J1TgXq`5%>JBMD!7Q9>%S%rqp2k}uHmA$h})>( zw$$D96!lkbz_#$0>5I7i>@&puNySZn{0pWJGg(9^amU;LAl7eeQg9n;Gu|Msx>O`j z#J6T*rpULa6x>04f`zy$&kPaD`1&7SAvV6+tl$Ria15awvyCEXS*GvA%h&8>`krP0 z4nBME;;V--zG5Z5(Gy~Xp6PG$Ag)KRd;2lp=9Je~&o=E~-=C ztDV!=diI7vTSCcqi-Ozx!eG%#RM*bA%)$--x^n?>e^GEJuE@TPdNzt`#b5)|a<1k# zQ9iaRxSR#64C3&0!73|1dhfbV{HRuku*QH3ETiJQD)QGeoIQg91CNog%`rXeuCMZq1! z7A_46ZbRS49;05|MP*e*_)A>QH9_4N-!28WJZAaZBEFh3d{JHEmQVhZ=w^CZ#Z^6< z!~AfY6%6Cs{K{WNIeJCGCI0o)p9EhHyCa;qL8Gq|dU;jBbu7B|sKBL{msz+4J6DVC zX?H8QneoY;n7$FFVKKgg4~!Z}IbKt6diS5NATC|eUyyUU*uLj=1$V>hHopp-qQAY@ zj1qeJyMo*IV8|m(U%H~dbzk=t<#LaL>;J&*!cNl_y>xx;q_CGa6x^Zb3S8uysibd9 zztmvL@uq@1@>x`^z$xjw<%LACOYmC?uHw)oPcnU(O8RDA(qR$f+pFLr4xRX!`If1q z?~aJa#5&Hm72N2*ed1>Qm!3OHgi_CY=8wLZ@x7zqmXDni$n=d<>}AN|#iG2utKc@b z{`h&~#w+q}yV@;!!1gJ)L;c?QQs5MMhg=#Y>X-Kv+>#|L2U6bgioA;+O%i^|`wH%k zh}By~d`kLqqNBvh#19nQv3Bh-Kui*M-*R>+wnlkJXg}>Cx?i=2` zgt!kC+zp$KejxZ(W7=k^Y4_g+6%uzq!5wV*qp-h8ie5J6{7uxmA1Sz*_q@22@l8_n zvir@q_A$PL3a)C$95>T9NzqH^l*vKFeXQUjmW`;Typt4p4{z8$l(}p}#{4?uMu*MY~nKz*o*UT;ECP?=uD0 zcmJ}N$k$Nx^5A!Eh5kNQa0|{h>=Za9eWQm}ilMwl1vhQ&u3MQtL(xmg-s^>*cv!&= zKY3c%DW=uh_203_hYzE?UnsZ*>mGfP`ZE;$oroSO?CMJex8GBnF8C_-pMK|C!ms;E z!QCp&B$c}r=)M(>EFbDfj=m?-J|#PX8O>% zZ>Miv#p9xT@tA@e61DVGrmsv%-|+lu(eeMIf_t#d_vx(vu%1nXQqRY?yzwg2_mhI# zGiIOg|1e`&*o%CVDv8&HW`0(XZJ#b5PDv^iiTAGRKY%eFS8%=eZOsrkMPk>@ABmFm zi-OD8`c@7lu2du*efpfx%&!VAXy@@eM0|=xuc^FvJ^B7a!9|?R`7K?`=^3?KK;%K%nvMp4Y>cM-dV(*Q*b$tx6dWt z`3m22n=*zI_q&2y`OH7=Wqjjpk0|PThtYQFz^z1DJCzH&ys_$pumrpASYdShc;}VG zP2>p&aeXTT4^o5ZjIZKaM?GwXF(iEJaYBS6W8$WEJGh@XbnDx=y<6vI5N9ayZGL3b zAxd(kEy)U_$6ud&oe=RNhri@Ii}@ayGGpWPys{$3H^!JV$G~64H*VYd5sXg^-iR>t)f_l`9qlU1m|a*5 zAaN_xUKX>9FfT?N{Z(mOz99}%QpCads%m1sq8yVHy9!!<-KE4mrr`QMoboBj>{2NR}l$MuwV{A{e6 z#b5I6QGQov;+|A+$L{>5J8_0meoHz(IghwME4aB`?-Ol$p;|t!Op7KClT5@xz0AGi zPzvLlp_Jd@--S&h?k@_i$LlwbB(7K~zxxwD6q|8uRd6}Sw5`;$N73`TZ7+&^dsfBu zOFhYQv_MJUo;LeMy}M1pO>1+|^f?TmO*>t8OuXAZr{IR{irK{U)hOln(9hFE)x2H7 z%}p75FZq@!<#**hSBSp2zbd${&t27#@y$}o@0q|6v#6Kn72NXNfBco@w_GW|Tjq62 zAPy5?#3A$?^XN8~x7kX$Ja+VjPl?;1;JOxf6y>) zm2a*X$M{4iC;pP}$9aBwQgMwR>_u`A9y=3_^^8Tgb~)ehMXRZd zPjnLFFXiZa=TmuntVSv4YbHd9di)h7z6ZA+J4JbG75m%sSvS#MzN+AkeR%Icl5>>u z>l%`NEBWqLaBGHEh-$M)!5!MPbqH~oZX^z-?|4ghdl8>f&Np*~96JrdX3Tuo3eAj;|>`IUG#kaf9pL?<# zd1m`?+ajZHCf@)BceF*-7qo+#Qmh-qs0Gtkcw=cQaiIz>qW+nGiuzz)#Z251xSjnT zUPWA(f(t4t2xoE^%o8wy>+!_CY~sQd+~(x&ImDG$iLOzJo05}6T!ez_J7a4haaH9$ z+|IWi`hvKY3U0`2!^)`Viek}qA>w=R`trfVwN`M2o@;`Mo2}q7zG?W0xHbyzT8cS-~CbcaO-CSOpg}d4PBeE>v)HAI%pQ z(^Euq-pH;rTt=e(6EG##hl4!+mtS>n4ct z4InNm9w!{EiF$7vau4O0=fP@bGe1WE?Ju7Y*IvO*-9AHj2v{Y~ z^Juc@C90{y4iP49=B(GY5Z6_~9UJYsm@R{Wy%bQPiujJUITlP@KLzJ{V$Vd%i-`oV zQj_o9?Oq{nse+sK@^{1axGDuVb?x%8jBmMudw$mY*AiE( z;PfkB6&~fi3hvm{T8%httYN2bSI_mW8Q%&8xBqERTjocR$(VMqs7tjNRen~%xxRYf zcE(rk_QiLi>y8M<_l|-)m^Vzkan≶hPF468Elx+xx?39}0ODT&qvt_>Q=J3eNRQ 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�npRenaL}!p=72 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�ndhj>#XjR9 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

ygvR5qw_YRsC+E_*wu5IJ8zW+o# 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 z

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π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

-2OZq>9_-j5+nvQh9U63GeJi9R>jreZ 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 (#^L$UFFTzrOhAx6sx|mx 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�>x7P-{*-2f0ecL3bv-@g_Ta!h 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

+0!fuKLu_TPq8Qj)T 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%0D5F~#U+efo=}p`qBhK-~Aheb^Ec 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 z%0D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

&%LJ`hs`di9MBtRcW|y$# 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 z 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

8PID9deu+{T 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

  • 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 Bzv%z~ literal 0 HcmV?d00001 diff --git a/node_modules/.cache/esm/.data.json b/node_modules/.cache/esm/.data.json new file mode 100644 index 0000000000000..f851c60aec737 --- /dev/null +++ b/node_modules/.cache/esm/.data.json @@ -0,0 +1 @@ +{"map":{"4bcc649921137845.js":[0,1304],"07779371d9bcdfe7.js":[1304,31848],"a1dd45ce21137845.js":[31848,36152],"c68f825757a510ce.js":[36152,42304],"6eea19f457a510ce.js":[42304,50472],"a96a3ae957a510ce.js":[50472,51368],"249b34c957a510ce.js":[51368,52800],"d167523921137845.js":[52800,54472],"6368250b3460ae95.js":[54472,64864],"fd9a39b63460ae95.js":[64864,70280],"827da7f13460ae95.js":[70280,71352],"e380589c3460ae95.js":[71352,86144],"5c89a8627f0b843f.js":[86144,87104],"757252ca2f95aacc.js":[87104,89728],"f1377aed2d350237.js":[89728,91032],"90c86af42d350237.js":[91032,92112],"6c86a43bf1f0a572.js":[92112,95120],"27cf29e11771f47f.js":[95120,96928],"a126fac52d350237.js":[96928,98216],"903ec97349f7d246.js":[98216,104224],"d6b1a5cc2d350237.js":[104224,105216],"652a22bd2d350237.js":[105216,106312],"e46041010def8cae.js":[106312,108992],"bf748d6edb2fb243.js":[108992,110232],"8fb3696b3460ae95.js":[110232,117824],"6e772becc7eb21f6.js":[117824,118616],"3eb4319591adc060.js":[118616,119704],"46bcf78dc8a0631a.js":[119704,141392],"90d784883d1e01a1.js":[141392,150496],"7a844a993d1e01a1.js":[150496,154824],"106fca493d1e01a1.js":[154824,155672],"15be35003460ae95.js":[155672,156344],"ce123ba33460ae95.js":[156344,158744],"0901d4793460ae95.js":[158744,165784],"c4b8157a3460ae95.js":[165784,167048],"72d522f73460ae95.js":[167048,167944],"87d535e03460ae95.js":[167944,168928],"95ebed323460ae95.js":[168928,170272],"5daa52f93460ae95.js":[170272,174736],"60f2c5c03460ae95.js":[174736,178136],"032dd61a3460ae95.js":[178136,178992],"2eae96eb3460ae95.js":[178992,180144],"56220cae3460ae95.js":[180144,181120],"308ed2fc3460ae95.js":[181120,182136],"10bef34d3460ae95.js":[182136,183152],"982d93843460ae95.js":[183152,184168],"b810cce53460ae95.js":[184168,186320],"ceb824843460ae95.js":[186320,188264],"4020db4a3460ae95.js":[188264,191080],"b084cffd3460ae95.js":[191080,192984],"5ecd93133460ae95.js":[192984,194784],"9e647a303460ae95.js":[194784,195688],"14e198bc3460ae95.js":[195688,197312],"826ad8153460ae95.js":[197312,198512],"b0cb623d3460ae95.js":[198512,199624],"22094b093460ae95.js":[199624,200752],"e621b50e3460ae95.js":[200752,201912],"9a2117653460ae95.js":[201912,203248],"770b039b3460ae95.js":[203248,204568],"b445ec493460ae95.js":[204568,206160],"6050b3aedc569a8e.js":[206160,305496],"a57cc8d83460ae95.js":[305496,311816],"5bbeb335c511c9bd.js":[311816,312760],"0f5628d07bbf5e2b.js":[312760,313800],"fea194433460ae95.js":[313800,314928],"5a090291b1265ae5.js":[314928,316544],"3f171c9a0e13a01b.js":[316544,318024],"0b74009b3460ae95.js":[318024,318712],"3181bd913460ae95.js":[318712,321128],"6ce3e36a3460ae95.js":[321128,328184],"c41fb0f13460ae95.js":[328184,329464],"7ae873b23460ae95.js":[329464,330376],"d19c33293460ae95.js":[330376,331376],"f6a5ab073460ae95.js":[331376,332736],"7ac8e63d3460ae95.js":[332736,337216],"885439923460ae95.js":[337216,340632],"79b103f53460ae95.js":[340632,341504],"4ca9cd073460ae95.js":[341504,342672],"6368eaff3460ae95.js":[342672,343664],"6069c96e3460ae95.js":[343664,344696],"8fbe9f5d3460ae95.js":[344696,345728],"8a3e95f93460ae95.js":[345728,346760],"fe6ea95f3460ae95.js":[346760,348928],"d61181383460ae95.js":[348928,350888],"8c9da74d3460ae95.js":[350888,353712],"5fd4a5d53460ae95.js":[353712,355640],"c864808c3460ae95.js":[355640,357456],"37bde71c3460ae95.js":[357456,358384],"5522f9cb3460ae95.js":[358384,360024],"8379b1a23460ae95.js":[360024,361240],"3e818da03460ae95.js":[361240,362376],"0d4f801b3460ae95.js":[362376,363520],"38d5fbe53460ae95.js":[363520,364696],"1f248b433460ae95.js":[364696,366048],"b58e74223460ae95.js":[366048,367384],"e488e6883460ae95.js":[367384,368992],"3987a10c3460ae95.js":[368992,375328],"e79a9a501194c3a5.js":[375328,376936],"45d396698b91a4fe.js":[376936,377792],"5ea879023460ae95.js":[377792,380032],"a31ecd733460ae95.js":[380032,381816],"72689e479e359637.js":[381816,384344],"c7d681d33d1e01a1.js":[384344,385480],"27b79903d9bcdfe7.js":[385480,388104],"c2d48a5611e1cf2f.js":[388104,393784],"bd95a1cbc2cce000.js":[393784,395400],"a3a26e99c2cce000.js":[395400,397368],"c308578b6c7a370e.js":[397368,402208],"ffaea614db2fb243.js":[402208,404504],"375fe35fa64d3c66.js":[404504,405384],"d1731f20fbafa855.js":[405384,406312],"a5de0d289a2960f3.js":[406312,407200],"4731d2d7e8691b4c.js":[407200,408104],"d620319557a510ce.js":[408104,411624],"f810c3c211e1cf2f.js":[411624,413680],"6ac702a29a2960f3.js":[413680,414808],"154f8623a932150e.js":[414808,416096],"1ed6ea1cc7eb21f6.js":[416096,417480],"c1140e9502a7330b.js":[417480,421784],"8deaf0ac02a7330b.js":[421784,423104],"3de39d6221137845.js":[423104,425696],"59f2e00721137845.js":[425696,432320],"fb489729ee2e6385.js":[432320,433872],"1a6108d8949381e5.js":[433872,434592],"8a215617ed237473.js":[434592,435496],"16421edadb2fb243.js":[435496,451344],"01261cd2db2fb243.js":[451344,461472],"38864d23db2fb243.js":[461472,463912],"37f69b83ed237473.js":[463912,468208],"146a6fb6db2fb243.js":[468208,470840],"f2dcb781db2fb243.js":[470840,472800],"0801a3e5db2fb243.js":[472800,475864],"91312eeedb2fb243.js":[475864,477632],"7a207b7fdb2fb243.js":[477632,480840],"3b6504b7ed237473.js":[480840,483488],"20ca4040ed237473.js":[483488,500048],"68dcb23fdb2fb243.js":[500048,502904],"72af042eed237473.js":[502904,504272],"240b3df2db2fb243.js":[504272,505632],"e9b30599db2fb243.js":[505632,507328],"ff5f8efded237473.js":[507328,509288],"2fedd8d8ed237473.js":[509288,512440],"ea698191db2fb243.js":[512440,514376],"27d4b716db2fb243.js":[514376,517952],"d7aa69dbdb2fb243.js":[517952,525632],"f77f61acdb2fb243.js":[525632,528336],"95efb346ed237473.js":[528336,530768],"817825cadb2fb243.js":[530768,534808],"bafeb408db2fb243.js":[534808,537064],"56a56173db2fb243.js":[537064,540432],"b7953906db2fb243.js":[540432,542120],"479d2c59db2fb243.js":[542120,545888],"76f7b8ffdb2fb243.js":[545888,548736],"d97349c3db2fb243.js":[548736,550328],"b72c85c5db2fb243.js":[550328,553496],"7b6e32b2db2fb243.js":[553496,555400],"71a30454db2fb243.js":[555400,559376],"e7db54a9db2fb243.js":[559376,560616],"aeda560adb2fb243.js":[560616,562240],"87362b4eed237473.js":[562240,563520],"5586a11b21137845.js":[563520,567528],"9ac01a63c7eb21f6.js":[567528,574952],"5475fe4cb6142426.js":[574952,575808],"227c3384b6142426.js":[575808,578920],"510e81c3b6142426.js":[578920,580128],"d1c3f9ceb6142426.js":[580128,581616],"8e20b5f1b6142426.js":[581616,583288],"36631fd8b6142426.js":[583288,584728],"daaf293eb6142426.js":[584728,592352],"310819608524be10.js":[592352,593464],"f434313b9a2960f3.js":[593464,594296],"a17ba878b6142426.js":[594296,595024],"3261b6e7d9bcdfe7.js":[595024,596704],"6f413501a64d3c66.js":[596704,598816],"7b44115bb6142426.js":[598816,601056],"63450b39b6142426.js":[601056,602200],"679e71b4b6142426.js":[602200,609440],"d3dc197eaf35b0ed.js":[609440,610144],"e3d61160b6142426.js":[610144,612488],"01779f58b6142426.js":[612488,614472],"40fcb2acb6142426.js":[614472,615624],"91d7a96a59e3a5c1.js":[615624,617864],"25e63cfe11e1cf2f.js":[617864,625488],"d5a4c40511e1cf2f.js":[625488,627712],"d5999af5a64d3c66.js":[627712,632136],"9ebac25611e1cf2f.js":[632136,634320],"5c9e03cfa932150e.js":[634320,635464],"e21651cca932150e.js":[635464,636504],"fbecb1a3fbb51954.js":[636504,637360],"baedcd890746b45d.js":[637360,638336],"1c9c43b75c914323.js":[638336,639088],"cbe654779a2960f3.js":[639088,639928],"5bb5e783c7eb21f6.js":[639928,640728],"16523bc011e1cf2f.js":[640728,647528],"4de5acacc7eb21f6.js":[647528,650184],"7daeadeb11e1cf2f.js":[650184,651088],"21a859f311e1cf2f.js":[651088,652120],"f48ef24411e1cf2f.js":[652120,653096],"6c0723c111e1cf2f.js":[653096,654632],"5dfe04f957a510ce.js":[654632,655904],"f4680d3c11e1cf2f.js":[655904,657304],"a567b3ef11e1cf2f.js":[657304,659832],"50221e7711e1cf2f.js":[659832,664688],"d771579911e1cf2f.js":[664688,665896],"44a41bb611e1cf2f.js":[665896,666608],"8c33a61211e1cf2f.js":[666608,667776],"f7ab948711e1cf2f.js":[667776,668448],"03a60fda11e1cf2f.js":[668448,669104],"c2ba311011e1cf2f.js":[669104,669960],"f138e94cd9bcdfe7.js":[669960,671416],"ceeb921002a7330b.js":[671416,672232],"8aa7847102a7330b.js":[672232,673112],"5816381c02a7330b.js":[673112,673872],"893410ef02a7330b.js":[673872,674808],"78a3d8d821137845.js":[674808,677624],"f19ce16321137845.js":[677624,682832],"f682f2e91ba2ddcb.js":[682832,704592],"88a0f006949381e5.js":[704592,708088],"5f4fe0a552aacd1d.js":[708088,724280],"cc0ef42aa64d3c66.js":[724280,732096],"22e182f78524be10.js":[732096,737360],"ad517b9b9a2960f3.js":[737360,742912],"c0246a7052aacd1d.js":[742912,760464],"e9fb4171fd38840b.js":[760464,769248],"0e6a1023771cdbcf.js":[769248,771344],"7cd7f652c7eb21f6.js":[771344,775296],"76b3a14ec7eb21f6.js":[775296,776872],"f282b8bc949381e5.js":[776872,778288],"9bbd50c5af35b0ed.js":[778288,781168],"5d0c035f52aacd1d.js":[781168,784208],"b0e99c11f1ce72b1.js":[784208,786976],"0ca982f452aacd1d.js":[786976,787816],"50eee1bc1ba2ddcb.js":[787816,788952],"e4534bd1f87b83de.js":[788952,790064],"e20bb2601ba2ddcb.js":[790064,792128],"6d9c090252aacd1d.js":[792128,793008],"f1a0bc081ba2ddcb.js":[793008,793776],"06f4ce0d1ba2ddcb.js":[793776,794656],"c908709252aacd1d.js":[794656,795536],"70796505a932150e.js":[795536,800080],"88bec4439a2960f3.js":[800080,802024],"fd5625a29a2960f3.js":[802024,804408],"809ab6e1949381e5.js":[804408,805944],"926fa5604d6a6a14.js":[805944,807824],"1660e80f52aacd1d.js":[807824,811280],"4f1388bc949381e5.js":[811280,812088],"53621745949381e5.js":[812088,815424],"a0854ecd8c7f5525.js":[815424,816104],"ec85d716c7eb21f6.js":[816104,825112],"648f7837c7eb21f6.js":[825112,831184],"e9a53755c7eb21f6.js":[831184,835984],"25d07481f1ce72b1.js":[835984,843312],"4f9b9352c7eb21f6.js":[843312,844328],"00ec0a4ac7eb21f6.js":[844328,848304],"ee8a18fa6c7a370e.js":[848304,858496],"2baf262be0592814.js":[858496,859504],"908c5de2a932150e.js":[859504,864832],"9219df72c7eb21f6.js":[864832,868128],"2eaf7e166c7a370e.js":[868128,880248],"1708e59e57a510ce.js":[880248,888688],"36eb8b353d1e01a1.js":[888688,896208],"cb05bdac3d1e01a1.js":[896208,903424],"8d1c95413d1e01a1.js":[903424,905464],"d0b525a60beb919a.js":[905464,906656],"88a43cb2077984c2.js":[906656,909280],"d9eb5315d9bcdfe7.js":[909280,911104],"c81c20cf077984c2.js":[911104,912512],"f3f94c01077984c2.js":[912512,915256],"f877fd8f077984c2.js":[915256,916760],"d67657490beb919a.js":[916760,917576],"15f983c53d1e01a1.js":[917576,918416],"7d28f4db01b480c5.js":[918416,920640],"b950ca893d1e01a1.js":[920640,929592],"c09009503d1e01a1.js":[929592,931896],"3e48418c01b480c5.js":[931896,936912],"967614978524be10.js":[936912,939184],"12d60f9c0beb919a.js":[939184,939912],"c1d1074e8524be10.js":[939912,940608],"d9f248e38524be10.js":[940608,943144],"457159da8524be10.js":[943144,946152],"431623ce6c7a370e.js":[946152,950928],"a9a1e6116c7a370e.js":[950928,951720],"48d6546a771cdbcf.js":[951720,953264],"303d41904d6a6a14.js":[953264,958344],"35d595931400c1e7.js":[958344,959288],"6ac22420356a0c41.js":[959288,966592],"c01472bbaf35b0ed.js":[966592,967368],"4efa5737af35b0ed.js":[967368,968400],"a791679aaf35b0ed.js":[968400,969344],"137fe466af35b0ed.js":[969344,971184],"171e2c90af35b0ed.js":[971184,972520],"8fb4a211949381e5.js":[972520,974288],"858848e5ce065572.js":[974288,979912],"6d49cb6ce4fab372.js":[979912,987816],"db954cf2e4fab372.js":[987816,993928],"80eac2f77dc6c4fb.js":[993928,995288],"8b2392bfbd969993.js":[995288,996088],"2d75d81c3ff63b4e.js":[996088,997256],"45dca0b4af35b0ed.js":[997256,997984],"dadb112f08fde66d.js":[997984,1001360],"7faced77949381e5.js":[1001360,1003264],"b3812c2d1ba2ddcb.js":[1003264,1039336],"37f52a0a949381e5.js":[1039336,1041040],"8489aa71ee2e6385.js":[1041040,1049816],"5589f9e2ee2e6385.js":[1049816,1066064],"9d69a11ffd38840b.js":[1066064,1069384],"33932d95fd38840b.js":[1069384,1088720],"ee06b94baf35b0ed.js":[1088720,1090200],"46767505ce308a65.js":[1090200,1091096],"d067d798ce308a65.js":[1091096,1092232],"33acb45ace308a65.js":[1092232,1093112],"af2fe88dce308a65.js":[1093112,1101320],"d1e4a4a557a510ce.js":[1101320,1107152],"d63fb86857a510ce.js":[1107152,1112496],"489907f657a510ce.js":[1112496,1115424],"996deff8fd38840b.js":[1115424,1116544],"4824765afd38840b.js":[1116544,1118992],"b141bd40fd38840b.js":[1118992,1120696],"220f42e8fd38840b.js":[1120696,1121512],"06c9b585fd38840b.js":[1121512,1122640],"f6398abcfd38840b.js":[1122640,1123440],"47b16f9bfd38840b.js":[1123440,1124808],"b3585cddfd38840b.js":[1124808,1125576],"dcf5cd5efd38840b.js":[1125576,1127072],"b4ff685f02a7330b.js":[1127072,1127816],"8770cd990beb919a.js":[1127816,1129480],"27b19b9bb6142426.js":[1129480,1131480],"f32121ecb6142426.js":[1131480,1133648],"9ff8af2de98b8cc5.js":[1133648,1134984],"c729e23d59e3a5c1.js":[1134984,1136016],"22683689b6142426.js":[1136016,1137544],"d3b6a9f5077984c2.js":[1137544,1139128],"3bcbbd4bb6142426.js":[1139128,1146328],"98fc0f11817e0f11.js":[1146328,1155480],"b4b41d96949381e5.js":[1155480,1156968],"242f6bb0817e0f11.js":[1156968,1160616],"65f2ffb5949381e5.js":[1160616,1162144],"1c3cbfbd8b91a4fe.js":[1162144,1163952],"21ef77aa1ba2ddcb.js":[1163952,1166040],"c846e85e1ba2ddcb.js":[1166040,1169824],"681b83d41ba2ddcb.js":[1169824,1176560],"34c994041ba2ddcb.js":[1176560,1179608],"5ff5c329949381e5.js":[1179608,1180544],"c0c8be03949381e5.js":[1180544,1182232],"d1e5bedf1ba2ddcb.js":[1182232,1183176],"419932021ba2ddcb.js":[1183176,1184112],"eea1de8c949381e5.js":[1184112,1185152],"243952fd1ba2ddcb.js":[1185152,1186792],"07094fd5ce308a65.js":[1186792,1192608],"85b041121ba2ddcb.js":[1192608,1213936],"b4b52bf81ba2ddcb.js":[1213936,1219464],"e082023b949381e5.js":[1219464,1220352],"c5fe6bab2d619b95.js":[1220352,1223488],"575bc411949381e5.js":[1223488,1224392],"98132f07af35b0ed.js":[1224392,1225280],"e899472eaf35b0ed.js":[1225280,1226168],"ce8d1a519a2960f3.js":[1226168,1228208],"f1c2c2d0e8691b4c.js":[1228208,1229312],"908768a6e8691b4c.js":[1229312,1231128],"1ac10ddce8691b4c.js":[1231128,1232768],"caf3869de8691b4c.js":[1232768,1238400],"c215058ae8691b4c.js":[1238400,1242744],"5f40bbf1e8691b4c.js":[1242744,1243816],"e2fb2a95fbb51954.js":[1243816,1245464],"e36ee6acfbb51954.js":[1245464,1247232],"bfadab00fbb51954.js":[1247232,1249256],"7321134a1400c1e7.js":[1249256,1255312],"62afed70fbb51954.js":[1255312,1256056],"09c542391400c1e7.js":[1256056,1261688],"eeb5c6621400c1e7.js":[1261688,1265544],"dab59a991400c1e7.js":[1265544,1266616],"1b8119c13d1e01a1.js":[1266616,1273744],"d6c0b1dd3d1e01a1.js":[1273744,1276056],"f6ba20841400c1e7.js":[1276056,1277488],"d06141a41400c1e7.js":[1277488,1279976],"b539e5b91400c1e7.js":[1279976,1285712],"fb6466131400c1e7.js":[1285712,1287560],"ea3223ecfbb51954.js":[1287560,1291272],"a0e276e9fbb51954.js":[1291272,1292768],"15e5c22c1400c1e7.js":[1292768,1293976],"cd6764d41400c1e7.js":[1293976,1296248],"d43938161400c1e7.js":[1296248,1297000],"a3d29f7bc2cce000.js":[1297000,1303784],"e5eb9756fbb51954.js":[1303784,1305464],"d38d90881400c1e7.js":[1305464,1311264],"ad620de91400c1e7.js":[1311264,1313168],"31b071041400c1e7.js":[1313168,1314200],"5ab5f584fbb51954.js":[1314200,1315824],"45b64ad31400c1e7.js":[1315824,1321864],"a71f247cfbb51954.js":[1321864,1324032],"0f6cc3b51400c1e7.js":[1324032,1325856],"afcda76ee8691b4c.js":[1325856,1328592],"1034a6a5e8691b4c.js":[1328592,1330024],"55e13bf5e8691b4c.js":[1330024,1331784],"f8ea7e512d619b95.js":[1331784,1332456],"d5d075cb2d619b95.js":[1332456,1336992],"4bb485dc2d619b95.js":[1336992,1337768],"5344cf562d619b95.js":[1337768,1344368],"f832ff312d619b95.js":[1344368,1345616],"cd8cb1482d619b95.js":[1345616,1346680],"6d7e57212d619b95.js":[1346680,1348136],"0a918aaa2d619b95.js":[1348136,1350384],"174beff38524be10.js":[1350384,1352976],"d13d88213d1e01a1.js":[1352976,1354328],"07464f8fcd33734d.js":[1354328,1356912],"a4e0b7710beb919a.js":[1356912,1359952],"9aeb47fbce308a65.js":[1359952,1360888],"1a0c131efbb51954.js":[1360888,1361720],"362b7daecd33734d.js":[1361720,1363496],"126a2c42cd33734d.js":[1363496,1365336],"a413658b0beb919a.js":[1365336,1368928],"0d5131910beb919a.js":[1368928,1370368],"734c39d90beb919a.js":[1370368,1377984],"2cdec8c10beb919a.js":[1377984,1378704],"c6c0218f0beb919a.js":[1378704,1380936],"c3e816d90beb919a.js":[1380936,1382072],"9430084a0beb919a.js":[1382072,1389304],"d69ad0130beb919a.js":[1389304,1391640],"129b135f0beb919a.js":[1391640,1393616],"6a4fd5b90beb919a.js":[1393616,1394760],"7243614ff87b83de.js":[1394760,1396648],"4b46b8df1400c1e7.js":[1396648,1397392],"65ac56991400c1e7.js":[1397392,1398824],"4e2ea5931400c1e7.js":[1398824,1406440],"2756168e1400c1e7.js":[1406440,1407160],"43c074a31400c1e7.js":[1407160,1409392],"0bfeafdc1400c1e7.js":[1409392,1410528],"744ea3ee1400c1e7.js":[1410528,1417760],"20cd53501400c1e7.js":[1417760,1420096],"69fedb0d1400c1e7.js":[1420096,1422072],"38a958701400c1e7.js":[1422072,1423216],"ebc43ddba932150e.js":[1423216,1424024],"807c9aaaa64d3c66.js":[1424024,1426216],"4cf4eaaea64d3c66.js":[1426216,1427656],"25d2b36da64d3c66.js":[1427656,1435280],"7657ea5aa64d3c66.js":[1435280,1436000],"b9374310a64d3c66.js":[1436000,1438240],"0a0afce0a64d3c66.js":[1438240,1439384],"26b09845a64d3c66.js":[1439384,1446624],"b0e510e9a64d3c66.js":[1446624,1448960],"88c9ff51a64d3c66.js":[1448960,1450944],"99b69639a64d3c66.js":[1450944,1452096],"5eb2f40cf1ce72b1.js":[1452096,1454360],"97346bdfc2cce000.js":[1454360,1455792],"5e8defe1f1ce72b1.js":[1455792,1463408],"5df29895f1ce72b1.js":[1463408,1464120],"25fce45df1ce72b1.js":[1464120,1466352],"076adc79f1ce72b1.js":[1466352,1467488],"8fa945c2f1ce72b1.js":[1467488,1474720],"8f60a52ef1ce72b1.js":[1474720,1477048],"a919158bf1ce72b1.js":[1477048,1479024],"d326aca2f1ce72b1.js":[1479024,1480168],"c4c264cbf1ce72b1.js":[1480168,1481856],"7b7060b9f1ce72b1.js":[1481856,1483304],"91d8ee8cf1ce72b1.js":[1483304,1490928],"caa9a902f1ce72b1.js":[1490928,1491656],"d4281284f1ce72b1.js":[1491656,1493904],"f151d072f1ce72b1.js":[1493904,1495048],"d9597abdf1ce72b1.js":[1495048,1502288],"c72b15b8f1ce72b1.js":[1502288,1504632],"f4076e92f1ce72b1.js":[1504632,1506616],"16cb801ef1ce72b1.js":[1506616,1507776],"e73c699be8691b4c.js":[1507776,1509496],"358d2e2ae8691b4c.js":[1509496,1510944],"6fdd3302e8691b4c.js":[1510944,1518568],"f3a0dfc9e8691b4c.js":[1518568,1519296],"38e244bce8691b4c.js":[1519296,1521544],"5d30ae55e8691b4c.js":[1521544,1522688],"6353a824e8691b4c.js":[1522688,1529928],"fd7b0817e8691b4c.js":[1529928,1532272],"adb0223be8691b4c.js":[1532272,1534256],"f93f5307e8691b4c.js":[1534256,1535416],"287ae67c59e3a5c1.js":[1535416,1536616],"dcfe10692d619b95.js":[1536616,1538112],"f46ca05ea932150e.js":[1538112,1541648],"72a18ab62d619b95.js":[1541648,1544736],"4a4a66ad2d619b95.js":[1544736,1547288],"525c528a2d619b95.js":[1547288,1554248],"09f56bba2d619b95.js":[1554248,1558592],"73749ff62d619b95.js":[1558592,1559664],"b4ca00e42d619b95.js":[1559664,1562544],"579dd6972d619b95.js":[1562544,1564376],"f4dd36762d619b95.js":[1564376,1567000],"56271f402d619b95.js":[1567000,1568184],"74c8bb762d619b95.js":[1568184,1569096],"41ddba172d619b95.js":[1569096,1570464],"f67e7b772d619b95.js":[1570464,1571496],"4cd749a62d619b95.js":[1571496,1572168],"8c7c7e592d619b95.js":[1572168,1575192],"5b3ec4d52d619b95.js":[1575192,1576816],"3b71d89be8691b4c.js":[1576816,1579952],"6fa6690a8524be10.js":[1579952,1591056],"0e38bb5711e1cf2f.js":[1591056,1596112],"5bc08f0711e1cf2f.js":[1596112,1598480],"9edd688b11e1cf2f.js":[1598480,1599464],"e8215ce211e1cf2f.js":[1599464,1601144],"f0f81b9de8691b4c.js":[1601144,1603496],"be514d59e8691b4c.js":[1603496,1605784],"af889eafe8691b4c.js":[1605784,1606520],"621d0d5ce8691b4c.js":[1606520,1607408],"4f3fc729e8691b4c.js":[1607408,1608200],"5c4665c1e8691b4c.js":[1608200,1609280],"23238f32e8691b4c.js":[1609280,1610680],"0dccc119e8691b4c.js":[1610680,1612440],"f2e2bc6211e1cf2f.js":[1612440,1614008],"e2b9dae011e1cf2f.js":[1614008,1614880],"0b8f297d1ba2ddcb.js":[1614880,1616456],"da1192d31ba2ddcb.js":[1616456,1618032],"b9535dca1ba2ddcb.js":[1618032,1619456],"9cfb9ab61ba2ddcb.js":[1619456,1622200],"98d0d17c356a0c41.js":[1622200,1625192],"ad269f31949381e5.js":[1625192,1626336],"6cbfadbe1ba2ddcb.js":[1626336,1627056],"7e7113481ba2ddcb.js":[1627056,1627784],"be377c2c1ba2ddcb.js":[1627784,1628760],"31b35a391ba2ddcb.js":[1628760,1632616],"f1ba2406949381e5.js":[1632616,1633448],"adc162f3128f1cfa.js":[1633448,1634248],"4a1371ce59e3a5c1.js":[1634248,1635184],"00d95df159e3a5c1.js":[1635184,1636184],"7b5c8cd8fbb51954.js":[1636184,1637096],"a3ec0fc6817e0f11.js":[1637096,1646496],"7e5891cda932150e.js":[1646496,1651000],"188801a2949381e5.js":[1651000,1651744],"e1ecc1361ba2ddcb.js":[1651744,1652704],"9076369d1ba2ddcb.js":[1652704,1655896],"8bec415f1ba2ddcb.js":[1655896,1657024],"6a4d70581ba2ddcb.js":[1657024,1657976],"ba01d9f21ba2ddcb.js":[1657976,1658696],"fad4a1921ba2ddcb.js":[1658696,1660496],"c9fa1cb51ba2ddcb.js":[1660496,1661664],"d0a718581ba2ddcb.js":[1661664,1662408],"58264a881ba2ddcb.js":[1662408,1663368],"6a4b826e1ba2ddcb.js":[1663368,1664728],"6743457e1ba2ddcb.js":[1664728,1665504],"c3f2e4c01ba2ddcb.js":[1665504,1666976],"cd756d2b1ba2ddcb.js":[1666976,1669208],"8b707fd4817e0f11.js":[1669208,1685272],"759849f21ba2ddcb.js":[1685272,1689248],"4ac67086356a0c41.js":[1689248,1690448],"b31ad0d2356a0c41.js":[1690448,1691440],"e8de3f34356a0c41.js":[1691440,1693072],"6e28fa2b356a0c41.js":[1693072,1693976],"a5ce31d0356a0c41.js":[1693976,1695152],"669e9c648b91a4fe.js":[1695152,1695832],"bf5e439b8b91a4fe.js":[1695832,1697440],"38082ab68b91a4fe.js":[1697440,1700824],"81ef571bfbb51954.js":[1700824,1701768],"941b56a1fbb51954.js":[1701768,1702624],"62ff661efbb51954.js":[1702624,1703400],"5e630567fbb51954.js":[1703400,1704192],"a31a3ada8b91a4fe.js":[1704192,1707640],"21fa45f78b91a4fe.js":[1707640,1711840],"a4183fb9356a0c41.js":[1711840,1712584],"e44b8022356a0c41.js":[1712584,1713416],"a143b6fd52aacd1d.js":[1713416,1717576],"eb87d550949381e5.js":[1717576,1721992],"3fb160fbdb2fb243.js":[1721992,1723712],"05936d9c5c914323.js":[1723712,1726464],"5e349e8c5c914323.js":[1726464,1727352],"dc449859a932150e.js":[1727352,1728792],"70703a6759e3a5c1.js":[1728792,1729616],"3637d58c5c914323.js":[1729616,1731288],"520782f2a932150e.js":[1731288,1737656],"9b8e3b415c914323.js":[1737656,1739152],"1f5caf60949381e5.js":[1739152,1740296],"83bf543152aacd1d.js":[1740296,1742560],"e7471089356a0c41.js":[1742560,1748768],"37b21ae3356a0c41.js":[1748768,1750112],"2fdfc567db2fb243.js":[1750112,1752280],"18de0fccd9bcdfe7.js":[1752280,1755056],"72dffb7b3d1e01a1.js":[1755056,1756568],"19e040933d1e01a1.js":[1756568,1760040],"6bdb4716a64d3c66.js":[1760040,1762664],"fa253311a64d3c66.js":[1762664,1766136],"2cb783d4c2cce000.js":[1766136,1768488],"a79a5c74c2cce000.js":[1768488,1769936],"67c47388c2cce000.js":[1769936,1777568],"3c89d0c5c2cce000.js":[1777568,1778304],"296582c0c2cce000.js":[1778304,1780552],"0dc7ba78c2cce000.js":[1780552,1781704],"1bce9804c2cce000.js":[1781704,1788952],"5a9016f7c2cce000.js":[1788952,1791296],"260fea07c2cce000.js":[1791296,1793288],"9ce50ca2c2cce000.js":[1793288,1794448],"4e5d838fc2cce000.js":[1794448,1796216],"5f542b7da64d3c66.js":[1796216,1796952],"a3dd8cd9d9bcdfe7.js":[1796952,1798208],"588790b7d9bcdfe7.js":[1798208,1801672],"a490cdfae8691b4c.js":[1801672,1802592],"7d1dd094949381e5.js":[1802592,1803704],"3ad75907356a0c41.js":[1803704,1808128],"ab77ca87356a0c41.js":[1808128,1811568],"9fda784c077984c2.js":[1811568,1815200],"a33c5999949381e5.js":[1815200,1819352],"a3e56d3f1ba2ddcb.js":[1819352,1820272],"58b1f9cccd33734d.js":[1820272,1821888],"252052051ba2ddcb.js":[1821888,1831040],"c3bec0ad1ba2ddcb.js":[1831040,1832192],"97d0f3f21ba2ddcb.js":[1832192,1835424],"69a2a907949381e5.js":[1835424,1836528],"dbd230ef11e1cf2f.js":[1836528,1837408],"36b3c46911e1cf2f.js":[1837408,1840616],"09f2dbdd11e1cf2f.js":[1840616,1844080],"b6935e58c2cce000.js":[1844080,1845528],"fb66db5e11e1cf2f.js":[1845528,1847288],"7abe78e211e1cf2f.js":[1847288,1849216],"fec8139f52aacd1d.js":[1849216,1850104],"3912d55c1ba2ddcb.js":[1850104,1851040],"1b6c4485949381e5.js":[1851040,1852096],"693fc05a1ba2ddcb.js":[1852096,1853016],"41b3481ea932150e.js":[1853016,1853968],"ca025078a932150e.js":[1853968,1857472],"f5ea6968a932150e.js":[1857472,1858432],"b3cf4f200beb919a.js":[1858432,1865312],"89df9b2f0beb919a.js":[1865312,1867952],"05c82a06e0592814.js":[1867952,1870704],"7e061b471ba2ddcb.js":[1870704,1871792],"121de30b52aacd1d.js":[1871792,1874216],"69b5fa5e8cf3d03c.js":[1874216,1877808],"5fbaedba5c914323.js":[1877808,1880080],"fbad95b752aacd1d.js":[1880080,1881064],"2526b2cf1ba2ddcb.js":[1881064,1882328],"3f9e04c11ba2ddcb.js":[1882328,1883280],"8bf676b01ba2ddcb.js":[1883280,1884240],"20d5b9131ba2ddcb.js":[1884240,1885536],"e4e5dd521ba2ddcb.js":[1885536,1887840],"b2d89feb1ba2ddcb.js":[1887840,1889688],"7313efdd1ba2ddcb.js":[1889688,1890840],"64b6a6ae949381e5.js":[1890840,1893896],"f20343211ba2ddcb.js":[1893896,1895776],"3726a8d11ba2ddcb.js":[1895776,1897000],"9c87c60e1ba2ddcb.js":[1897000,1898040],"0fa51a001ba2ddcb.js":[1898040,1899576],"09c8bc071ba2ddcb.js":[1899576,1902552],"90c12e2f949381e5.js":[1902552,1903608],"c5ed417aaf35b0ed.js":[1903608,1907840],"aadcfa38e8691b4c.js":[1907840,1908544],"d991b67fe8691b4c.js":[1908544,1910320],"47859fcee8691b4c.js":[1910320,1912488],"b084fe29e8691b4c.js":[1912488,1917024],"1e10760ae8691b4c.js":[1917024,1923368],"d48cfe65356a0c41.js":[1923368,1924600],"474ac529e8691b4c.js":[1924600,1926088],"7f0222006c7a370e.js":[1926088,1932008],"91abc741e3076823.js":[1932008,1932800],"c8e87753e3076823.js":[1932800,1936784],"0f158498e3076823.js":[1936784,1946296],"9f83d8b7077984c2.js":[1946296,1947536],"f3168c813d1e01a1.js":[1947536,1948920],"f20877fee3076823.js":[1948920,1950576],"767ebe1221137845.js":[1950576,1954752],"35dafc0e06132a24.js":[1954752,1958808],"781623e606132a24.js":[1958808,1964680],"efd4c2643460ae95.js":[1964680,1965448],"89d97ac73460ae95.js":[1965448,1967352],"76cef8d83460ae95.js":[1967352,1969696],"c9a511643460ae95.js":[1969696,1971632],"127f9faa3460ae95.js":[1971632,1978000],"0e21c04e3460ae95.js":[1978000,1985512],"4226ae833460ae95.js":[1985512,1987144],"488858353460ae95.js":[1987144,1989128],"98c864573460ae95.js":[1989128,2002536],"0925ff663460ae95.js":[2002536,2004856],"e8db9a2c3460ae95.js":[2004856,2005752],"c978f4573460ae95.js":[2005752,2006704],"86564d453460ae95.js":[2006704,2007608],"db3e21f93460ae95.js":[2007608,2008744],"b8195d3c3460ae95.js":[2008744,2012280],"13a3bada3460ae95.js":[2012280,2017168],"a00591a03460ae95.js":[2017168,2018312],"607b449b3460ae95.js":[2018312,2019624],"c14882d63460ae95.js":[2019624,2021024],"ad1e7cc73460ae95.js":[2021024,2022232],"a16357b23460ae95.js":[2022232,2023040],"6ff419533460ae95.js":[2023040,2026912],"4fbb041e3460ae95.js":[2026912,2028976],"6840c6573460ae95.js":[2028976,2030304],"956307ba3460ae95.js":[2030304,2031128],"54f955193460ae95.js":[2031128,2032424],"8372ca6406132a24.js":[2032424,2058568],"be245bd506132a24.js":[2058568,2064096],"7080511d06132a24.js":[2064096,2071240],"c88d1606949381e5.js":[2071240,2074008],"6eb6e109949381e5.js":[2074008,2075128],"3c4d8db0949381e5.js":[2075128,2077224],"b682994fe8691b4c.js":[2077224,2087080],"849fb652e8691b4c.js":[2087080,2102992],"40138051e8691b4c.js":[2102992,2105712],"22b5013d06132a24.js":[2105712,2115048],"98b2676f06132a24.js":[2115048,2124616],"4763366206132a24.js":[2124616,2131832],"fad9001706132a24.js":[2131832,2147888],"ff1904d306132a24.js":[2147888,2155344],"1ab3008a06132a24.js":[2155344,2161384],"7443e4f606132a24.js":[2161384,2167416],"e305797106132a24.js":[2167416,2187264],"ee5c1c7a93efec47.js":[2187264,2190464],"1cd052defbb51954.js":[2190464,2191208],"121c3df4fbb51954.js":[2191208,2193688],"32176f518cf3d03c.js":[2193688,2198040],"5284bc3a8cf3d03c.js":[2198040,2199472],"fa8239718cf3d03c.js":[2199472,2207080],"b722f39f8cf3d03c.js":[2207080,2207792],"ffb37eda8cf3d03c.js":[2207792,2210024],"1c7d46588cf3d03c.js":[2210024,2211152],"c61852408cf3d03c.js":[2211152,2218376],"094c3f908cf3d03c.js":[2218376,2220704],"d976cf1f8cf3d03c.js":[2220704,2222672],"43d09d5d8cf3d03c.js":[2222672,2223816],"5ad925a8fbb51954.js":[2223816,2229240],"00f40964e98b8cc5.js":[2229240,2230840],"66e222caee2e6385.js":[2230840,2254560],"b6f27b6be98b8cc5.js":[2254560,2255256],"4618d653ee2e6385.js":[2255256,2259392],"47ec6770ee2e6385.js":[2259392,2260616],"a6a949ece98b8cc5.js":[2260616,2262264],"3a7392a3ee2e6385.js":[2262264,2265344],"02f40d0eee2e6385.js":[2265344,2266328],"b4cc7341ee2e6385.js":[2266328,2276136],"64573053ee2e6385.js":[2276136,2278296],"2681d3c8ee2e6385.js":[2278296,2280536],"4527f91eee2e6385.js":[2280536,2281608],"af5182edee2e6385.js":[2281608,2282896],"357b6f0ee98b8cc5.js":[2282896,2284664],"a3b901f1fbb51954.js":[2284664,2291880],"68f8d820c2cce000.js":[2291880,2292608],"77af7b4406132a24.js":[2292608,2299312],"a47e2aa3949381e5.js":[2299312,2306272],"ec680920356a0c41.js":[2306272,2307160],"349004d3128f1cfa.js":[2307160,2308224],"3394276ffbb51954.js":[2308224,2309320],"75f46fd1fbb51954.js":[2309320,2310760],"d4c94d24fbb51954.js":[2310760,2318384],"df83f1eafbb51954.js":[2318384,2319112],"6f6227e8fbb51954.js":[2319112,2321352],"157f0240fbb51954.js":[2321352,2322496],"b0e00bb7fbb51954.js":[2322496,2329736],"75bc6186fbb51954.js":[2329736,2332072],"c0685e86fbb51954.js":[2332072,2334056],"05705441fbb51954.js":[2334056,2335208],"74cfa005128f1cfa.js":[2335208,2337408],"4cf82aa2128f1cfa.js":[2337408,2338768],"29a03864128f1cfa.js":[2338768,2344216],"8b30eb97128f1cfa.js":[2344216,2345040],"21dfeef1128f1cfa.js":[2345040,2348872],"63265540128f1cfa.js":[2348872,2350736],"3938328d128f1cfa.js":[2350736,2352656],"dde510de128f1cfa.js":[2352656,2353816],"27d52b6806132a24.js":[2353816,2365608],"bda5990206132a24.js":[2365608,2376528],"2e87891906132a24.js":[2376528,2384672],"1040f9fa06132a24.js":[2384672,2397520],"48fde36306132a24.js":[2397520,2406432],"aafaa0e906132a24.js":[2406432,2441976],"016a056406132a24.js":[2441976,2457376],"bffbd98b06132a24.js":[2457376,2465056],"31b2a77a06132a24.js":[2465056,2472144],"9b838a6606132a24.js":[2472144,2474544],"6c092b1706132a24.js":[2474544,2480128],"2acd579a3460ae95.js":[2480128,2483616],"7c4a091812e6bcd5.js":[2483616,2485160],"3f9305f906132a24.js":[2485160,2490672],"211cf6d606132a24.js":[2490672,2496336],"9b9978a006132a24.js":[2496336,2501912],"b4cbae7006132a24.js":[2501912,2512992],"3b4503bc06132a24.js":[2512992,2518568],"3749407606132a24.js":[2518568,2526736],"df709e9206132a24.js":[2526736,2532160],"fc8b68dd06132a24.js":[2532160,2538664],"dac6ae0a06132a24.js":[2538664,2541960],"3f96921306132a24.js":[2541960,2547232],"4cc95a5f06132a24.js":[2547232,2550280],"58bbc95506132a24.js":[2550280,2557048],"8a7730d006132a24.js":[2557048,2562032],"90bace7c06132a24.js":[2562032,2567096],"9c7546aa06132a24.js":[2567096,2572024],"9e98839a06132a24.js":[2572024,2577008],"eb5776c406132a24.js":[2577008,2583136],"b16e767b06132a24.js":[2583136,2590912],"1402b44d06132a24.js":[2590912,2614656],"787d1d0706132a24.js":[2614656,2620544],"540ffc4506132a24.js":[2620544,2625856],"0dda87a106132a24.js":[2625856,2629240],"1ec71cb506132a24.js":[2629240,2631384],"bee7caaa06132a24.js":[2631384,2649688],"2920597906132a24.js":[2649688,2654192],"52c3b1e906132a24.js":[2654192,2657920],"452a749f06132a24.js":[2657920,2662336],"62bfb32a06132a24.js":[2662336,2663960],"f9a061a406132a24.js":[2663960,2672488],"4799e81906132a24.js":[2672488,2676744],"b4f355d306132a24.js":[2676744,2681544],"6622e44806132a24.js":[2681544,2685056],"bbc26c4106132a24.js":[2685056,2689416],"747348fc06132a24.js":[2689416,2696184],"42a1f8aa06132a24.js":[2696184,2699704],"0666bfa506132a24.js":[2699704,2706408],"e6c6e2af06132a24.js":[2706408,2710496],"4277d63d06132a24.js":[2710496,2716776],"2a26b58c06132a24.js":[2716776,2722928],"6785f48d06132a24.js":[2722928,2731592],"cda3908f06132a24.js":[2731592,2743720],"9859139f06132a24.js":[2743720,2750824],"f72e208f06132a24.js":[2750824,2758728],"598f7ab11ba2ddcb.js":[2758728,2766296],"08ef1d59949381e5.js":[2766296,2767008],"d42ce918b6142426.js":[2767008,2770136],"7f384b52b6142426.js":[2770136,2771752],"679bccc11400c1e7.js":[2771752,2773048],"43d2b09f1ba2ddcb.js":[2773048,2777824],"3c080774949381e5.js":[2777824,2780064],"27518be41ba2ddcb.js":[2780064,2781760],"4aae3448949381e5.js":[2781760,2784816],"6076b72e1ba2ddcb.js":[2784816,2786312],"b2fe52551ba2ddcb.js":[2786312,2788696],"a7bac1fee98b8cc5.js":[2788696,2792392],"4e325868cad2f3bb.js":[2792392,2794944],"882db2add9bcdfe7.js":[2794944,2796880],"9a014426f87b83de.js":[2796880,2807968],"f73ae395f87b83de.js":[2807968,2808736],"1821f1bfe0592814.js":[2808736,2811736],"5ab31df9f87b83de.js":[2811736,2813528],"b381bf0cf87b83de.js":[2813528,2816232],"5878489cf87b83de.js":[2816232,2817032],"13f0fec5f87b83de.js":[2817032,2817760],"820f3de3d9bcdfe7.js":[2817760,2819928],"7d583c234d6a6a14.js":[2819928,2820848],"5565fe34d9bcdfe7.js":[2820848,2856760],"1914dbb2fbafa855.js":[2856760,2858848],"32a2beeefbafa855.js":[2858848,2862728],"56c93cbafbafa855.js":[2862728,2865272],"8686ec7257a510ce.js":[2865272,2866656],"95fc48d357a510ce.js":[2866656,2868840],"c8f49194fbafa855.js":[2868840,2875696],"0e09b4d2077984c2.js":[2875696,2877560],"6d9fd6dece308a65.js":[2877560,2879816],"9a261ed2ce308a65.js":[2879816,2883648],"d858e057ce308a65.js":[2883648,2890736],"0d47ec06ce308a65.js":[2890736,2893208],"9bb6f5b7ce308a65.js":[2893208,2894888],"f9bec914ce308a65.js":[2894888,2898736],"8b117f56ce308a65.js":[2898736,2901216],"92564acace308a65.js":[2901216,2904776],"dfb8d7e3ce308a65.js":[2904776,2908912],"c2190d34ce308a65.js":[2908912,2912648],"f5957635ce308a65.js":[2912648,2914728],"e03b47b1ce308a65.js":[2914728,2916536],"18951e35ce308a65.js":[2916536,2918304],"7fb916c7fbafa855.js":[2918304,2919176],"68106521fbafa855.js":[2919176,2920272],"b1170bf4fbafa855.js":[2920272,2921128],"1a873dd1fbafa855.js":[2921128,2922816],"307a74a7fbafa855.js":[2922816,2925968],"64ee5934fbafa855.js":[2925968,2929416],"b5e0bef6ce308a65.js":[2929416,2932800],"594f7958ce308a65.js":[2932800,2936536],"121fd348ce308a65.js":[2936536,2938512],"2cd79643ce308a65.js":[2938512,2940336],"c9e834aace308a65.js":[2940336,2943904],"e54fa112ce308a65.js":[2943904,2945472],"d761ab0dce308a65.js":[2945472,2948288],"9fa73207ce308a65.js":[2948288,2952440],"429e27efce308a65.js":[2952440,2955688],"129c1446ce308a65.js":[2955688,2962464],"31d6f4e0ce308a65.js":[2962464,2964016],"7621059057a510ce.js":[2964016,2966904],"509ddac28c7f5525.js":[2966904,2972600],"a09369d6cad2f3bb.js":[2972600,2973912],"359f538faf35b0ed.js":[2973912,2977152],"3ff7bd714d6a6a14.js":[2977152,2979432],"a8e220cf077984c2.js":[2979432,2980752],"11ca72366c7a370e.js":[2980752,2983536],"c1a7b4f36c7a370e.js":[2983536,2984208],"1cc48b7b8b91a4fe.js":[2984208,2989128],"238a0444f1ce72b1.js":[2989128,2991104],"abb4dc66f1ce72b1.js":[2991104,2995144],"cd3a04aea64d3c66.js":[2995144,2998424],"fc898c2359e3a5c1.js":[2998424,3000696],"09c39ac1a64d3c66.js":[3000696,3001432],"1b738f76fbafa855.js":[3001432,3002320],"fe4e93befbafa855.js":[3002320,3003328],"04db5827fbafa855.js":[3003328,3004312],"d1589778fbafa855.js":[3004312,3005152],"5c160e6dfbafa855.js":[3005152,3005880],"986fa5ddfbafa855.js":[3005880,3006704],"ecc102eefbafa855.js":[3006704,3007456],"435dc933fbafa855.js":[3007456,3008336],"32047b2efbafa855.js":[3008336,3009152],"95c6f803fbafa855.js":[3009152,3010384],"664fe414f1ce72b1.js":[3010384,3011168],"1e407f0f4d6a6a14.js":[3011168,3012288],"f68771f19a2960f3.js":[3012288,3013720],"57a62156d9bcdfe7.js":[3013720,3015496],"1ed7397fd9bcdfe7.js":[3015496,3017584],"6d62016ccd33734d.js":[3017584,3018480],"d8eedb62cd33734d.js":[3018480,3020304],"d5d7cd03cd33734d.js":[3020304,3022464],"e0f22c51cd33734d.js":[3022464,3023744],"174b1bcbcd33734d.js":[3023744,3025416],"1df92752d9bcdfe7.js":[3025416,3026848],"3bb5524d57a510ce.js":[3026848,3029968],"5a6e545d0746b45d.js":[3029968,3035304],"33c084430746b45d.js":[3035304,3037568],"edb535fd0746b45d.js":[3037568,3040664],"86c0758ccad2f3bb.js":[3040664,3041584],"cb7dcc6e0746b45d.js":[3041584,3046608],"4b4881870746b45d.js":[3046608,3047344],"f1680f010746b45d.js":[3047344,3048144],"3bdd926c4d6a6a14.js":[3048144,3050168],"f43d86c60746b45d.js":[3050168,3051632],"c7d7a038f1ce72b1.js":[3051632,3052456],"b27007d80746b45d.js":[3052456,3053256],"baa9408c5c914323.js":[3053256,3055208],"13bbf0300746b45d.js":[3055208,3056376],"b3a666c50746b45d.js":[3056376,3065696],"e3eada9e0746b45d.js":[3065696,3066672],"40f01e150746b45d.js":[3066672,3069240],"616b07a40746b45d.js":[3069240,3069968],"eab827250746b45d.js":[3069968,3070696],"a99ad3400746b45d.js":[3070696,3071448],"c0a4f42f0746b45d.js":[3071448,3072176],"de906c750746b45d.js":[3072176,3072912],"3884a16e0746b45d.js":[3072912,3073656],"fcf0144c0746b45d.js":[3073656,3074384],"11da83700746b45d.js":[3074384,3075112],"a394beef0746b45d.js":[3075112,3075840],"e16289a00746b45d.js":[3075840,3076568],"306171600746b45d.js":[3076568,3077312],"cd9588490746b45d.js":[3077312,3078056],"18a39f3b0746b45d.js":[3078056,3078808],"5b4976b20746b45d.js":[3078808,3079552],"c45901b90746b45d.js":[3079552,3080280],"b0cc07fc0746b45d.js":[3080280,3081008],"ea3528f80746b45d.js":[3081008,3081736],"40610bc80746b45d.js":[3081736,3082480],"357216340746b45d.js":[3082480,3083224],"77a396320746b45d.js":[3083224,3083960],"68c2b1c90746b45d.js":[3083960,3084704],"683d7175bc5c122c.js":[3084704,3085984],"eee9a2c50746b45d.js":[3085984,3086832],"fd31ed8e0746b45d.js":[3086832,3087856],"a7f97d830746b45d.js":[3087856,3089064],"41404bdd0746b45d.js":[3089064,3089792],"0d5a811857a510ce.js":[3089792,3090544],"cfd5723157a510ce.js":[3090544,3092536],"4aca19d8d9bcdfe7.js":[3092536,3094504],"41198c8fd9bcdfe7.js":[3094504,3096440],"e7f18520c7eb21f6.js":[3096440,3098248],"607d3ee6d9bcdfe7.js":[3098248,3099408],"805c7a5ad9bcdfe7.js":[3099408,3101344],"c6ec15a9d9bcdfe7.js":[3101344,3106280],"cd71944fd9bcdfe7.js":[3106280,3109352],"f0cfaa57f87b83de.js":[3109352,3112160],"ac0ab1f88524be10.js":[3112160,3114272],"4e677cd81ba2ddcb.js":[3114272,3115952],"3fd239891ba2ddcb.js":[3115952,3118408],"21a2ce66e8691b4c.js":[3118408,3119112],"6262d37d06132a24.js":[3119112,3123376],"ed5c3aa706132a24.js":[3123376,3128200],"2af6a05706132a24.js":[3128200,3132728],"fa255d1106132a24.js":[3132728,3140216],"97a983a706132a24.js":[3140216,3149888],"48b98b3e06132a24.js":[3149888,3156504],"cd25658606132a24.js":[3156504,3161272],"ca970e5406132a24.js":[3161272,3168016],"7ecbbb3906132a24.js":[3168016,3173248],"6f15317a06132a24.js":[3173248,3178440],"307ad0bc06132a24.js":[3178440,3183664],"fd0592bf06132a24.js":[3183664,3188824],"62d64ab706132a24.js":[3188824,3199256],"839806c806132a24.js":[3199256,3210096],"161b85d4949381e5.js":[3210096,3211376],"1069c208949381e5.js":[3211376,3212112],"f885375c949381e5.js":[3212112,3213032],"eb363ae506132a24.js":[3213032,3222800],"60b6b8f406132a24.js":[3222800,3227984],"e39303e106132a24.js":[3227984,3233880],"e5e82bf506132a24.js":[3233880,3238952],"4552e0d206132a24.js":[3238952,3243968],"0f2ecacf06132a24.js":[3243968,3247240],"a629d20806132a24.js":[3247240,3253488],"3185d50906132a24.js":[3253488,3255768],"9c0a694d06132a24.js":[3255768,3270544],"df15b03d06132a24.js":[3270544,3275568],"5c44282f06132a24.js":[3275568,3283208],"9cc09c1f16687672.js":[3283208,3296800],"ca5ee7e11ba2ddcb.js":[3296800,3301424],"03e300d09a2960f3.js":[3301424,3303168],"010723158524be10.js":[3303168,3306096],"a3b7717aee2e6385.js":[3306096,3307024],"da37eb313d1e01a1.js":[3307024,3310208],"0167ba29d78182e9.js":[3310208,3312920],"a2656d8c817e0f11.js":[3312920,3314024],"d2ea6de5d78182e9.js":[3314024,3315256],"f9db893f817e0f11.js":[3315256,3316720],"4ac8b70c16687672.js":[3316720,3321328],"ce13359816687672.js":[3321328,3327000],"91d2f66316687672.js":[3327000,3332032],"010590a816687672.js":[3332032,3337128],"6e897b0816687672.js":[3337128,3341272],"0a4c712a16687672.js":[3341272,3345920],"df2525ca16687672.js":[3345920,3351624],"c4c783e216687672.js":[3351624,3356480],"af98803016687672.js":[3356480,3362672],"8f4d0bda16687672.js":[3362672,3367360],"aafe1a3716687672.js":[3367360,3373944],"3ed1b92d16687672.js":[3373944,3378400],"78dd1fed16687672.js":[3378400,3383008],"0bfd8ac316687672.js":[3383008,3387480],"9e6335f416687672.js":[3387480,3391384],"d78ec56c16687672.js":[3391384,3401776],"9e01492b16687672.js":[3401776,3406632],"65c4bfb5e8691b4c.js":[3406632,3407336],"4fce261016687672.js":[3407336,3411984],"e9b3862416687672.js":[3411984,3415576],"d5dadd3916687672.js":[3415576,3422440],"c7d7bfdc16687672.js":[3422440,3426792],"aa16c52916687672.js":[3426792,3431288],"cf2f2f5016687672.js":[3431288,3437120],"3c94f95f16687672.js":[3437120,3440496],"586e9fe916687672.js":[3440496,3445104],"e1d7a77316687672.js":[3445104,3452528],"c21ff77a16687672.js":[3452528,3455824],"9216ffbf16687672.js":[3455824,3460056],"9a06862516687672.js":[3460056,3464400],"0fcd430616687672.js":[3464400,3470688],"06ab0b0416687672.js":[3470688,3476808],"c285913c16687672.js":[3476808,3485976],"c40bf0e416687672.js":[3485976,3494496],"05022a9d16687672.js":[3494496,3501024],"adf4f46f16687672.js":[3501024,3506152],"bf75042c949381e5.js":[3506152,3507648],"a0ff100416687672.js":[3507648,3512008],"403bc9c316687672.js":[3512008,3516192],"9cd6b3ae16687672.js":[3516192,3527184],"0ed518fd16687672.js":[3527184,3532128],"0c6a693716687672.js":[3532128,3536960],"32ff6abd16687672.js":[3536960,3541968],"6a4651911ba2ddcb.js":[3541968,3556080],"f1892f651ba2ddcb.js":[3556080,3563336],"cb79e25c817e0f11.js":[3563336,3576640],"5ce6c7d7949381e5.js":[3576640,3577664],"1864b024ee2e6385.js":[3577664,3580192],"e8d5779216687672.js":[3580192,3583616],"5fe1da2316687672.js":[3583616,3590464],"db4e4bd216687672.js":[3590464,3594384],"cfdf33d316687672.js":[3594384,3597568],"0f3f36bd16687672.js":[3597568,3603320],"24f36e3f16687672.js":[3603320,3608192],"1af975ae16687672.js":[3608192,3613072],"357105c416687672.js":[3613072,3617680],"5e45d54b16687672.js":[3617680,3621728],"3779a6e316687672.js":[3621728,3625632],"4321123316687672.js":[3625632,3629352],"1b704bb116687672.js":[3629352,3634072],"83b72aeb16687672.js":[3634072,3637672],"fa163c0216687672.js":[3637672,3641952],"06b75f8516687672.js":[3641952,3655960],"a7834a4716687672.js":[3655960,3660040],"1f093e2e16687672.js":[3660040,3666880],"e2a34c0f16687672.js":[3666880,3672144],"c99bb1a516687672.js":[3672144,3676792],"5ad804b916687672.js":[3676792,3681360],"0bd8334216687672.js":[3681360,3691856],"cb946d6816687672.js":[3691856,3699112],"11f0665a16687672.js":[3699112,3708264],"8502e0b716687672.js":[3708264,3714840],"c04bc3b116687672.js":[3714840,3716608],"5e22684516687672.js":[3716608,3724288],"9b7d372616687672.js":[3724288,3733920],"0559a28516687672.js":[3733920,3737968],"f2050d8416687672.js":[3737968,3746976],"ee6e988c16687672.js":[3746976,3749248],"bb12169f16687672.js":[3749248,3752656],"82f6ea8416687672.js":[3752656,3757736],"8433d3ee16687672.js":[3757736,3766344],"30dbbc32949381e5.js":[3766344,3769656],"338ab305949381e5.js":[3769656,3771120],"4d0b94f916687672.js":[3771120,3776712],"68415d2416687672.js":[3776712,3779936],"e915e84316687672.js":[3779936,3782136],"9300f11f16687672.js":[3782136,3785424],"78a7c49816687672.js":[3785424,3789160],"2da696e016687672.js":[3789160,3797296],"70e24ecf16687672.js":[3797296,3805104],"99b9077f16687672.js":[3805104,3807288],"2a33b1f0949381e5.js":[3807288,3813112],"dda64da58c7f5525.js":[3813112,3813792],"bf2a19b08c7f5525.js":[3813792,3814488],"87be401f16687672.js":[3814488,3819144],"39747a3816687672.js":[3819144,3823856],"19c3745f16687672.js":[3823856,3828536],"60e73e0116687672.js":[3828536,3834248],"85ce3b2c16687672.js":[3834248,3840184],"01a565fe16687672.js":[3840184,3846184],"d478126d16687672.js":[3846184,3852704],"c71b3f7d16687672.js":[3852704,3859408],"dc04213c16687672.js":[3859408,3870912],"d0118ead16687672.js":[3870912,3880744],"c4f7ba2516687672.js":[3880744,3917040],"8bc675e216687672.js":[3917040,3922120],"f33cf37916687672.js":[3922120,3935520],"12ef983616687672.js":[3935520,3940216],"ac16088216687672.js":[3940216,3947384],"1621565e949381e5.js":[3947384,3949072],"107ddad116687672.js":[3949072,3955408],"66fb950215ce5db0.js":[3955408,3960640],"7dc16ab815ce5db0.js":[3960640,3967704],"1cfa8d2315ce5db0.js":[3967704,3974176],"0754d6e915ce5db0.js":[3974176,3976624],"de7afdda15ce5db0.js":[3976624,3983792],"86442adc15ce5db0.js":[3983792,3988416],"62f7e79215ce5db0.js":[3988416,3994040],"9ff680d315ce5db0.js":[3994040,4000840],"af2a330115ce5db0.js":[4000840,4008440],"95d8147915ce5db0.js":[4008440,4016464],"e11993b915ce5db0.js":[4016464,4021968],"6929eb4615ce5db0.js":[4021968,4025224],"dee59d2c15ce5db0.js":[4025224,4030728],"a062315115ce5db0.js":[4030728,4036048],"0297c4d415ce5db0.js":[4036048,4041312],"8f3c85bd949381e5.js":[4041312,4045728],"ad8956838c7f5525.js":[4045728,4046424],"70525f28d78182e9.js":[4046424,4047248],"62d6832ed78182e9.js":[4047248,4049808],"6c8447e8d78182e9.js":[4049808,4051192],"cc3387e48c7f5525.js":[4051192,4051904],"05b65a49949381e5.js":[4051904,4053072],"cca2da75949381e5.js":[4053072,4054648],"b94f7047c7eb21f6.js":[4054648,4056368],"73cb19998c7f5525.js":[4056368,4058872],"40851e228c7f5525.js":[4058872,4059560],"eb91786b8c7f5525.js":[4059560,4062016],"551dbdcb8c7f5525.js":[4062016,4063112],"ae1975548c7f5525.js":[4063112,4064272],"91484f78e8691b4c.js":[4064272,4065256],"fb815e588c7f5525.js":[4065256,4066608],"f40fd3778c7f5525.js":[4066608,4067464],"bcf6b459d78182e9.js":[4067464,4068248],"0a0530428c7f5525.js":[4068248,4069032],"85624f7f8c7f5525.js":[4069032,4069728],"30dc9a12356a0c41.js":[4069728,4072256],"c17708ae8c7f5525.js":[4072256,4072952],"e0f8ef3e8c7f5525.js":[4072952,4073648],"8e359666817e0f11.js":[4073648,4074712],"842368938c7f5525.js":[4074712,4075424],"6a2c169c8c7f5525.js":[4075424,4076120],"e9e65b308c7f5525.js":[4076120,4076808],"db7c60668c7f5525.js":[4076808,4077496],"44c5e6a98c7f5525.js":[4077496,4078184],"9a304e25d78182e9.js":[4078184,4080336],"95d171158c7f5525.js":[4080336,4081024],"4b88082b8c7f5525.js":[4081024,4084440],"a56ec2a68c7f5525.js":[4084440,4087760],"06768f258c7f5525.js":[4087760,4088448],"027807fad78182e9.js":[4088448,4090000],"4b4829838c7f5525.js":[4090000,4090688],"264000c8d78182e9.js":[4090688,4093328],"abb2f21fd78182e9.js":[4093328,4096648],"2838c0608c7f5525.js":[4096648,4097336],"94bc3f26d78182e9.js":[4097336,4099728],"482c7e32d78182e9.js":[4099728,4103048],"57a7b1eb8c7f5525.js":[4103048,4103760],"a750b47fc7eb21f6.js":[4103760,4107104],"552572048c7f5525.js":[4107104,4107816],"a0495db88c7f5525.js":[4107816,4108504],"c902f5438c7f5525.js":[4108504,4109200],"dec050458c7f5525.js":[4109200,4109880],"0ceb57cd8c7f5525.js":[4109880,4110576],"6c84989115ce5db0.js":[4110576,4116752],"d36c11bf15ce5db0.js":[4116752,4127464],"5394aef215ce5db0.js":[4127464,4130440],"f9ea4eca15ce5db0.js":[4130440,4132968],"2367ef9715ce5db0.js":[4132968,4143384],"6e75318515ce5db0.js":[4143384,4154408],"b8961a5115ce5db0.js":[4154408,4158048],"e294db1915ce5db0.js":[4158048,4181632],"711f49d515ce5db0.js":[4181632,4186704],"593de69515ce5db0.js":[4186704,4195336],"20a518f515ce5db0.js":[4195336,4201248],"0497279c15ce5db0.js":[4201248,4209752],"fefbbe0815ce5db0.js":[4209752,4222712],"731795da15ce5db0.js":[4222712,4224208],"02b72e5215ce5db0.js":[4224208,4230776],"7d8eaded15ce5db0.js":[4230776,4238320],"6737a38115ce5db0.js":[4238320,4243088],"a492b56215ce5db0.js":[4243088,4249056],"c10fc2c815ce5db0.js":[4249056,4253864],"c3d2cdb215ce5db0.js":[4253864,4258888],"5fe1f34d15ce5db0.js":[4258888,4265784],"43b2128915ce5db0.js":[4265784,4271016],"43a3e7e615ce5db0.js":[4271016,4274520],"0099b9b715ce5db0.js":[4274520,4281536],"8f61adfc15ce5db0.js":[4281536,4290384],"052615c615ce5db0.js":[4290384,4295912],"8943de3b15ce5db0.js":[4295912,4300856],"7263a73515ce5db0.js":[4300856,4306408],"df66d5f815ce5db0.js":[4306408,4313040],"10515cf415ce5db0.js":[4313040,4318448],"c4d12dc015ce5db0.js":[4318448,4324920],"dd97066415ce5db0.js":[4324920,4330688],"7f6c08ea15ce5db0.js":[4330688,4335864],"616a1aca15ce5db0.js":[4335864,4342816],"bb5a2f2c15ce5db0.js":[4342816,4348480],"1a5c812115ce5db0.js":[4348480,4353496],"cb7314d615ce5db0.js":[4353496,4359048],"4df19d9215ce5db0.js":[4359048,4361880],"b1b5003415ce5db0.js":[4361880,4364976],"34f5f1d615ce5db0.js":[4364976,4387344],"b645253e15ce5db0.js":[4387344,4393632],"fd5624ca52aacd1d.js":[4393632,4397968],"7889555015ce5db0.js":[4397968,4403056],"eb4699fc15ce5db0.js":[4403056,4407040],"1f4c349b15ce5db0.js":[4407040,4413072],"c0b750d715ce5db0.js":[4413072,4418848],"93c9f8c315ce5db0.js":[4418848,4429064],"054b431715ce5db0.js":[4429064,4432584],"df21937315ce5db0.js":[4432584,4442320],"9f3a91eb15ce5db0.js":[4442320,4446304],"b1cbb5b13460ae95.js":[4446304,4454232],"8847fd1115ce5db0.js":[4454232,4457432],"ac56d33b15ce5db0.js":[4457432,4463296],"360fa10915ce5db0.js":[4463296,4468136],"046bae4115ce5db0.js":[4468136,4473872],"7d8528cc15ce5db0.js":[4473872,4475464],"7896528115ce5db0.js":[4475464,4479616],"1963e50815ce5db0.js":[4479616,4482064],"25e8cfb915ce5db0.js":[4482064,4486824],"a11a711b15ce5db0.js":[4486824,4490632],"f0fb774a15ce5db0.js":[4490632,4493136],"528ad25615ce5db0.js":[4493136,4496624],"2dc31956949381e5.js":[4496624,4500672],"3e63ce129a2960f3.js":[4500672,4502248],"167b19a08b91a4fe.js":[4502248,4503992],"e32ad74a9a2960f3.js":[4503992,4507656],"a8e52eca949381e5.js":[4507656,4509096],"a0e941ed15ce5db0.js":[4509096,4515352],"5c9c6c9615ce5db0.js":[4515352,4520456],"0526816f15ce5db0.js":[4520456,4523512],"e226fbcd15ce5db0.js":[4523512,4535544],"d3a2a6ee949381e5.js":[4535544,4540632],"850827d915ce5db0.js":[4540632,4543896],"008deaa715ce5db0.js":[4543896,4549288],"49a57ba315ce5db0.js":[4549288,4553800],"e792d50115ce5db0.js":[4553800,4560624],"10f253d615ce5db0.js":[4560624,4565864],"84c03627949381e5.js":[4565864,4569136],"ab3fd97c949381e5.js":[4569136,4570888],"032bf14ee8691b4c.js":[4570888,4574792],"45aabd2e15ce5db0.js":[4574792,4580168],"e6006355949381e5.js":[4580168,4588464],"aa9e68be15ce5db0.js":[4588464,4589960],"a7bd86bb15ce5db0.js":[4589960,4594936],"04e8a37615ce5db0.js":[4594936,4601592],"faab67fc15ce5db0.js":[4601592,4617176],"6f77466915ce5db0.js":[4617176,4625472],"d7b658ee15ce5db0.js":[4625472,4637024],"d5d3d21c15ce5db0.js":[4637024,4642384],"a8e41f5415ce5db0.js":[4642384,4647056],"9bd2717d15ce5db0.js":[4647056,4650776],"4573d6af15ce5db0.js":[4650776,4656976],"ce410be315ce5db0.js":[4656976,4661544],"aa7d3a3815ce5db0.js":[4661544,4667560],"0dcd25c993efec47.js":[4667560,4673080],"d2779cd993efec47.js":[4673080,4681968],"23fe29d593efec47.js":[4681968,4688424],"cac7583693efec47.js":[4688424,4689568],"9631423421137845.js":[4689568,4692656],"8710956e21137845.js":[4692656,4696512],"c419249c21137845.js":[4696512,4702416],"095f603921137845.js":[4702416,4706216],"ea05511721137845.js":[4706216,4708424],"862393ee21137845.js":[4708424,4716320],"775b70b321137845.js":[4716320,4721272]},"version":"3.2.5"} \ No newline at end of file diff --git a/node_modules/.cache/esm/01261cd2db2fb243.js b/node_modules/.cache/esm/01261cd2db2fb243.js new file mode 100644 index 0000000000000..c5617ee870d50 --- /dev/null +++ b/node_modules/.cache/esm/01261cd2db2fb243.js @@ -0,0 +1,384 @@ +"use strict"; +var es5 = require("./es5"); +var canEvaluate = typeof navigator == "undefined"; + +var errorObj = {e: {}}; +var tryCatchTarget; +var globalObject = typeof self !== "undefined" ? self : + typeof window !== "undefined" ? window : + typeof global !== "undefined" ? global : + this !== undefined ? this : null; + +function tryCatcher() { + try { + var target = tryCatchTarget; + tryCatchTarget = null; + return target.apply(this, arguments); + } catch (e) { + errorObj.e = e; + return errorObj; + } +} +function tryCatch(fn) { + tryCatchTarget = fn; + return tryCatcher; +} + +var inherits = function(Child, Parent) { + var hasProp = {}.hasOwnProperty; + + function T() { + this.constructor = Child; + this.constructor$ = Parent; + for (var propertyName in Parent.prototype) { + if (hasProp.call(Parent.prototype, propertyName) && + propertyName.charAt(propertyName.length-1) !== "$" + ) { + this[propertyName + "$"] = Parent.prototype[propertyName]; + } + } + } + T.prototype = Parent.prototype; + Child.prototype = new T(); + return Child.prototype; +}; + + +function isPrimitive(val) { + return val == null || val === true || val === false || + typeof val === "string" || typeof val === "number"; + +} + +function isObject(value) { + return typeof value === "function" || + typeof value === "object" && value !== null; +} + +function maybeWrapAsError(maybeError) { + if (!isPrimitive(maybeError)) return maybeError; + + return new Error(safeToString(maybeError)); +} + +function withAppended(target, appendee) { + var len = target.length; + var ret = new Array(len + 1); + var i; + for (i = 0; i < len; ++i) { + ret[i] = target[i]; + } + ret[i] = appendee; + return ret; +} + +function getDataPropertyOrDefault(obj, key, defaultValue) { + if (es5.isES5) { + var desc = Object.getOwnPropertyDescriptor(obj, key); + + if (desc != null) { + return desc.get == null && desc.set == null + ? desc.value + : defaultValue; + } + } else { + return {}.hasOwnProperty.call(obj, key) ? obj[key] : undefined; + } +} + +function notEnumerableProp(obj, name, value) { + if (isPrimitive(obj)) return obj; + var descriptor = { + value: value, + configurable: true, + enumerable: false, + writable: true + }; + es5.defineProperty(obj, name, descriptor); + return obj; +} + +function thrower(r) { + throw r; +} + +var inheritedDataKeys = (function() { + var excludedPrototypes = [ + Array.prototype, + Object.prototype, + Function.prototype + ]; + + var isExcludedProto = function(val) { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (excludedPrototypes[i] === val) { + return true; + } + } + return false; + }; + + if (es5.isES5) { + var getKeys = Object.getOwnPropertyNames; + return function(obj) { + var ret = []; + var visitedKeys = Object.create(null); + while (obj != null && !isExcludedProto(obj)) { + var keys; + try { + keys = getKeys(obj); + } catch (e) { + return ret; + } + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (visitedKeys[key]) continue; + visitedKeys[key] = true; + var desc = Object.getOwnPropertyDescriptor(obj, key); + if (desc != null && desc.get == null && desc.set == null) { + ret.push(key); + } + } + obj = es5.getPrototypeOf(obj); + } + return ret; + }; + } else { + var hasProp = {}.hasOwnProperty; + return function(obj) { + if (isExcludedProto(obj)) return []; + var ret = []; + + /*jshint forin:false */ + enumeration: for (var key in obj) { + if (hasProp.call(obj, key)) { + ret.push(key); + } else { + for (var i = 0; i < excludedPrototypes.length; ++i) { + if (hasProp.call(excludedPrototypes[i], key)) { + continue enumeration; + } + } + ret.push(key); + } + } + return ret; + }; + } + +})(); + +var thisAssignmentPattern = /this\s*\.\s*\S+\s*=/; +function isClass(fn) { + try { + if (typeof fn === "function") { + var keys = es5.names(fn.prototype); + + var hasMethods = es5.isES5 && keys.length > 1; + var hasMethodsOtherThanConstructor = keys.length > 0 && + !(keys.length === 1 && keys[0] === "constructor"); + var hasThisAssignmentAndStaticMethods = + thisAssignmentPattern.test(fn + "") && es5.names(fn).length > 0; + + if (hasMethods || hasMethodsOtherThanConstructor || + hasThisAssignmentAndStaticMethods) { + return true; + } + } + return false; + } catch (e) { + return false; + } +} + +function toFastProperties(obj) { + /*jshint -W027,-W055,-W031*/ + function FakeConstructor() {} + FakeConstructor.prototype = obj; + var receiver = new FakeConstructor(); + function ic() { + return typeof receiver.foo; + } + ic(); + ic(); + return obj; + eval(obj); +} + +var rident = /^[a-z$_][a-z$_0-9]*$/i; +function isIdentifier(str) { + return rident.test(str); +} + +function filledRange(count, prefix, suffix) { + var ret = new Array(count); + for(var i = 0; i < count; ++i) { + ret[i] = prefix + i + suffix; + } + return ret; +} + +function safeToString(obj) { + try { + return obj + ""; + } catch (e) { + return "[no string representation]"; + } +} + +function isError(obj) { + return obj instanceof Error || + (obj !== null && + typeof obj === "object" && + typeof obj.message === "string" && + typeof obj.name === "string"); +} + +function markAsOriginatingFromRejection(e) { + try { + notEnumerableProp(e, "isOperational", true); + } + catch(ignore) {} +} + +function originatesFromRejection(e) { + if (e == null) return false; + return ((e instanceof Error["__BluebirdErrorTypes__"].OperationalError) || + e["isOperational"] === true); +} + +function canAttachTrace(obj) { + return isError(obj) && es5.propertyIsWritable(obj, "stack"); +} + +var ensureErrorObject = (function() { + if (!("stack" in new Error())) { + return function(value) { + if (canAttachTrace(value)) return value; + try {throw new Error(safeToString(value));} + catch(err) {return err;} + }; + } else { + return function(value) { + if (canAttachTrace(value)) return value; + return new Error(safeToString(value)); + }; + } +})(); + +function classString(obj) { + return {}.toString.call(obj); +} + +function copyDescriptors(from, to, filter) { + var keys = es5.names(from); + for (var i = 0; i < keys.length; ++i) { + var key = keys[i]; + if (filter(key)) { + try { + es5.defineProperty(to, key, es5.getDescriptor(from, key)); + } catch (ignore) {} + } + } +} + +var asArray = function(v) { + if (es5.isArray(v)) { + return v; + } + return null; +}; + +if (typeof Symbol !== "undefined" && Symbol.iterator) { + var ArrayFrom = typeof Array.from === "function" ? function(v) { + return Array.from(v); + } : function(v) { + var ret = []; + var it = v[Symbol.iterator](); + var itResult; + while (!((itResult = it.next()).done)) { + ret.push(itResult.value); + } + return ret; + }; + + asArray = function(v) { + if (es5.isArray(v)) { + return v; + } else if (v != null && typeof v[Symbol.iterator] === "function") { + return ArrayFrom(v); + } + return null; + }; +} + +var isNode = typeof process !== "undefined" && + classString(process).toLowerCase() === "[object process]"; + +var hasEnvVariables = typeof process !== "undefined" && + typeof process.env !== "undefined"; + +function env(key) { + return hasEnvVariables ? process.env[key] : undefined; +} + +function getNativePromise() { + if (typeof Promise === "function") { + try { + var promise = new Promise(function(){}); + if ({}.toString.call(promise) === "[object Promise]") { + return Promise; + } + } catch (e) {} + } +} + +function domainBind(self, cb) { + return self.bind(cb); +} + +var ret = { + isClass: isClass, + isIdentifier: isIdentifier, + inheritedDataKeys: inheritedDataKeys, + getDataPropertyOrDefault: getDataPropertyOrDefault, + thrower: thrower, + isArray: es5.isArray, + asArray: asArray, + notEnumerableProp: notEnumerableProp, + isPrimitive: isPrimitive, + isObject: isObject, + isError: isError, + canEvaluate: canEvaluate, + errorObj: errorObj, + tryCatch: tryCatch, + inherits: inherits, + withAppended: withAppended, + maybeWrapAsError: maybeWrapAsError, + toFastProperties: toFastProperties, + filledRange: filledRange, + toString: safeToString, + canAttachTrace: canAttachTrace, + ensureErrorObject: ensureErrorObject, + originatesFromRejection: originatesFromRejection, + markAsOriginatingFromRejection: markAsOriginatingFromRejection, + classString: classString, + copyDescriptors: copyDescriptors, + hasDevTools: typeof chrome !== "undefined" && chrome && + typeof chrome.loadTimes === "function", + isNode: isNode, + hasEnvVariables: hasEnvVariables, + env: env, + global: globalObject, + getNativePromise: getNativePromise, + domainBind: domainBind +}; +ret.isRecentNode = ret.isNode && (function() { + var version = process.versions.node.split(".").map(Number); + return (version[0] === 0 && version[1] > 10) || (version[0] > 0); +})(); + +if (ret.isNode) ret.toFastProperties(process); + +try {throw new Error(); } catch (e) {ret.lastLineError = e;} +module.exports = ret; diff --git a/node_modules/fstream/.npmignore b/node_modules/fstream/.npmignore deleted file mode 100644 index 494272a81afb6..0000000000000 --- a/node_modules/fstream/.npmignore +++ /dev/null @@ -1,5 +0,0 @@ -.*.swp -node_modules/ -examples/deep-copy/ -examples/path/ -examples/filter-copy/ diff --git a/node_modules/fstream/lib/writer.js b/node_modules/fstream/lib/writer.js index 140e449e06dd5..3f10547820fad 100644 --- a/node_modules/fstream/lib/writer.js +++ b/node_modules/fstream/lib/writer.js @@ -147,7 +147,7 @@ Writer.prototype._stat = function (current) { // if it's a type change, then we need to clobber or error. // if it's not a type change, then let the impl take care of it. - if (currentType !== self.type) { + if (currentType !== self.type || self.type === 'File' && current.nlink > 1) { return rimraf(self._path, function (er) { if (er) return self.error(er) self._old = null diff --git a/node_modules/fstream/package.json b/node_modules/fstream/package.json index 25418b6709e64..041a4342a7164 100644 --- a/node_modules/fstream/package.json +++ b/node_modules/fstream/package.json @@ -1,8 +1,8 @@ { "_from": "fstream@^1.0.0", - "_id": "fstream@1.0.11", + "_id": "fstream@1.0.12", "_inBundle": false, - "_integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "_integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "_location": "/fstream", "_phantomChildren": {}, "_requested": { @@ -16,13 +16,13 @@ "fetchSpec": "^1.0.0" }, "_requiredBy": [ - "/node-gyp", - "/node-gyp/tar" + "/npm-lifecycle/node-gyp", + "/npm-lifecycle/tar" ], - "_resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "_shasum": "5c1fb1f117477114f0632a0eb4b71b3cb0fd3171", + "_resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "_shasum": "4e8ba8ee2d48be4f7d0de505455548eae5932045", "_spec": "fstream@^1.0.0", - "_where": "/Users/rebecca/code/npm/node_modules/node-gyp", + "_where": "/home/hugh/Development/github.com/npm/cli/node_modules/npm-lifecycle/node_modules/node-gyp", "author": { "name": "Isaac Z. Schlueter", "email": "i@izs.me", @@ -58,5 +58,5 @@ "scripts": { "test": "standard && tap examples/*.js" }, - "version": "1.0.11" + "version": "1.0.12" } diff --git a/node_modules/node-gyp/CHANGELOG.md b/node_modules/node-gyp/CHANGELOG.md index 33bbfad5dec9a..05167c92dc640 100644 --- a/node_modules/node-gyp/CHANGELOG.md +++ b/node_modules/node-gyp/CHANGELOG.md @@ -1,3 +1,11 @@ +v4.0.0 2019-04-24 +================= + +* [[`ceed5cbe10`](https://github.com/nodejs/node-gyp/commit/ceed5cbe10)] - **deps**: updated tar package version to 4.4.8 (Pobegaylo Maksim) [#1713](https://github.com/nodejs/node-gyp/pull/1713) +* [[`374519e066`](https://github.com/nodejs/node-gyp/commit/374519e066)] - **(SEMVER-MAJOR)** Upgrade to tar v3 (isaacs) [#1212](https://github.com/nodejs/node-gyp/pull/1212) +* [[`e6699d13cd`](https://github.com/nodejs/node-gyp/commit/e6699d13cd)] - **test**: fix addon test for Node.js 12 and V8 7.4 (Richard Lau) [#1705](https://github.com/nodejs/node-gyp/pull/1705) +* [[`0c6bf530a0`](https://github.com/nodejs/node-gyp/commit/0c6bf530a0)] - **lib**: use print() for python version detection (GreenAddress) [#1534](https://github.com/nodejs/node-gyp/pull/1534) + v3.8.0 2018-08-09 ================= diff --git a/node_modules/node-gyp/lib/configure.js b/node_modules/node-gyp/lib/configure.js index 35e6787d1f3e3..a42abe59724c7 100644 --- a/node_modules/node-gyp/lib/configure.js +++ b/node_modules/node-gyp/lib/configure.js @@ -448,7 +448,7 @@ PythonFinder.prototype = { }, checkPythonVersion: function checkPythonVersion () { - var args = ['-c', 'import sys; print "%s.%s.%s" % sys.version_info[:3];'] + var args = ['-c', 'import sys; print("%s.%s.%s" % sys.version_info[:3]);'] var env = extend({}, this.env) env.TERM = 'dumb' diff --git a/node_modules/node-gyp/lib/install.js b/node_modules/node-gyp/lib/install.js index cb84972e18325..8a615dfb38880 100644 --- a/node_modules/node-gyp/lib/install.js +++ b/node_modules/node-gyp/lib/install.js @@ -20,10 +20,8 @@ var fs = require('graceful-fs') , rm = require('rimraf') , path = require('path') , crypto = require('crypto') - , zlib = require('zlib') , log = require('npmlog') , semver = require('semver') - , fstream = require('fstream') , request = require('request') , mkdir = require('mkdirp') , processRelease = require('./process-release') @@ -148,41 +146,33 @@ function install (fs, gyp, argv, callback) { var tarPath = gyp.opts.tarball var 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 () { - var name = this.path.substring(devDir.length + 1) - var isValid = valid(name) - if (name === '' && this.type === 'Directory') { - // the first directory entry is ok - return true - } + function isValid (path, entry) { + var isValid = valid(path) if (isValid) { - log.verbose('extracted file from tarball', name) + log.verbose('extracted file from tarball', path) extractCount++ } else { // invalid - log.silly('ignoring from tarball', name) + log.silly('ignoring from tarball', path) } return isValid } - gunzip.on('error', cb) - extracter.on('error', cb) - extracter.on('end', afterTarball) - - // download the tarball, gunzip and extract! + // download the tarball and extract! if (tarPath) { - var input = fs.createReadStream(tarPath) - input.pipe(gunzip).pipe(extracter) - return + return tar.extract({ + file: tarPath, + strip: 1, + filter: isValid, + cwd: devDir + }).then(afterTarball, cb) } try { @@ -222,7 +212,11 @@ function install (fs, gyp, argv, callback) { }) // start unzipping and untaring - req.pipe(gunzip).pipe(extracter) + res.pipe(tar.extract({ + strip: 1, + cwd: devDir, + filter: isValid + }).on('close', afterTarball).on('error', cb)) }) // invoked after the tarball has finished being extracted diff --git a/node_modules/node-gyp/node_modules/tar/.npmignore b/node_modules/node-gyp/node_modules/tar/.npmignore deleted file mode 100644 index c167ad5b1c12f..0000000000000 --- a/node_modules/node-gyp/node_modules/tar/.npmignore +++ /dev/null @@ -1,5 +0,0 @@ -.*.swp -node_modules -examples/extract/ -test/tmp/ -test/fixtures/ diff --git a/node_modules/node-gyp/package.json b/node_modules/node-gyp/package.json index ba6913209c47d..90486a23df4bc 100644 --- a/node_modules/node-gyp/package.json +++ b/node_modules/node-gyp/package.json @@ -1,34 +1,30 @@ { - "_from": "node-gyp@latest", - "_id": "node-gyp@3.8.0", + "_from": "node-gyp@4.0.0", + "_id": "node-gyp@4.0.0", "_inBundle": false, - "_integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "_integrity": "sha512-2XiryJ8sICNo6ej8d0idXDEMKfVfFK7kekGCtJAuelGsYHQxhj13KTf95swTCN2dZ/4lTfZ84Fu31jqJEEgjWA==", "_location": "/node-gyp", "_phantomChildren": { - "abbrev": "1.1.1", - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" + "abbrev": "1.1.1" }, "_requested": { - "type": "tag", + "type": "version", "registry": true, - "raw": "node-gyp@latest", + "raw": "node-gyp@4.0.0", "name": "node-gyp", "escapedName": "node-gyp", - "rawSpec": "latest", + "rawSpec": "4.0.0", "saveSpec": null, - "fetchSpec": "latest" + "fetchSpec": "4.0.0" }, "_requiredBy": [ "#USER", - "/", - "/npm-lifecycle" + "/" ], - "_resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "_shasum": "540304261c330e80d0d5edce253a68cb3964218c", - "_spec": "node-gyp@latest", - "_where": "/Users/zkat/Documents/code/work/npm", + "_resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-4.0.0.tgz", + "_shasum": "972654af4e5dd0cd2a19081b4b46fe0442ba6f45", + "_spec": "node-gyp@4.0.0", + "_where": "/home/hugh/Development/github.com/npm/cli", "author": { "name": "Nathan Rajlich", "email": "nathan@tootallnate.net", @@ -42,7 +38,6 @@ }, "bundleDependencies": false, "dependencies": { - "fstream": "^1.0.0", "glob": "^7.0.3", "graceful-fs": "^4.1.2", "mkdirp": "^0.5.0", @@ -52,7 +47,7 @@ "request": "^2.87.0", "rimraf": "2", "semver": "~5.3.0", - "tar": "^2.0.0", + "tar": "^4.4.8", "which": "1" }, "deprecated": false, @@ -64,7 +59,7 @@ "tape": "~4.2.0" }, "engines": { - "node": ">= 0.8.0" + "node": ">= 4.0.0" }, "homepage": "https://github.com/nodejs/node-gyp#readme", "installVersion": 9, @@ -88,5 +83,5 @@ "scripts": { "test": "tape test/test-*" }, - "version": "3.8.0" + "version": "4.0.0" } diff --git a/node_modules/npm-lifecycle/node_modules/.bin/node-gyp b/node_modules/npm-lifecycle/node_modules/.bin/node-gyp new file mode 120000 index 0000000000000..9b31a4fe437b3 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/.bin/node-gyp @@ -0,0 +1 @@ +../node-gyp/bin/node-gyp.js \ No newline at end of file diff --git a/node_modules/npm-lifecycle/node_modules/.bin/nopt b/node_modules/npm-lifecycle/node_modules/.bin/nopt new file mode 120000 index 0000000000000..6b6566ea7febb --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/.bin/nopt @@ -0,0 +1 @@ +../nopt/bin/nopt.js \ No newline at end of file diff --git a/node_modules/npm-lifecycle/node_modules/.bin/semver b/node_modules/npm-lifecycle/node_modules/.bin/semver new file mode 120000 index 0000000000000..317eb293d8e12 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/.bin/semver @@ -0,0 +1 @@ +../semver/bin/semver \ No newline at end of file diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/.github/ISSUE_TEMPLATE.md b/node_modules/npm-lifecycle/node_modules/node-gyp/.github/ISSUE_TEMPLATE.md new file mode 100644 index 0000000000000..dbd053a90b38f --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/.github/ISSUE_TEMPLATE.md @@ -0,0 +1,26 @@ + + +* **Node Version**: +* **Platform**: +* **Compiler**: +* **Module**: + +
    Verbose output (from npm or node-gyp): + + + +``` + +``` + +
    + + + diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/.github/PULL_REQUEST_TEMPLATE.md b/node_modules/npm-lifecycle/node_modules/node-gyp/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000000..10156d89af112 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,17 @@ + + +##### Checklist + + +- [ ] `npm install && npm test` passes +- [ ] tests are included +- [ ] documentation is changed or added +- [ ] commit message follows [commit guidelines](https://github.com/nodejs/node/blob/master/doc/guides/contributing/pull-requests.md#commit-message-guidelines) + +##### Description of change + + diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/CHANGELOG.md b/node_modules/npm-lifecycle/node_modules/node-gyp/CHANGELOG.md new file mode 100644 index 0000000000000..33bbfad5dec9a --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/CHANGELOG.md @@ -0,0 +1,227 @@ +v3.8.0 2018-08-09 +================= + +* [[`c5929cb4fe`](https://github.com/nodejs/node-gyp/commit/c5929cb4fe)] - **doc**: update Xcode preferences tab name. (Ivan Daniluk) [#1330](https://github.com/nodejs/node-gyp/pull/1330) +* [[`8b488da8b9`](https://github.com/nodejs/node-gyp/commit/8b488da8b9)] - **doc**: update link to commit guidelines (Jonas Hermsmeier) [#1456](https://github.com/nodejs/node-gyp/pull/1456) +* [[`b4fe8c16f9`](https://github.com/nodejs/node-gyp/commit/b4fe8c16f9)] - **doc**: fix visual studio links (Bartosz Sosnowski) [#1490](https://github.com/nodejs/node-gyp/pull/1490) +* [[`536759c7e9`](https://github.com/nodejs/node-gyp/commit/536759c7e9)] - **configure**: use sys.version\_info to get python version (Yang Guo) [#1504](https://github.com/nodejs/node-gyp/pull/1504) +* [[`94c39c604e`](https://github.com/nodejs/node-gyp/commit/94c39c604e)] - **gyp**: fix ninja build failure (GYP patch) (Daniel Bevenius) [nodejs/node#12484](https://github.com/nodejs/node/pull/12484) +* [[`e8ea74e0fa`](https://github.com/nodejs/node-gyp/commit/e8ea74e0fa)] - **tools**: patch gyp to avoid xcrun errors (Ujjwal Sharma) [nodejs/node#21520](https://github.com/nodejs/node/pull/21520) +* [[`ea9aff44f2`](https://github.com/nodejs/node-gyp/commit/ea9aff44f2)] - **tools**: fix "the the" typos in comments (Masashi Hirano) [nodejs/node#20716](https://github.com/nodejs/node/pull/20716) +* [[`207e5aa4fd`](https://github.com/nodejs/node-gyp/commit/207e5aa4fd)] - **gyp**: implement LD/LDXX for ninja and FIPS (Sam Roberts) +* [[`b416c5f4b7`](https://github.com/nodejs/node-gyp/commit/b416c5f4b7)] - **gyp**: enable cctest to use objects (gyp part) (Daniel Bevenius) [nodejs/node#12450](https://github.com/nodejs/node/pull/12450) +* [[`40692d016b`](https://github.com/nodejs/node-gyp/commit/40692d016b)] - **gyp**: add compile\_commands.json gyp generator (Ben Noordhuis) [nodejs/node#12450](https://github.com/nodejs/node/pull/12450) +* [[`fc3c4e2b10`](https://github.com/nodejs/node-gyp/commit/fc3c4e2b10)] - **gyp**: float gyp patch for long filenames (Anna Henningsen) [nodejs/node#7963](https://github.com/nodejs/node/pull/7963) +* [[`8aedbfdef6`](https://github.com/nodejs/node-gyp/commit/8aedbfdef6)] - **gyp**: backport GYP fix to fix AIX shared suffix (Stewart Addison) +* [[`6cd84b84fc`](https://github.com/nodejs/node-gyp/commit/6cd84b84fc)] - **test**: formatting and minor fixes for execFileSync replacement (Rod Vagg) [#1521](https://github.com/nodejs/node-gyp/pull/1521) +* [[`60e421363f`](https://github.com/nodejs/node-gyp/commit/60e421363f)] - **test**: added test/processExecSync.js for when execFileSync is not available. (Rohit Hazra) [#1492](https://github.com/nodejs/node-gyp/pull/1492) +* [[`969447c5bd`](https://github.com/nodejs/node-gyp/commit/969447c5bd)] - **deps**: bump request to 2.8.7, fixes heok/hawk issues (Rohit Hazra) [#1492](https://github.com/nodejs/node-gyp/pull/1492) +* [[`340403ccfe`](https://github.com/nodejs/node-gyp/commit/340403ccfe)] - **win**: improve parsing of SDK version (Alessandro Vergani) [#1516](https://github.com/nodejs/node-gyp/pull/1516) + +v3.7.0 2018-06-08 +================= + +* [[`84cea7b30d`](https://github.com/nodejs/node-gyp/commit/84cea7b30d)] - Remove unused gyp test scripts. (Ben Noordhuis) [#1458](https://github.com/nodejs/node-gyp/pull/1458) +* [[`0540e4ec63`](https://github.com/nodejs/node-gyp/commit/0540e4ec63)] - **gyp**: escape spaces in filenames in make generator (Jeff Senn) [#1436](https://github.com/nodejs/node-gyp/pull/1436) +* [[`88fc6fa0ec`](https://github.com/nodejs/node-gyp/commit/88fc6fa0ec)] - Drop dependency on minimatch. (Brian Woodward) [#1158](https://github.com/nodejs/node-gyp/pull/1158) +* [[`1e203c5148`](https://github.com/nodejs/node-gyp/commit/1e203c5148)] - Fix include path when pointing to Node.js source (Richard Lau) [#1055](https://github.com/nodejs/node-gyp/pull/1055) +* [[`53d8cb967c`](https://github.com/nodejs/node-gyp/commit/53d8cb967c)] - Prefix build targets with /t: on Windows (Natalie Wolfe) [#1164](https://github.com/nodejs/node-gyp/pull/1164) +* [[`53a5f8ff38`](https://github.com/nodejs/node-gyp/commit/53a5f8ff38)] - **gyp**: add support for .mm files to msvs generator (Julien Racle) [#1167](https://github.com/nodejs/node-gyp/pull/1167) +* [[`dd8561e528`](https://github.com/nodejs/node-gyp/commit/dd8561e528)] - **zos**: don't use universal-new-lines mode (John Barboza) [#1451](https://github.com/nodejs/node-gyp/pull/1451) +* [[`e5a69010ed`](https://github.com/nodejs/node-gyp/commit/e5a69010ed)] - **zos**: add search locations for libnode.x (John Barboza) [#1451](https://github.com/nodejs/node-gyp/pull/1451) +* [[`79febace53`](https://github.com/nodejs/node-gyp/commit/79febace53)] - **doc**: update macOS information in README (Josh Parnham) [#1323](https://github.com/nodejs/node-gyp/pull/1323) +* [[`9425448945`](https://github.com/nodejs/node-gyp/commit/9425448945)] - **gyp**: don't print xcodebuild not found errors (Gibson Fahnestock) [#1370](https://github.com/nodejs/node-gyp/pull/1370) +* [[`6f1286f5b2`](https://github.com/nodejs/node-gyp/commit/6f1286f5b2)] - Fix infinite install loop. (Ben Noordhuis) [#1384](https://github.com/nodejs/node-gyp/pull/1384) +* [[`2580b9139e`](https://github.com/nodejs/node-gyp/commit/2580b9139e)] - Update `--nodedir` description in README. (Ben Noordhuis) [#1372](https://github.com/nodejs/node-gyp/pull/1372) +* [[`a61360391a`](https://github.com/nodejs/node-gyp/commit/a61360391a)] - Update README with another way to install on windows (JeffAtDeere) [#1352](https://github.com/nodejs/node-gyp/pull/1352) +* [[`47496bf6dc`](https://github.com/nodejs/node-gyp/commit/47496bf6dc)] - Fix IndexError when parsing GYP files. (Ben Noordhuis) [#1267](https://github.com/nodejs/node-gyp/pull/1267) +* [[`b2024dee7b`](https://github.com/nodejs/node-gyp/commit/b2024dee7b)] - **zos**: support platform (John Barboza) [#1276](https://github.com/nodejs/node-gyp/pull/1276) +* [[`90d86512f4`](https://github.com/nodejs/node-gyp/commit/90d86512f4)] - **win**: run PS with `-NoProfile` (Refael Ackermann) [#1292](https://github.com/nodejs/node-gyp/pull/1292) +* [[`2da5f86ef7`](https://github.com/nodejs/node-gyp/commit/2da5f86ef7)] - **doc**: add github PR and Issue templates (Gibson Fahnestock) [#1228](https://github.com/nodejs/node-gyp/pull/1228) +* [[`a46a770d68`](https://github.com/nodejs/node-gyp/commit/a46a770d68)] - **doc**: update proposed DCO and CoC (Mikeal Rogers) [#1229](https://github.com/nodejs/node-gyp/pull/1229) +* [[`7e803d58e0`](https://github.com/nodejs/node-gyp/commit/7e803d58e0)] - **doc**: headerify the Install instructions (Nick Schonning) [#1225](https://github.com/nodejs/node-gyp/pull/1225) +* [[`f27599193a`](https://github.com/nodejs/node-gyp/commit/f27599193a)] - **gyp**: update xml string encoding conversion (Liu Chao) [#1203](https://github.com/nodejs/node-gyp/pull/1203) +* [[`0a07e481f7`](https://github.com/nodejs/node-gyp/commit/0a07e481f7)] - **configure**: don't set ensure if tarball is set (Gibson Fahnestock) [#1220](https://github.com/nodejs/node-gyp/pull/1220) + +v3.6.3 2018-06-08 +================= + +* [[`90cd2e8da9`](https://github.com/nodejs/node-gyp/commit/90cd2e8da9)] - **gyp**: fix regex to match multi-digit versions (Jonas Hermsmeier) [#1455](https://github.com/nodejs/node-gyp/pull/1455) +* [[`7900122337`](https://github.com/nodejs/node-gyp/commit/7900122337)] - deps: pin `request` version range (Refael Ackerman) [#1300](https://github.com/nodejs/node-gyp/pull/1300) + +v3.6.2 2017-06-01 +================= + +* [[`72afdd62cd`](https://github.com/nodejs/node-gyp/commit/72afdd62cd)] - **build**: rename copyNodeLib() to doBuild() (Liu Chao) [#1206](https://github.com/nodejs/node-gyp/pull/1206) +* [[`bad903ac70`](https://github.com/nodejs/node-gyp/commit/bad903ac70)] - **win**: more robust parsing of SDK version (Refael Ackermann) [#1198](https://github.com/nodejs/node-gyp/pull/1198) +* [[`241752f381`](https://github.com/nodejs/node-gyp/commit/241752f381)] - Log dist-url. (Ben Noordhuis) [#1170](https://github.com/nodejs/node-gyp/pull/1170) +* [[`386746c7d1`](https://github.com/nodejs/node-gyp/commit/386746c7d1)] - **configure**: use full path in node_lib_file GYP var (Pavel Medvedev) [#964](https://github.com/nodejs/node-gyp/pull/964) +* [[`0913b2dd99`](https://github.com/nodejs/node-gyp/commit/0913b2dd99)] - **build, win**: use target_arch to link with node.lib (Pavel Medvedev) [#964](https://github.com/nodejs/node-gyp/pull/964) +* [[`c307b302f7`](https://github.com/nodejs/node-gyp/commit/c307b302f7)] - **doc**: blorb about setting `npm_config_OPTION_NAME` (Refael Ackermann) [#1185](https://github.com/nodejs/node-gyp/pull/1185) + +v3.6.1 2017-04-30 +================= + +* [[`49801716c2`](https://github.com/nodejs/node-gyp/commit/49801716c2)] - **test**: fix test-find-python on v0.10.x buildbot. (Ben Noordhuis) [#1172](https://github.com/nodejs/node-gyp/pull/1172) +* [[`a83a3801fc`](https://github.com/nodejs/node-gyp/commit/a83a3801fc)] - **test**: fix test/test-configure-python on AIX (Richard Lau) [#1131](https://github.com/nodejs/node-gyp/pull/1131) +* [[`8a767145c9`](https://github.com/nodejs/node-gyp/commit/8a767145c9)] - **gyp**: Revert quote_cmd workaround (Kunal Pathak) [#1153](https://github.com/nodejs/node-gyp/pull/1153) +* [[`c09cf7671e`](https://github.com/nodejs/node-gyp/commit/c09cf7671e)] - **doc**: add a note for using `configure` on Windows (Vse Mozhet Byt) [#1152](https://github.com/nodejs/node-gyp/pull/1152) +* [[`da9cb5f411`](https://github.com/nodejs/node-gyp/commit/da9cb5f411)] - Delete superfluous .patch files. (Ben Noordhuis) [#1122](https://github.com/nodejs/node-gyp/pull/1122) + +v3.6.0 2017-03-16 +================= + +* [[`ae141e1906`](https://github.com/nodejs/node-gyp/commit/ae141e1906)] - **win**: find and setup for VS2017 (Refael Ackermann) [#1130](https://github.com/nodejs/node-gyp/pull/1130) +* [[`ec5fc36a80`](https://github.com/nodejs/node-gyp/commit/ec5fc36a80)] - Add support to build node.js with chakracore for ARM. (Kunal Pathak) [#873](https://github.com/nodejs/node-gyp/pull/873) +* [[`a04ea3051a`](https://github.com/nodejs/node-gyp/commit/a04ea3051a)] - Add support to build node.js with chakracore. (Kunal Pathak) [#873](https://github.com/nodejs/node-gyp/pull/873) +* [[`93d7fa83c8`](https://github.com/nodejs/node-gyp/commit/93d7fa83c8)] - Upgrade semver dependency. (Ben Noordhuis) [#1107](https://github.com/nodejs/node-gyp/pull/1107) +* [[`ff9a6fadfd`](https://github.com/nodejs/node-gyp/commit/ff9a6fadfd)] - Update link of gyp as Google code is shutting down (Peter Dave Hello) [#1061](https://github.com/nodejs/node-gyp/pull/1061) + + +v3.5.0 2017-01-10 +================= + +* [[`762d19a39e`](https://github.com/nodejs/node-gyp/commit/762d19a39e)] - \[doc\] merge History.md and CHANGELOG.md (Rod Vagg) +* [[`80fc5c3d31`](https://github.com/nodejs/node-gyp/commit/80fc5c3d31)] - Fix deprecated dependency warning (Simone Primarosa) [#1069](https://github.com/nodejs/node-gyp/pull/1069) +* [[`05c44944fd`](https://github.com/nodejs/node-gyp/commit/05c44944fd)] - Open the build file with universal-newlines mode (Guy Margalit) [#1053](https://github.com/nodejs/node-gyp/pull/1053) +* [[`37ae7be114`](https://github.com/nodejs/node-gyp/commit/37ae7be114)] - Try python launcher when stock python is python 3. (Ben Noordhuis) [#992](https://github.com/nodejs/node-gyp/pull/992) +* [[`e3778d9907`](https://github.com/nodejs/node-gyp/commit/e3778d9907)] - Add lots of findPython() tests. (Ben Noordhuis) [#992](https://github.com/nodejs/node-gyp/pull/992) +* [[`afc766adf6`](https://github.com/nodejs/node-gyp/commit/afc766adf6)] - Unset executable bit for .bat files (Pavel Medvedev) [#969](https://github.com/nodejs/node-gyp/pull/969) +* [[`ddac348991`](https://github.com/nodejs/node-gyp/commit/ddac348991)] - Use push on PYTHONPATH and add tests (Michael Hart) [#990](https://github.com/nodejs/node-gyp/pull/990) +* [[`b182a19042`](https://github.com/nodejs/node-gyp/commit/b182a19042)] - ***Revert*** "add "path-array" dep" (Michael Hart) [#990](https://github.com/nodejs/node-gyp/pull/990) +* [[`7c08b85c5a`](https://github.com/nodejs/node-gyp/commit/7c08b85c5a)] - ***Revert*** "**configure**: use "path-array" for PYTHONPATH" (Michael Hart) [#990](https://github.com/nodejs/node-gyp/pull/990) +* [[`9c8d275526`](https://github.com/nodejs/node-gyp/commit/9c8d275526)] - Add --devdir flag. (Ben Noordhuis) [#916](https://github.com/nodejs/node-gyp/pull/916) +* [[`f6eab1f9e4`](https://github.com/nodejs/node-gyp/commit/f6eab1f9e4)] - **doc**: add windows-build-tools to readme (Felix Rieseberg) [#970](https://github.com/nodejs/node-gyp/pull/970) + +v3.4.0 2016-06-28 +================= + +* [[`ce5fd04e94`](https://github.com/nodejs/node-gyp/commit/ce5fd04e94)] - **deps**: update minimatch version (delphiactual) [#961](https://github.com/nodejs/node-gyp/pull/961) +* [[`77383ddd85`](https://github.com/nodejs/node-gyp/commit/77383ddd85)] - Replace fs.accessSync call to fs.statSync (Richard Lau) [#955](https://github.com/nodejs/node-gyp/pull/955) +* [[`0dba4bda57`](https://github.com/nodejs/node-gyp/commit/0dba4bda57)] - **test**: add simple addon test (Richard Lau) [#955](https://github.com/nodejs/node-gyp/pull/955) +* [[`c4344b3889`](https://github.com/nodejs/node-gyp/commit/c4344b3889)] - **doc**: add --target option to README (Gibson Fahnestock) [#958](https://github.com/nodejs/node-gyp/pull/958) +* [[`cc778e9215`](https://github.com/nodejs/node-gyp/commit/cc778e9215)] - Override BUILDING_UV_SHARED, BUILDING_V8_SHARED. (Ben Noordhuis) [#915](https://github.com/nodejs/node-gyp/pull/915) +* [[`af35b2ad32`](https://github.com/nodejs/node-gyp/commit/af35b2ad32)] - Move VC++ Build Tools to Build Tools landing page. (Andrew Pardoe) [#953](https://github.com/nodejs/node-gyp/pull/953) +* [[`f31482e226`](https://github.com/nodejs/node-gyp/commit/f31482e226)] - **win**: work around __pfnDliNotifyHook2 type change (Alexis Campailla) [#952](https://github.com/nodejs/node-gyp/pull/952) +* [[`3df8222fa5`](https://github.com/nodejs/node-gyp/commit/3df8222fa5)] - Allow for npmlog@3.x (Rebecca Turner) [#950](https://github.com/nodejs/node-gyp/pull/950) +* [[`a4fa07b390`](https://github.com/nodejs/node-gyp/commit/a4fa07b390)] - More verbose error on locating msbuild.exe failure. (Mateusz Jaworski) [#930](https://github.com/nodejs/node-gyp/pull/930) +* [[`4ee31329e0`](https://github.com/nodejs/node-gyp/commit/4ee31329e0)] - **doc**: add command options to README.md (Gibson Fahnestock) [#937](https://github.com/nodejs/node-gyp/pull/937) +* [[`c8c7ca86b9`](https://github.com/nodejs/node-gyp/commit/c8c7ca86b9)] - Add --silent option for zero output. (Gibson Fahnestock) [#937](https://github.com/nodejs/node-gyp/pull/937) +* [[`ac29d23a7c`](https://github.com/nodejs/node-gyp/commit/ac29d23a7c)] - Upgrade to glob@7.0.3. (Ben Noordhuis) [#943](https://github.com/nodejs/node-gyp/pull/943) +* [[`15fd56be3d`](https://github.com/nodejs/node-gyp/commit/15fd56be3d)] - Enable V8 deprecation warnings for native modules (Matt Loring) [#920](https://github.com/nodejs/node-gyp/pull/920) +* [[`7f1c1b960c`](https://github.com/nodejs/node-gyp/commit/7f1c1b960c)] - **gyp**: improvements for android generator (Robert Chiras) [#935](https://github.com/nodejs/node-gyp/pull/935) +* [[`088082766c`](https://github.com/nodejs/node-gyp/commit/088082766c)] - Update Windows install instructions (Sara Itani) [#867](https://github.com/nodejs/node-gyp/pull/867) +* [[`625c1515f9`](https://github.com/nodejs/node-gyp/commit/625c1515f9)] - **gyp**: inherit CC/CXX for CC/CXX.host (Johan Bergström) [#908](https://github.com/nodejs/node-gyp/pull/908) +* [[`3bcb1720e4`](https://github.com/nodejs/node-gyp/commit/3bcb1720e4)] - Add support for the Python launcher on Windows (Patrick Westerhoff) [#894](https://github.com/nodejs/node-gyp/pull/894 + +v3.3.1 2016-03-04 +================= + +* [[`a981ef847a`](https://github.com/nodejs/node-gyp/commit/a981ef847a)] - **gyp**: fix android generator (Robert Chiras) [#889](https://github.com/nodejs/node-gyp/pull/889) + +v3.3.0 2016-02-16 +================= + +* [[`818d854a4d`](https://github.com/nodejs/node-gyp/commit/818d854a4d)] - Introduce NODEJS_ORG_MIRROR and IOJS_ORG_MIRROR (Rod Vagg) [#878](https://github.com/nodejs/node-gyp/pull/878) +* [[`d1e4cc4b62`](https://github.com/nodejs/node-gyp/commit/d1e4cc4b62)] - **(SEMVER-MINOR)** Download headers tarball for ~0.12.10 || ~0.10.42 (Rod Vagg) [#877](https://github.com/nodejs/node-gyp/pull/877) +* [[`6e28ad1bea`](https://github.com/nodejs/node-gyp/commit/6e28ad1bea)] - Allow for npmlog@2.x (Rebecca Turner) [#861](https://github.com/nodejs/node-gyp/pull/861) +* [[`07371e5812`](https://github.com/nodejs/node-gyp/commit/07371e5812)] - Use -fPIC for NetBSD. (Marcin Cieślak) [#856](https://github.com/nodejs/node-gyp/pull/856) +* [[`8c4b0ffa50`](https://github.com/nodejs/node-gyp/commit/8c4b0ffa50)] - **(SEMVER-MINOR)** Add --cafile command line option. (Ben Noordhuis) [#837](https://github.com/nodejs/node-gyp/pull/837) +* [[`b3ad43498e`](https://github.com/nodejs/node-gyp/commit/b3ad43498e)] - **(SEMVER-MINOR)** Make download() function testable. (Ben Noordhuis) [#837](https://github.com/nodejs/node-gyp/pull/837) + +v3.2.1 2015-12-03 +================= + +* [[`ab89b477c4`](https://github.com/nodejs/node-gyp/commit/ab89b477c4)] - Upgrade gyp to b3cef02. (Ben Noordhuis) [#831](https://github.com/nodejs/node-gyp/pull/831) +* [[`90078ecb17`](https://github.com/nodejs/node-gyp/commit/90078ecb17)] - Define WIN32_LEAN_AND_MEAN conditionally. (Ben Noordhuis) [#824](https://github.com/nodejs/node-gyp/pull/824) + +v3.2.0 2015-11-25 +================= + +* [[`268f1ca4c7`](https://github.com/nodejs/node-gyp/commit/268f1ca4c7)] - Use result of `which` when searching for python. (Refael Ackermann) [#668](https://github.com/nodejs/node-gyp/pull/668) +* [[`817ed9bd78`](https://github.com/nodejs/node-gyp/commit/817ed9bd78)] - Add test for python executable search logic. (Ben Noordhuis) [#756](https://github.com/nodejs/node-gyp/pull/756) +* [[`0e2dfda1f3`](https://github.com/nodejs/node-gyp/commit/0e2dfda1f3)] - Fix test/test-options when run through `npm test`. (Ben Noordhuis) [#755](https://github.com/nodejs/node-gyp/pull/755) +* [[`9bfa0876b4`](https://github.com/nodejs/node-gyp/commit/9bfa0876b4)] - Add support for AIX (Michael Dawson) [#753](https://github.com/nodejs/node-gyp/pull/753) +* [[`a8d441a0a2`](https://github.com/nodejs/node-gyp/commit/a8d441a0a2)] - Update README for Windows 10 support. (Jason Williams) [#766](https://github.com/nodejs/node-gyp/pull/766) +* [[`d1d6015276`](https://github.com/nodejs/node-gyp/commit/d1d6015276)] - Update broken links and switch to HTTPS. (andrew morton) + +v3.1.0 2015-11-14 +================= + +* [[`9049241f91`](https://github.com/nodejs/node-gyp/commit/9049241f91)] - **gyp**: don't use links at all, just copy the files instead (Nathan Zadoks) +* [[`8ef90348d1`](https://github.com/nodejs/node-gyp/commit/8ef90348d1)] - **gyp**: apply https://codereview.chromium.org/11361103/ (Nathan Rajlich) +* [[`a2ed0df84e`](https://github.com/nodejs/node-gyp/commit/a2ed0df84e)] - **gyp**: always install into $PRODUCT_DIR (Nathan Rajlich) +* [[`cc8b2fa83e`](https://github.com/nodejs/node-gyp/commit/cc8b2fa83e)] - Update gyp to b3cef02. (Imran Iqbal) [#781](https://github.com/nodejs/node-gyp/pull/781) +* [[`f5d86eb84e`](https://github.com/nodejs/node-gyp/commit/f5d86eb84e)] - Update to tar@2.0.0. (Edgar Muentes) [#797](https://github.com/nodejs/node-gyp/pull/797) +* [[`2ac7de02c4`](https://github.com/nodejs/node-gyp/commit/2ac7de02c4)] - Fix infinite loop with zero-length options. (Ben Noordhuis) [#745](https://github.com/nodejs/node-gyp/pull/745) +* [[`101bed639b`](https://github.com/nodejs/node-gyp/commit/101bed639b)] - This platform value came from debian package, and now the value (Jérémy Lal) [#738](https://github.com/nodejs/node-gyp/pull/738) + +v3.0.3 2015-09-14 +================= + +* [[`ad827cda30`](https://github.com/nodejs/node-gyp/commit/ad827cda30)] - tarballUrl global and && when checking for iojs (Lars-Magnus Skog) [#729](https://github.com/nodejs/node-gyp/pull/729) + +v3.0.2 2015-09-12 +================= + +* [[`6e8c3bf3c6`](https://github.com/nodejs/node-gyp/commit/6e8c3bf3c6)] - add back support for passing additional cmdline args (Rod Vagg) [#723](https://github.com/nodejs/node-gyp/pull/723) +* [[`ff82f2f3b9`](https://github.com/nodejs/node-gyp/commit/ff82f2f3b9)] - fixed broken link in docs to Visual Studio 2013 download (simon-p-r) [#722](https://github.com/nodejs/node-gyp/pull/722) + +v3.0.1 2015-09-08 +================= + +* [[`846337e36b`](https://github.com/nodejs/node-gyp/commit/846337e36b)] - normalise versions for target == this comparison (Rod Vagg) [#716](https://github.com/nodejs/node-gyp/pull/716) + +v3.0.0 2015-09-08 +================= + +* [[`9720d0373c`](https://github.com/nodejs/node-gyp/commit/9720d0373c)] - remove node_modules from tree (Rod Vagg) [#711](https://github.com/nodejs/node-gyp/pull/711) +* [[`6dcf220db7`](https://github.com/nodejs/node-gyp/commit/6dcf220db7)] - test version major directly, don't use semver.satisfies() (Rod Vagg) [#711](https://github.com/nodejs/node-gyp/pull/711) +* [[`938dd18d1c`](https://github.com/nodejs/node-gyp/commit/938dd18d1c)] - refactor for clarity, fix dist-url, add env var dist-url functionality (Rod Vagg) [#711](https://github.com/nodejs/node-gyp/pull/711) +* [[`9e9df66a06`](https://github.com/nodejs/node-gyp/commit/9e9df66a06)] - use process.release, make aware of io.js & node v4 differences (Rod Vagg) [#711](https://github.com/nodejs/node-gyp/pull/711) +* [[`1ea7ed01f4`](https://github.com/nodejs/node-gyp/commit/1ea7ed01f4)] - **deps**: update graceful-fs dependency to the latest (Sakthipriyan Vairamani) [#714](https://github.com/nodejs/node-gyp/pull/714) +* [[`0fbc387b35`](https://github.com/nodejs/node-gyp/commit/0fbc387b35)] - Update repository URLs. (Ben Noordhuis) [#715](https://github.com/nodejs/node-gyp/pull/715) +* [[`bbedb8868b`](https://github.com/nodejs/node-gyp/commit/bbedb8868b)] - **(SEMVER-MAJOR)** **win**: enable delay-load hook by default (Jeremiah Senkpiel) [#708](https://github.com/nodejs/node-gyp/pull/708) +* [[`85ed107565`](https://github.com/nodejs/node-gyp/commit/85ed107565)] - Merge pull request #664 from othiym23/othiym23/allow-semver-5 (Nathan Rajlich) +* [[`0c720d234c`](https://github.com/nodejs/node-gyp/commit/0c720d234c)] - allow semver@5 (Forrest L Norvell) + +2.0.2 / 2015-07-14 +================== + + * Use HTTPS for dist url (#656, @SonicHedgehog) + * Merge pull request #648 from nevosegal/master + * Merge pull request #650 from magic890/patch-1 + * Updated Installation section on README + * Updated link to gyp user documentation + * Fix download error message spelling (#643, @tomxtobin) + * Merge pull request #637 from lygstate/master + * Set NODE_GYP_DIR for addon.gypi to setting absolute path for + src/win_delay_load_hook.c, and fixes of the long relative path issue on Win32. + Fixes #636 (#637, @lygstate). + +2.0.1 / 2015-05-28 +================== + + * configure: try/catch the semver range.test() call + * README: update for visual studio 2013 (#510, @samccone) + +2.0.0 / 2015-05-24 +================== + + * configure: check for python2 executable by default, fallback to python + * configure: don't clobber existing $PYTHONPATH + * configure: use "path-array" for PYTHONPATH + * gyp: fix for non-acsii userprofile name on Windows + * gyp: always install into $PRODUCT_DIR + * gyp: apply https://codereview.chromium.org/11361103/ + * gyp: don't use links at all, just copy the files instead + * gyp: update gyp to e1c8fcf7 + * Updated README.md with updated Windows build info + * Show URL when a download fails + * package: add a "license" field + * move HMODULE m declaration to top + * Only add "-undefined dynamic_lookup" to loadable_module targets + * win: optionally allow node.exe/iojs.exe to be renamed + * Avoid downloading shasums if using tarPath + * Add target name preprocessor define: `NODE_GYP_MODULE_NAME` + * Show better error message in case of bad network settings diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/CONTRIBUTING.md b/node_modules/npm-lifecycle/node_modules/node-gyp/CONTRIBUTING.md new file mode 100644 index 0000000000000..f48786bd84af3 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/CONTRIBUTING.md @@ -0,0 +1,34 @@ +# Contributing to node-gyp + +## Code of Conduct + +Please read the +[Code of Conduct](https://github.com/nodejs/TSC/blob/master/CODE_OF_CONDUCT.md) +which explains the minimum behavior expectations for node-gyp contributors. + +
    +## Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +* (a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +* (b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +* (c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +* (d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/LICENSE b/node_modules/npm-lifecycle/node_modules/node-gyp/LICENSE new file mode 100644 index 0000000000000..2ea4dc5efb872 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/LICENSE @@ -0,0 +1,24 @@ +(The MIT License) + +Copyright (c) 2012 Nathan Rajlich + +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. diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/README.md b/node_modules/npm-lifecycle/node_modules/node-gyp/README.md new file mode 100644 index 0000000000000..0fed03c54322a --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/README.md @@ -0,0 +1,244 @@ +node-gyp +========= +## Node.js native addon build tool + +`node-gyp` is a cross-platform command-line tool written in Node.js for compiling +native addon modules for Node.js. It bundles the [gyp](https://gyp.gsrc.io) +project used by the Chromium team and takes away the pain of dealing with the +various differences in build platforms. It is the replacement to the `node-waf` +program which is removed for node `v0.8`. If you have a native addon for node that +still has a `wscript` file, then you should definitely add a `binding.gyp` file +to support the latest versions of node. + +Multiple target versions of node are supported (i.e. `0.8`, ..., `4`, `5`, `6`, +etc.), regardless of what version of node is actually installed on your system +(`node-gyp` downloads the necessary development files or headers for the target version). + +## Features + + * Easy to use, consistent interface + * Same commands to build your module on every platform + * Supports multiple target versions of Node + + +Installation +------------ + +You can install with `npm`: + +``` bash +$ npm install -g node-gyp +``` + +You will also need to install: + +### On Unix + + * `python` (`v2.7` recommended, `v3.x.x` is __*not*__ supported) + * `make` + * A proper C/C++ compiler toolchain, like [GCC](https://gcc.gnu.org) + +### On macOS + + * `python` (`v2.7` recommended, `v3.x.x` is __*not*__ supported) (already installed on macOS) + * [Xcode](https://developer.apple.com/xcode/download/) + * You also need to install the `Command Line Tools` via Xcode. You can find this under the menu `Xcode -> Preferences -> Locations` (or by running `xcode-select --install` in your Terminal) + * This step will install `gcc` and the related toolchain containing `make` + +### On Windows + +#### Option 1 + +Install all the required tools and configurations using Microsoft's [windows-build-tools](https://github.com/felixrieseberg/windows-build-tools) using `npm install --global --production windows-build-tools` from an elevated PowerShell or CMD.exe (run as Administrator). + +#### Option 2 + +Install tools and configuration manually: + * Install Visual C++ Build Environment: [Visual Studio Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools) + (using "Visual C++ build tools" workload) or [Visual Studio 2017 Community](https://visualstudio.microsoft.com/pl/thank-you-downloading-visual-studio/?sku=Community) + (using the "Desktop development with C++" workload) + * Install [Python 2.7](https://www.python.org/downloads/) (`v3.x.x` is not supported), and run `npm config set python python2.7` (or see below for further instructions on specifying the proper Python version and path.) + * Launch cmd, `npm config set msvs_version 2017` + + If the above steps didn't work for you, please visit [Microsoft's Node.js Guidelines for Windows](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules) for additional tips. + +If you have multiple Python versions installed, you can identify which Python +version `node-gyp` uses by setting the '--python' variable: + +``` bash +$ node-gyp --python /path/to/python2.7 +``` + +If `node-gyp` is called by way of `npm` *and* you have multiple versions of +Python installed, then you can set `npm`'s 'python' config key to the appropriate +value: + +``` bash +$ npm config set python /path/to/executable/python2.7 +``` + +How to Use +---------- + +To compile your native addon, first go to its root directory: + +``` bash +$ cd my_node_addon +``` + +The next step is to generate the appropriate project build files for the current +platform. Use `configure` for that: + +``` bash +$ node-gyp configure +``` + +Auto-detection fails for Visual C++ Build Tools 2015, so `--msvs_version=2015` +needs to be added (not needed when run by npm as configured above): +``` bash +$ node-gyp configure --msvs_version=2015 +``` + +__Note__: The `configure` step looks for the `binding.gyp` file in the current +directory to process. See below for instructions on creating the `binding.gyp` file. + +Now you will have either a `Makefile` (on Unix platforms) or a `vcxproj` file +(on Windows) in the `build/` directory. Next invoke the `build` command: + +``` bash +$ node-gyp build +``` + +Now you have your compiled `.node` bindings file! The compiled bindings end up +in `build/Debug/` or `build/Release/`, depending on the build mode. At this point +you can require the `.node` file with Node and run your tests! + +__Note:__ To create a _Debug_ build of the bindings file, pass the `--debug` (or +`-d`) switch when running either the `configure`, `build` or `rebuild` command. + + +The "binding.gyp" file +---------------------- + +Previously when node had `node-waf` you had to write a `wscript` file. The +replacement for that is the `binding.gyp` file, which describes the configuration +to build your module in a JSON-like format. This file gets placed in the root of +your package, alongside the `package.json` file. + +A barebones `gyp` file appropriate for building a node addon looks like: + +``` python +{ + "targets": [ + { + "target_name": "binding", + "sources": [ "src/binding.cc" ] + } + ] +} +``` + +Some additional resources for addons and writing `gyp` files: + + * ["Going Native" a nodeschool.io tutorial](http://nodeschool.io/#goingnative) + * ["Hello World" node addon example](https://github.com/nodejs/node/tree/master/test/addons/hello-world) + * [gyp user documentation](https://gyp.gsrc.io/docs/UserDocumentation.md) + * [gyp input format reference](https://gyp.gsrc.io/docs/InputFormatReference.md) + * [*"binding.gyp" files out in the wild* wiki page](https://github.com/nodejs/node-gyp/wiki/%22binding.gyp%22-files-out-in-the-wild) + + +Commands +-------- + +`node-gyp` responds to the following commands: + +| **Command** | **Description** +|:--------------|:--------------------------------------------------------------- +| `help` | Shows the help dialog +| `build` | Invokes `make`/`msbuild.exe` and builds the native addon +| `clean` | Removes the `build` directory if it exists +| `configure` | Generates project build files for the current platform +| `rebuild` | Runs `clean`, `configure` and `build` all in a row +| `install` | Installs node header files for the given version +| `list` | Lists the currently installed node header versions +| `remove` | Removes the node header files for the given version + + +Command Options +-------- + +`node-gyp` accepts the following command options: + +| **Command** | **Description** +|:----------------------------------|:------------------------------------------ +| `-j n`, `--jobs n` | Run make in parallel +| `--target=v6.2.1` | Node version to build for (default=process.version) +| `--silly`, `--loglevel=silly` | Log all progress to console +| `--verbose`, `--loglevel=verbose` | Log most progress to console +| `--silent`, `--loglevel=silent` | Don't log anything to console +| `debug`, `--debug` | Make Debug build (default=Release) +| `--release`, `--no-debug` | Make Release build +| `-C $dir`, `--directory=$dir` | Run command in different directory +| `--make=$make` | Override make command (e.g. gmake) +| `--thin=yes` | Enable thin static libraries +| `--arch=$arch` | Set target architecture (e.g. ia32) +| `--tarball=$path` | Get headers from a local tarball +| `--devdir=$path` | SDK download directory (default=~/.node-gyp) +| `--ensure` | Don't reinstall headers if already present +| `--dist-url=$url` | Download header tarball from custom URL +| `--proxy=$url` | Set HTTP proxy for downloading header tarball +| `--cafile=$cafile` | Override default CA chain (to download tarball) +| `--nodedir=$path` | Set the path to the node source code +| `--python=$path` | Set path to the python (2) binary +| `--msvs_version=$version` | Set Visual Studio version (win) +| `--solution=$solution` | Set Visual Studio Solution version (win) + + +Configuration +-------- + +__`node-gyp` responds to environment variables or `npm` configuration__ +1. Environment variables take the form `npm_config_OPTION_NAME` for any of the + options listed above (dashes in option names should be replaced by underscores). + These work also when `node-gyp` is invoked directly: + `$ export npm_config_devdir=/tmp/.gyp` + or on Windows + `> set npm_config_devdir=c:\temp\.gyp` +2. As `npm` configuration, variables take the form `OPTION_NAME`. + This way only works when `node-gyp` is executed by `npm`: + `$ npm config set [--global] devdir /tmp/.gyp` + `$ npm i buffertools` + + + +License +------- + +(The MIT License) + +Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net> + +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. + + +[python-v2.7.10]: https://www.python.org/downloads/release/python-2710/ +[msvc2013]: https://www.microsoft.com/en-gb/download/details.aspx?id=44914 +[win7sdk]: https://www.microsoft.com/en-us/download/details.aspx?id=8279 +[compiler update for the Windows SDK 7.1]: https://www.microsoft.com/en-us/download/details.aspx?id=4422 diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/addon.gypi b/node_modules/npm-lifecycle/node_modules/node-gyp/addon.gypi new file mode 100644 index 0000000000000..55fb3211186f4 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/addon.gypi @@ -0,0 +1,147 @@ +{ + 'variables' : { + 'node_engine_include_dir%': 'deps/v8/include', + }, + 'target_defaults': { + 'type': 'loadable_module', + 'win_delay_load_hook': 'true', + 'product_prefix': '', + + 'conditions': [ + [ 'node_engine=="chakracore"', { + 'variables': { + 'node_engine_include_dir%': 'deps/chakrashim/include' + }, + }] + ], + + 'include_dirs': [ + '<(node_root_dir)/include/node', + '<(node_root_dir)/src', + '<(node_root_dir)/deps/openssl/config', + '<(node_root_dir)/deps/openssl/openssl/include', + '<(node_root_dir)/deps/uv/include', + '<(node_root_dir)/deps/zlib', + '<(node_root_dir)/<(node_engine_include_dir)' + ], + 'defines!': [ + 'BUILDING_UV_SHARED=1', # Inherited from common.gypi. + 'BUILDING_V8_SHARED=1', # Inherited from common.gypi. + ], + 'defines': [ + 'NODE_GYP_MODULE_NAME=>(_target_name)', + 'USING_UV_SHARED=1', + 'USING_V8_SHARED=1', + # Warn when using deprecated V8 APIs. + 'V8_DEPRECATION_WARNINGS=1' + ], + + 'target_conditions': [ + ['_type=="loadable_module"', { + 'product_extension': 'node', + 'defines': [ + 'BUILDING_NODE_EXTENSION' + ], + 'xcode_settings': { + 'OTHER_LDFLAGS': [ + '-undefined dynamic_lookup' + ], + }, + }], + + ['_type=="static_library"', { + # set to `1` to *disable* the -T thin archive 'ld' flag. + # older linkers don't support this flag. + 'standalone_static_library': '<(standalone_static_library)' + }], + + ['_win_delay_load_hook=="true"', { + # If the addon specifies `'win_delay_load_hook': 'true'` in its + # binding.gyp, link a delay-load hook into the DLL. This hook ensures + # that the addon will work regardless of whether the node/iojs binary + # is named node.exe, iojs.exe, or something else. + 'conditions': [ + [ 'OS=="win"', { + 'sources': [ + '<(node_gyp_dir)/src/win_delay_load_hook.cc', + ], + 'msvs_settings': { + 'VCLinkerTool': { + 'DelayLoadDLLs': [ 'iojs.exe', 'node.exe' ], + # Don't print a linker warning when no imports from either .exe + # are used. + 'AdditionalOptions': [ '/ignore:4199' ], + }, + }, + }], + ], + }], + ], + + 'conditions': [ + [ 'OS=="mac"', { + 'defines': [ + '_DARWIN_USE_64_BIT_INODE=1' + ], + 'xcode_settings': { + 'DYLIB_INSTALL_NAME_BASE': '@rpath' + }, + }], + [ 'OS=="aix"', { + 'ldflags': [ + '-Wl,-bimport:<(node_exp_file)' + ], + }], + [ 'OS=="zos"', { + 'cflags': [ + '-q64', + '-Wc,DLL', + '-qlonglong' + ], + 'ldflags': [ + '-q64', + '<(node_exp_file)' + ], + }], + [ 'OS=="win"', { + 'conditions': [ + ['node_engine=="chakracore"', { + 'library_dirs': [ '<(node_root_dir)/$(ConfigurationName)' ], + 'libraries': [ '<@(node_engine_libs)' ], + }], + ], + 'libraries': [ + '-lkernel32.lib', + '-luser32.lib', + '-lgdi32.lib', + '-lwinspool.lib', + '-lcomdlg32.lib', + '-ladvapi32.lib', + '-lshell32.lib', + '-lole32.lib', + '-loleaut32.lib', + '-luuid.lib', + '-lodbc32.lib', + '-lDelayImp.lib', + '-l"<(node_lib_file)"' + ], + 'msvs_disabled_warnings': [ + # warning C4251: 'node::ObjectWrap::handle_' : class 'v8::Persistent' + # needs to have dll-interface to be used by + # clients of class 'node::ObjectWrap' + 4251 + ], + }, { + # OS!="win" + 'defines': [ + '_LARGEFILE_SOURCE', + '_FILE_OFFSET_BITS=64' + ], + }], + [ 'OS in "freebsd openbsd netbsd solaris" or \ + (OS=="linux" and target_arch!="ia32")', { + 'cflags': [ '-fPIC' ], + }] + ] + } +} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/bin/node-gyp.js b/node_modules/npm-lifecycle/node_modules/node-gyp/bin/node-gyp.js new file mode 100755 index 0000000000000..70d7d502628bc --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/bin/node-gyp.js @@ -0,0 +1,148 @@ +#!/usr/bin/env node + +/** + * Set the title. + */ + +process.title = 'node-gyp' + +/** + * Module dependencies. + */ + +var gyp = require('../') +var log = require('npmlog') +var osenv = require('osenv') +var path = require('path') + +/** + * Process and execute the selected commands. + */ + +var prog = gyp() +var completed = false +prog.parseArgv(process.argv) +prog.devDir = prog.opts.devdir + +var homeDir = osenv.home() +if (prog.devDir) { + prog.devDir = prog.devDir.replace(/^~/, homeDir) +} else if (homeDir) { + prog.devDir = path.resolve(homeDir, '.node-gyp') +} else { + throw new Error( + "node-gyp requires that the user's home directory is specified " + + "in either of the environmental variables HOME or USERPROFILE. " + + "Overide with: --devdir /path/to/.node-gyp") +} + +if (prog.todo.length === 0) { + if (~process.argv.indexOf('-v') || ~process.argv.indexOf('--version')) { + console.log('v%s', prog.version) + } else { + console.log('%s', prog.usage()) + } + return process.exit(0) +} + +log.info('it worked if it ends with', 'ok') +log.verbose('cli', process.argv) +log.info('using', 'node-gyp@%s', prog.version) +log.info('using', 'node@%s | %s | %s', process.versions.node, process.platform, process.arch) + + +/** + * Change dir if -C/--directory was passed. + */ + +var dir = prog.opts.directory +if (dir) { + var fs = require('fs') + try { + var stat = fs.statSync(dir) + if (stat.isDirectory()) { + log.info('chdir', dir) + process.chdir(dir) + } else { + log.warn('chdir', dir + ' is not a directory') + } + } catch (e) { + if (e.code === 'ENOENT') { + log.warn('chdir', dir + ' is not a directory') + } else { + log.warn('chdir', 'error during chdir() "%s"', e.message) + } + } +} + +function run () { + var command = prog.todo.shift() + if (!command) { + // done! + completed = true + log.info('ok') + return + } + + prog.commands[command.name](command.args, function (err) { + if (err) { + log.error(command.name + ' error') + log.error('stack', err.stack) + errorMessage() + log.error('not ok') + return process.exit(1) + } + if (command.name == 'list') { + var versions = arguments[1] + if (versions.length > 0) { + versions.forEach(function (version) { + console.log(version) + }) + } else { + console.log('No node development files installed. Use `node-gyp install` to install a version.') + } + } else if (arguments.length >= 2) { + console.log.apply(console, [].slice.call(arguments, 1)) + } + + // now run the next command in the queue + process.nextTick(run) + }) +} + +process.on('exit', function (code) { + if (!completed && !code) { + log.error('Completion callback never invoked!') + issueMessage() + process.exit(6) + } +}) + +process.on('uncaughtException', function (err) { + log.error('UNCAUGHT EXCEPTION') + log.error('stack', err.stack) + issueMessage() + process.exit(7) +}) + +function errorMessage () { + // copied from npm's lib/util/error-handler.js + var os = require('os') + log.error('System', os.type() + ' ' + os.release()) + log.error('command', process.argv + .map(JSON.stringify).join(' ')) + log.error('cwd', process.cwd()) + log.error('node -v', process.version) + log.error('node-gyp -v', 'v' + prog.package.version) +} + +function issueMessage () { + errorMessage() + log.error('', [ 'This is a bug in `node-gyp`.' + , 'Try to update node-gyp and file an Issue if it does not help:' + , ' ' + ].join('\n')) +} + +// start running the given commands! +run() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/AUTHORS b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/AUTHORS new file mode 100644 index 0000000000000..d76d8cd7683f2 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/AUTHORS @@ -0,0 +1,13 @@ +# Names should be added to this file like so: +# Name or Organization + +Google Inc. <*@google.com> +Bloomberg Finance L.P. <*@bloomberg.net> +IBM Inc. <*@*.ibm.com> +Yandex LLC <*@yandex-team.ru> + +Steven Knight +Ryan Norton +David J. Sankel +Eric N. Vander Weele +Tom Freudenberg diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/DEPS b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/DEPS new file mode 100644 index 0000000000000..2e1120f274687 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/DEPS @@ -0,0 +1,24 @@ +# DEPS file for gclient use in buildbot execution of gyp tests. +# +# (You don't need to use gclient for normal GYP development work.) + +vars = { + "chrome_trunk": "http://src.chromium.org/svn/trunk", + "googlecode_url": "http://%s.googlecode.com/svn", +} + +deps = { +} + +deps_os = { + "win": { + "third_party/cygwin": + Var("chrome_trunk") + "/deps/third_party/cygwin@66844", + + "third_party/python_26": + Var("chrome_trunk") + "/tools/third_party/python_26@89111", + + "src/third_party/pefile": + (Var("googlecode_url") % "pefile") + "/trunk@63", + }, +} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/LICENSE b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/LICENSE new file mode 100644 index 0000000000000..ab6b011a10933 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2009 Google Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + + * Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. + * 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. + * Neither the name of Google Inc. nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT +OWNER 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/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/OWNERS b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/OWNERS new file mode 100644 index 0000000000000..72e8ffc0db8aa --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/OWNERS @@ -0,0 +1 @@ +* diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/PRESUBMIT.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/PRESUBMIT.py new file mode 100644 index 0000000000000..f6c8a357afe14 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/PRESUBMIT.py @@ -0,0 +1,139 @@ +# Copyright (c) 2012 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. + + +"""Top-level presubmit script for GYP. + +See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts +for more details about the presubmit API built into gcl. +""" + + +PYLINT_BLACKLIST = [ + # TODO: fix me. + # From SCons, not done in google style. + 'test/lib/TestCmd.py', + 'test/lib/TestCommon.py', + 'test/lib/TestGyp.py', +] + + +PYLINT_DISABLED_WARNINGS = [ + # TODO: fix me. + # Many tests include modules they don't use. + 'W0611', + # Possible unbalanced tuple unpacking with sequence. + 'W0632', + # Attempting to unpack a non-sequence. + 'W0633', + # Include order doesn't properly include local files? + 'F0401', + # Some use of built-in names. + 'W0622', + # Some unused variables. + 'W0612', + # Operator not preceded/followed by space. + 'C0323', + 'C0322', + # Unnecessary semicolon. + 'W0301', + # Unused argument. + 'W0613', + # String has no effect (docstring in wrong place). + 'W0105', + # map/filter on lambda could be replaced by comprehension. + 'W0110', + # Use of eval. + 'W0123', + # Comma not followed by space. + 'C0324', + # Access to a protected member. + 'W0212', + # Bad indent. + 'W0311', + # Line too long. + 'C0301', + # Undefined variable. + 'E0602', + # Not exception type specified. + 'W0702', + # No member of that name. + 'E1101', + # Dangerous default {}. + 'W0102', + # Cyclic import. + 'R0401', + # Others, too many to sort. + 'W0201', 'W0232', 'E1103', 'W0621', 'W0108', 'W0223', 'W0231', + 'R0201', 'E0101', 'C0321', + # ************* Module copy + # W0104:427,12:_test.odict.__setitem__: Statement seems to have no effect + 'W0104', +] + + +def _LicenseHeader(input_api): + # Accept any year number from 2009 to the current year. + current_year = int(input_api.time.strftime('%Y')) + allowed_years = (str(s) for s in reversed(xrange(2009, current_year + 1))) + + years_re = '(' + '|'.join(allowed_years) + ')' + + # The (c) is deprecated, but tolerate it until it's removed from all files. + return ( + r'.*? Copyright (\(c\) )?%(year)s Google Inc\. All rights reserved\.\n' + r'.*? Use of this source code is governed by a BSD-style license that ' + r'can be\n' + r'.*? found in the LICENSE file\.\n' + ) % { + 'year': years_re, + } + +def CheckChangeOnUpload(input_api, output_api): + report = [] + report.extend(input_api.canned_checks.PanProjectChecks( + input_api, output_api, license_header=_LicenseHeader(input_api))) + return report + + +def CheckChangeOnCommit(input_api, output_api): + report = [] + + report.extend(input_api.canned_checks.PanProjectChecks( + input_api, output_api, license_header=_LicenseHeader(input_api))) + report.extend(input_api.canned_checks.CheckTreeIsOpen( + 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=blacklist, + disabled_warnings=PYLINT_DISABLED_WARNINGS)) + finally: + sys.path = old_sys_path + return report + + +TRYBOTS = [ + 'linux_try', + 'mac_try', + 'win_try', +] + + +def GetPreferredTryMasters(_, change): + return { + 'client.gyp': { t: set(['defaulttests']) for t in TRYBOTS }, + } diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/codereview.settings b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/codereview.settings new file mode 100644 index 0000000000000..faf37f1145f17 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/codereview.settings @@ -0,0 +1,10 @@ +# This file is used by gcl to get repository specific information. +CODE_REVIEW_SERVER: codereview.chromium.org +CC_LIST: gyp-developer@googlegroups.com +VIEW_VC: https://chromium.googlesource.com/external/gyp/+/ +TRY_ON_UPLOAD: False +TRYSERVER_PROJECT: gyp +TRYSERVER_PATCHLEVEL: 1 +TRYSERVER_ROOT: gyp +TRYSERVER_SVN_URL: svn://svn.chromium.org/chrome-try/try-nacl +PROJECT: gyp diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc new file mode 100644 index 0000000000000..8bca510815e0a --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc @@ -0,0 +1,12 @@ +// 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. + +// This file is used to generate an empty .pdb -- with a 4KB pagesize -- that is +// then used during the final link for modules that have large PDBs. Otherwise, +// the linker will generate a pdb with a page size of 1KB, which imposes a limit +// of 1GB on the .pdb. By generating an initial empty .pdb with the compiler +// (rather than the linker), this limit is avoided. With this in place PDBs may +// grow to 2GB. +// +// This file is referenced by the msvs_large_pdb mechanism in MSVSUtil.py. diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp new file mode 100755 index 0000000000000..1b8b9bdfb05f5 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp @@ -0,0 +1,8 @@ +#!/bin/sh +# Copyright 2013 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +set -e +base=$(dirname "$0") +exec python "${base}/gyp_main.py" "$@" diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp.bat b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp.bat new file mode 100644 index 0000000000000..c0b4ca24e5df0 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp.bat @@ -0,0 +1,5 @@ +@rem Copyright (c) 2009 Google Inc. All rights reserved. +@rem Use of this source code is governed by a BSD-style license that can be +@rem found in the LICENSE file. + +@python "%~dp0gyp_main.py" %* diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp_main.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp_main.py new file mode 100755 index 0000000000000..25a6eba94aae7 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp_main.py @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +# Copyright (c) 2009 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. + +import os +import sys + +# Make sure we're using the version of pylib in this repo, not one installed +# elsewhere on the system. +sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), 'pylib')) +import gyp + +if __name__ == '__main__': + sys.exit(gyp.script_main()) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py new file mode 100644 index 0000000000000..593f0e5b0b2e8 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py @@ -0,0 +1,340 @@ +# Copyright (c) 2012 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. + +"""New implementation of Visual Studio project generation.""" + +import os +import random + +import gyp.common + +# hashlib is supplied as of Python 2.5 as the replacement interface for md5 +# and other secure hashes. In 2.6, md5 is deprecated. Import hashlib if +# available, avoiding a deprecation warning under 2.6. Import md5 otherwise, +# preserving 2.4 compatibility. +try: + import hashlib + _new_md5 = hashlib.md5 +except ImportError: + import md5 + _new_md5 = md5.new + + +# Initialize random number generator +random.seed() + +# GUIDs for project types +ENTRY_TYPE_GUIDS = { + 'project': '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}', + 'folder': '{2150E333-8FDC-42A3-9474-1A3956D46DE8}', +} + +#------------------------------------------------------------------------------ +# Helper functions + + +def MakeGuid(name, seed='msvs_new'): + """Returns a GUID for the specified target name. + + Args: + name: Target name. + seed: Seed for MD5 hash. + Returns: + A GUID-line string calculated from the name and seed. + + This generates something which looks like a GUID, but depends only on the + name and seed. This means the same name/seed will always generate the same + GUID, so that projects and solutions which refer to each other can explicitly + determine the GUID to refer to explicitly. It also means that the GUID will + not change when the project for a target is rebuilt. + """ + # Calculate a MD5 signature for the seed and name. + d = _new_md5(str(seed) + str(name)).hexdigest().upper() + # Convert most of the signature to GUID form (discard the rest) + guid = ('{' + d[:8] + '-' + d[8:12] + '-' + d[12:16] + '-' + d[16:20] + + '-' + d[20:32] + '}') + return guid + +#------------------------------------------------------------------------------ + + +class MSVSSolutionEntry(object): + def __cmp__(self, other): + # Sort by name then guid (so things are in order on vs2008). + return cmp((self.name, self.get_guid()), (other.name, other.get_guid())) + + +class MSVSFolder(MSVSSolutionEntry): + """Folder in a Visual Studio project or solution.""" + + def __init__(self, path, name = None, entries = None, + guid = None, items = None): + """Initializes the folder. + + Args: + path: Full path to the folder. + name: Name of the folder. + entries: List of folder entries to nest inside this folder. May contain + Folder or Project objects. May be None, if the folder is empty. + guid: GUID to use for folder, if not None. + items: List of solution items to include in the folder project. May be + None, if the folder does not directly contain items. + """ + if name: + self.name = name + else: + # Use last layer. + self.name = os.path.basename(path) + + self.path = path + self.guid = guid + + # Copy passed lists (or set to empty lists) + self.entries = sorted(list(entries or [])) + self.items = list(items or []) + + self.entry_type_guid = ENTRY_TYPE_GUIDS['folder'] + + def get_guid(self): + if self.guid is None: + # Use consistent guids for folders (so things don't regenerate). + self.guid = MakeGuid(self.path, seed='msvs_folder') + return self.guid + + +#------------------------------------------------------------------------------ + + +class MSVSProject(MSVSSolutionEntry): + """Visual Studio project.""" + + def __init__(self, path, name = None, dependencies = None, guid = None, + spec = None, build_file = None, config_platform_overrides = None, + fixpath_prefix = None): + """Initializes the project. + + Args: + path: Absolute path to the project file. + name: Name of project. If None, the name will be the same as the base + name of the project file. + dependencies: List of other Project objects this project is dependent + upon, if not None. + guid: GUID to use for project, if not None. + spec: Dictionary specifying how to build this project. + build_file: Filename of the .gyp file that the vcproj file comes from. + config_platform_overrides: optional dict of configuration platforms to + used in place of the default for this target. + fixpath_prefix: the path used to adjust the behavior of _fixpath + """ + self.path = path + self.guid = guid + self.spec = spec + self.build_file = build_file + # Use project filename if name not specified + self.name = name or os.path.splitext(os.path.basename(path))[0] + + # Copy passed lists (or set to empty lists) + self.dependencies = list(dependencies or []) + + self.entry_type_guid = ENTRY_TYPE_GUIDS['project'] + + if config_platform_overrides: + self.config_platform_overrides = config_platform_overrides + else: + self.config_platform_overrides = {} + self.fixpath_prefix = fixpath_prefix + self.msbuild_toolset = None + + def set_dependencies(self, dependencies): + self.dependencies = list(dependencies or []) + + def get_guid(self): + if self.guid is None: + # Set GUID from path + # TODO(rspangler): This is fragile. + # 1. We can't just use the project filename sans path, since there could + # be multiple projects with the same base name (for example, + # foo/unittest.vcproj and bar/unittest.vcproj). + # 2. The path needs to be relative to $SOURCE_ROOT, so that the project + # GUID is the same whether it's included from base/base.sln or + # foo/bar/baz/baz.sln. + # 3. The GUID needs to be the same each time this builder is invoked, so + # that we don't need to rebuild the solution when the project changes. + # 4. We should be able to handle pre-built project files by reading the + # GUID from the files. + self.guid = MakeGuid(self.name) + return self.guid + + def set_msbuild_toolset(self, msbuild_toolset): + self.msbuild_toolset = msbuild_toolset + +#------------------------------------------------------------------------------ + + +class MSVSSolution(object): + """Visual Studio solution.""" + + def __init__(self, path, version, entries=None, variants=None, + websiteProperties=True): + """Initializes the solution. + + Args: + path: Path to solution file. + version: Format version to emit. + entries: List of entries in solution. May contain Folder or Project + objects. May be None, if the folder is empty. + variants: List of build variant strings. If none, a default list will + be used. + websiteProperties: Flag to decide if the website properties section + is generated. + """ + self.path = path + self.websiteProperties = websiteProperties + self.version = version + + # Copy passed lists (or set to empty lists) + self.entries = list(entries or []) + + if variants: + # Copy passed list + self.variants = variants[:] + else: + # Use default + self.variants = ['Debug|Win32', 'Release|Win32'] + # TODO(rspangler): Need to be able to handle a mapping of solution config + # to project config. Should we be able to handle variants being a dict, + # or add a separate variant_map variable? If it's a dict, we can't + # guarantee the order of variants since dict keys aren't ordered. + + + # TODO(rspangler): Automatically write to disk for now; should delay until + # node-evaluation time. + self.Write() + + + def Write(self, writer=gyp.common.WriteOnDiff): + """Writes the solution file to disk. + + Raises: + IndexError: An entry appears multiple times. + """ + # Walk the entry tree and collect all the folders and projects. + all_entries = set() + entries_to_check = self.entries[:] + while entries_to_check: + e = entries_to_check.pop(0) + + # If this entry has been visited, nothing to do. + if e in all_entries: + continue + + all_entries.add(e) + + # If this is a folder, check its entries too. + if isinstance(e, MSVSFolder): + entries_to_check += e.entries + + all_entries = sorted(all_entries) + + # Open file and print header + f = writer(self.path) + f.write('Microsoft Visual Studio Solution File, ' + 'Format Version %s\r\n' % self.version.SolutionVersion()) + f.write('# %s\r\n' % self.version.Description()) + + # Project entries + sln_root = os.path.split(self.path)[0] + for e in all_entries: + relative_path = gyp.common.RelativePath(e.path, sln_root) + # msbuild does not accept an empty folder_name. + # use '.' in case relative_path is empty. + folder_name = relative_path.replace('/', '\\') or '.' + f.write('Project("%s") = "%s", "%s", "%s"\r\n' % ( + e.entry_type_guid, # Entry type GUID + e.name, # Folder name + folder_name, # Folder name (again) + e.get_guid(), # Entry GUID + )) + + # TODO(rspangler): Need a way to configure this stuff + if self.websiteProperties: + f.write('\tProjectSection(WebsiteProperties) = preProject\r\n' + '\t\tDebug.AspNetCompiler.Debug = "True"\r\n' + '\t\tRelease.AspNetCompiler.Debug = "False"\r\n' + '\tEndProjectSection\r\n') + + if isinstance(e, MSVSFolder): + if e.items: + f.write('\tProjectSection(SolutionItems) = preProject\r\n') + for i in e.items: + f.write('\t\t%s = %s\r\n' % (i, i)) + f.write('\tEndProjectSection\r\n') + + if isinstance(e, MSVSProject): + if e.dependencies: + f.write('\tProjectSection(ProjectDependencies) = postProject\r\n') + for d in e.dependencies: + f.write('\t\t%s = %s\r\n' % (d.get_guid(), d.get_guid())) + f.write('\tEndProjectSection\r\n') + + f.write('EndProject\r\n') + + # Global section + f.write('Global\r\n') + + # Configurations (variants) + f.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n') + for v in self.variants: + f.write('\t\t%s = %s\r\n' % (v, v)) + f.write('\tEndGlobalSection\r\n') + + # Sort config guids for easier diffing of solution changes. + config_guids = [] + config_guids_overrides = {} + for e in all_entries: + if isinstance(e, MSVSProject): + config_guids.append(e.get_guid()) + config_guids_overrides[e.get_guid()] = e.config_platform_overrides + config_guids.sort() + + f.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n') + for g in config_guids: + for v in self.variants: + nv = config_guids_overrides[g].get(v, v) + # Pick which project configuration to build for this solution + # configuration. + f.write('\t\t%s.%s.ActiveCfg = %s\r\n' % ( + g, # Project GUID + v, # Solution build configuration + nv, # Project build config for that solution config + )) + + # Enable project in this solution configuration. + f.write('\t\t%s.%s.Build.0 = %s\r\n' % ( + g, # Project GUID + v, # Solution build configuration + nv, # Project build config for that solution config + )) + f.write('\tEndGlobalSection\r\n') + + # TODO(rspangler): Should be able to configure this stuff too (though I've + # never seen this be any different) + f.write('\tGlobalSection(SolutionProperties) = preSolution\r\n') + f.write('\t\tHideSolutionNode = FALSE\r\n') + f.write('\tEndGlobalSection\r\n') + + # Folder mappings + # Omit this section if there are no folders + if any([e.entries for e in all_entries if isinstance(e, MSVSFolder)]): + f.write('\tGlobalSection(NestedProjects) = preSolution\r\n') + for e in all_entries: + if not isinstance(e, MSVSFolder): + continue # Does not apply to projects, only folders + for subentry in e.entries: + f.write('\t\t%s = %s\r\n' % (subentry.get_guid(), e.get_guid())) + f.write('\tEndGlobalSection\r\n') + + f.write('EndGlobal\r\n') + + f.close() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py new file mode 100644 index 0000000000000..db1ceede344c6 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py @@ -0,0 +1,208 @@ +# Copyright (c) 2012 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. + +"""Visual Studio project reader/writer.""" + +import gyp.common +import gyp.easy_xml as easy_xml + +#------------------------------------------------------------------------------ + + +class Tool(object): + """Visual Studio tool.""" + + def __init__(self, name, attrs=None): + """Initializes the tool. + + Args: + name: Tool name. + attrs: Dict of tool attributes; may be None. + """ + self._attrs = attrs or {} + self._attrs['Name'] = name + + def _GetSpecification(self): + """Creates an element for the tool. + + Returns: + A new xml.dom.Element for the tool. + """ + return ['Tool', self._attrs] + +class Filter(object): + """Visual Studio filter - that is, a virtual folder.""" + + def __init__(self, name, contents=None): + """Initializes the folder. + + Args: + name: Filter (folder) name. + contents: List of filenames and/or Filter objects contained. + """ + self.name = name + self.contents = list(contents or []) + + +#------------------------------------------------------------------------------ + + +class Writer(object): + """Visual Studio XML project writer.""" + + def __init__(self, project_path, version, name, guid=None, platforms=None): + """Initializes the project. + + Args: + project_path: Path to the project file. + version: Format version to emit. + name: Name of the project. + guid: GUID to use for project, if not None. + platforms: Array of string, the supported platforms. If null, ['Win32'] + """ + self.project_path = project_path + self.version = version + self.name = name + self.guid = guid + + # Default to Win32 for platforms. + if not platforms: + platforms = ['Win32'] + + # Initialize the specifications of the various sections. + self.platform_section = ['Platforms'] + for platform in platforms: + self.platform_section.append(['Platform', {'Name': platform}]) + self.tool_files_section = ['ToolFiles'] + self.configurations_section = ['Configurations'] + self.files_section = ['Files'] + + # Keep a dict keyed on filename to speed up access. + self.files_dict = dict() + + def AddToolFile(self, path): + """Adds a tool file to the project. + + Args: + path: Relative path from project to tool file. + """ + self.tool_files_section.append(['ToolFile', {'RelativePath': path}]) + + def _GetSpecForConfiguration(self, config_type, config_name, attrs, tools): + """Returns the specification for a configuration. + + Args: + config_type: Type of configuration node. + config_name: Configuration name. + attrs: Dict of configuration attributes; may be None. + tools: List of tools (strings or Tool objects); may be None. + Returns: + """ + # Handle defaults + if not attrs: + attrs = {} + if not tools: + tools = [] + + # Add configuration node and its attributes + node_attrs = attrs.copy() + node_attrs['Name'] = config_name + specification = [config_type, node_attrs] + + # Add tool nodes and their attributes + if tools: + for t in tools: + if isinstance(t, Tool): + specification.append(t._GetSpecification()) + else: + specification.append(Tool(t)._GetSpecification()) + return specification + + + def AddConfig(self, name, attrs=None, tools=None): + """Adds a configuration to the project. + + Args: + name: Configuration name. + attrs: Dict of configuration attributes; may be None. + tools: List of tools (strings or Tool objects); may be None. + """ + spec = self._GetSpecForConfiguration('Configuration', name, attrs, tools) + self.configurations_section.append(spec) + + def _AddFilesToNode(self, parent, files): + """Adds files and/or filters to the parent node. + + Args: + parent: Destination node + files: A list of Filter objects and/or relative paths to files. + + Will call itself recursively, if the files list contains Filter objects. + """ + for f in files: + if isinstance(f, Filter): + node = ['Filter', {'Name': f.name}] + self._AddFilesToNode(node, f.contents) + else: + node = ['File', {'RelativePath': f}] + self.files_dict[f] = node + parent.append(node) + + def AddFiles(self, files): + """Adds files to the project. + + Args: + files: A list of Filter objects and/or relative paths to files. + + This makes a copy of the file/filter tree at the time of this call. If you + later add files to a Filter object which was passed into a previous call + to AddFiles(), it will not be reflected in this project. + """ + self._AddFilesToNode(self.files_section, files) + # TODO(rspangler) This also doesn't handle adding files to an existing + # filter. That is, it doesn't merge the trees. + + def AddFileConfig(self, path, config, attrs=None, tools=None): + """Adds a configuration to a file. + + Args: + path: Relative path to the file. + config: Name of configuration to add. + attrs: Dict of configuration attributes; may be None. + tools: List of tools (strings or Tool objects); may be None. + + Raises: + ValueError: Relative path does not match any file added via AddFiles(). + """ + # Find the file node with the right relative path + parent = self.files_dict.get(path) + if not parent: + raise ValueError('AddFileConfig: file "%s" not in project.' % path) + + # Add the config to the file node + spec = self._GetSpecForConfiguration('FileConfiguration', config, attrs, + tools) + parent.append(spec) + + def WriteIfChanged(self): + """Writes the project file.""" + # First create XML content definition + content = [ + 'VisualStudioProject', + {'ProjectType': 'Visual C++', + 'Version': self.version.ProjectVersion(), + 'Name': self.name, + 'ProjectGUID': self.guid, + 'RootNamespace': self.name, + 'Keyword': 'Win32Proj' + }, + self.platform_section, + self.tool_files_section, + self.configurations_section, + ['References'], # empty section + self.files_section, + ['Globals'] # empty section + ] + easy_xml.WriteXmlIfChanged(content, self.project_path, + encoding="Windows-1252") diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py new file mode 100644 index 0000000000000..a08cc154d7398 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py @@ -0,0 +1,1096 @@ +# Copyright (c) 2012 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. + +r"""Code to validate and convert settings of the Microsoft build tools. + +This file contains code to validate and convert settings of the Microsoft +build tools. The function ConvertToMSBuildSettings(), ValidateMSVSSettings(), +and ValidateMSBuildSettings() are the entry points. + +This file was created by comparing the projects created by Visual Studio 2008 +and Visual Studio 2010 for all available settings through the user interface. +The MSBuild schemas were also considered. They are typically found in the +MSBuild install directory, e.g. c:\Program Files (x86)\MSBuild +""" + +import sys +import re + +# Dictionaries of settings validators. The key is the tool name, the value is +# a dictionary mapping setting names to validation functions. +_msvs_validators = {} +_msbuild_validators = {} + + +# A dictionary of settings converters. The key is the tool name, the value is +# a dictionary mapping setting names to conversion functions. +_msvs_to_msbuild_converters = {} + + +# Tool name mapping from MSVS to MSBuild. +_msbuild_name_of_tool = {} + + +class _Tool(object): + """Represents a tool used by MSVS or MSBuild. + + Attributes: + msvs_name: The name of the tool in MSVS. + msbuild_name: The name of the tool in MSBuild. + """ + + def __init__(self, msvs_name, msbuild_name): + self.msvs_name = msvs_name + self.msbuild_name = msbuild_name + + +def _AddTool(tool): + """Adds a tool to the four dictionaries used to process settings. + + This only defines the tool. Each setting also needs to be added. + + Args: + tool: The _Tool object to be added. + """ + _msvs_validators[tool.msvs_name] = {} + _msbuild_validators[tool.msbuild_name] = {} + _msvs_to_msbuild_converters[tool.msvs_name] = {} + _msbuild_name_of_tool[tool.msvs_name] = tool.msbuild_name + + +def _GetMSBuildToolSettings(msbuild_settings, tool): + """Returns an MSBuild tool dictionary. Creates it if needed.""" + return msbuild_settings.setdefault(tool.msbuild_name, {}) + + +class _Type(object): + """Type of settings (Base class).""" + + def ValidateMSVS(self, value): + """Verifies that the value is legal for MSVS. + + Args: + value: the value to check for this type. + + Raises: + ValueError if value is not valid for MSVS. + """ + + def ValidateMSBuild(self, value): + """Verifies that the value is legal for MSBuild. + + Args: + value: the value to check for this type. + + Raises: + ValueError if value is not valid for MSBuild. + """ + + def ConvertToMSBuild(self, value): + """Returns the MSBuild equivalent of the MSVS value given. + + Args: + value: the MSVS value to convert. + + Returns: + the MSBuild equivalent. + + Raises: + ValueError if value is not valid. + """ + return value + + +class _String(_Type): + """A setting that's just a string.""" + + def ValidateMSVS(self, value): + if not isinstance(value, basestring): + raise ValueError('expected string; got %r' % value) + + def ValidateMSBuild(self, value): + if not isinstance(value, basestring): + raise ValueError('expected string; got %r' % value) + + def ConvertToMSBuild(self, value): + # Convert the macros + return ConvertVCMacrosToMSBuild(value) + + +class _StringList(_Type): + """A settings that's a list of strings.""" + + def ValidateMSVS(self, value): + if not isinstance(value, basestring) and not isinstance(value, list): + raise ValueError('expected string list; got %r' % value) + + def ValidateMSBuild(self, value): + if not isinstance(value, basestring) and not isinstance(value, list): + raise ValueError('expected string list; got %r' % value) + + def ConvertToMSBuild(self, value): + # Convert the macros + if isinstance(value, list): + return [ConvertVCMacrosToMSBuild(i) for i in value] + else: + return ConvertVCMacrosToMSBuild(value) + + +class _Boolean(_Type): + """Boolean settings, can have the values 'false' or 'true'.""" + + def _Validate(self, value): + if value != 'true' and value != 'false': + raise ValueError('expected bool; got %r' % value) + + def ValidateMSVS(self, value): + self._Validate(value) + + def ValidateMSBuild(self, value): + self._Validate(value) + + def ConvertToMSBuild(self, value): + self._Validate(value) + return value + + +class _Integer(_Type): + """Integer settings.""" + + def __init__(self, msbuild_base=10): + _Type.__init__(self) + self._msbuild_base = msbuild_base + + def ValidateMSVS(self, value): + # Try to convert, this will raise ValueError if invalid. + self.ConvertToMSBuild(value) + + def ValidateMSBuild(self, value): + # Try to convert, this will raise ValueError if invalid. + int(value, self._msbuild_base) + + def ConvertToMSBuild(self, value): + msbuild_format = (self._msbuild_base == 10) and '%d' or '0x%04x' + return msbuild_format % int(value) + + +class _Enumeration(_Type): + """Type of settings that is an enumeration. + + In MSVS, the values are indexes like '0', '1', and '2'. + MSBuild uses text labels that are more representative, like 'Win32'. + + Constructor args: + label_list: an array of MSBuild labels that correspond to the MSVS index. + In the rare cases where MSVS has skipped an index value, None is + used in the array to indicate the unused spot. + new: an array of labels that are new to MSBuild. + """ + + def __init__(self, label_list, new=None): + _Type.__init__(self) + self._label_list = label_list + self._msbuild_values = set(value for value in label_list + if value is not None) + if new is not None: + self._msbuild_values.update(new) + + def ValidateMSVS(self, value): + # Try to convert. It will raise an exception if not valid. + self.ConvertToMSBuild(value) + + def ValidateMSBuild(self, value): + if value not in self._msbuild_values: + raise ValueError('unrecognized enumerated value %s' % value) + + def ConvertToMSBuild(self, value): + index = int(value) + if index < 0 or index >= len(self._label_list): + raise ValueError('index value (%d) not in expected range [0, %d)' % + (index, len(self._label_list))) + label = self._label_list[index] + if label is None: + raise ValueError('converted value for %s not specified.' % value) + return label + + +# Instantiate the various generic types. +_boolean = _Boolean() +_integer = _Integer() +# For now, we don't do any special validation on these types: +_string = _String() +_file_name = _String() +_folder_name = _String() +_file_list = _StringList() +_folder_list = _StringList() +_string_list = _StringList() +# Some boolean settings went from numerical values to boolean. The +# mapping is 0: default, 1: false, 2: true. +_newly_boolean = _Enumeration(['', 'false', 'true']) + + +def _Same(tool, name, setting_type): + """Defines a setting that has the same name in MSVS and MSBuild. + + Args: + tool: a dictionary that gives the names of the tool for MSVS and MSBuild. + name: the name of the setting. + setting_type: the type of this setting. + """ + _Renamed(tool, name, name, setting_type) + + +def _Renamed(tool, msvs_name, msbuild_name, setting_type): + """Defines a setting for which the name has changed. + + Args: + tool: a dictionary that gives the names of the tool for MSVS and MSBuild. + msvs_name: the name of the MSVS setting. + msbuild_name: the name of the MSBuild setting. + setting_type: the type of this setting. + """ + + def _Translate(value, msbuild_settings): + msbuild_tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool) + msbuild_tool_settings[msbuild_name] = setting_type.ConvertToMSBuild(value) + + _msvs_validators[tool.msvs_name][msvs_name] = setting_type.ValidateMSVS + _msbuild_validators[tool.msbuild_name][msbuild_name] = ( + setting_type.ValidateMSBuild) + _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate + + +def _Moved(tool, settings_name, msbuild_tool_name, setting_type): + _MovedAndRenamed(tool, settings_name, msbuild_tool_name, settings_name, + setting_type) + + +def _MovedAndRenamed(tool, msvs_settings_name, msbuild_tool_name, + msbuild_settings_name, setting_type): + """Defines a setting that may have moved to a new section. + + Args: + tool: a dictionary that gives the names of the tool for MSVS and MSBuild. + msvs_settings_name: the MSVS name of the setting. + msbuild_tool_name: the name of the MSBuild tool to place the setting under. + msbuild_settings_name: the MSBuild name of the setting. + setting_type: the type of this setting. + """ + + def _Translate(value, msbuild_settings): + tool_settings = msbuild_settings.setdefault(msbuild_tool_name, {}) + tool_settings[msbuild_settings_name] = setting_type.ConvertToMSBuild(value) + + _msvs_validators[tool.msvs_name][msvs_settings_name] = ( + setting_type.ValidateMSVS) + validator = setting_type.ValidateMSBuild + _msbuild_validators[msbuild_tool_name][msbuild_settings_name] = validator + _msvs_to_msbuild_converters[tool.msvs_name][msvs_settings_name] = _Translate + + +def _MSVSOnly(tool, name, setting_type): + """Defines a setting that is only found in MSVS. + + Args: + tool: a dictionary that gives the names of the tool for MSVS and MSBuild. + name: the name of the setting. + setting_type: the type of this setting. + """ + + def _Translate(unused_value, unused_msbuild_settings): + # Since this is for MSVS only settings, no translation will happen. + pass + + _msvs_validators[tool.msvs_name][name] = setting_type.ValidateMSVS + _msvs_to_msbuild_converters[tool.msvs_name][name] = _Translate + + +def _MSBuildOnly(tool, name, setting_type): + """Defines a setting that is only found in MSBuild. + + Args: + tool: a dictionary that gives the names of the tool for MSVS and MSBuild. + name: the name of the setting. + setting_type: the type of this setting. + """ + + def _Translate(value, msbuild_settings): + # Let msbuild-only properties get translated as-is from msvs_settings. + tool_settings = msbuild_settings.setdefault(tool.msbuild_name, {}) + tool_settings[name] = value + + _msbuild_validators[tool.msbuild_name][name] = setting_type.ValidateMSBuild + _msvs_to_msbuild_converters[tool.msvs_name][name] = _Translate + + +def _ConvertedToAdditionalOption(tool, msvs_name, flag): + """Defines a setting that's handled via a command line option in MSBuild. + + Args: + tool: a dictionary that gives the names of the tool for MSVS and MSBuild. + msvs_name: the name of the MSVS setting that if 'true' becomes a flag + flag: the flag to insert at the end of the AdditionalOptions + """ + + def _Translate(value, msbuild_settings): + if value == 'true': + tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool) + if 'AdditionalOptions' in tool_settings: + new_flags = '%s %s' % (tool_settings['AdditionalOptions'], flag) + else: + new_flags = flag + tool_settings['AdditionalOptions'] = new_flags + _msvs_validators[tool.msvs_name][msvs_name] = _boolean.ValidateMSVS + _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate + + +def _CustomGeneratePreprocessedFile(tool, msvs_name): + def _Translate(value, msbuild_settings): + tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool) + if value == '0': + tool_settings['PreprocessToFile'] = 'false' + tool_settings['PreprocessSuppressLineNumbers'] = 'false' + elif value == '1': # /P + tool_settings['PreprocessToFile'] = 'true' + tool_settings['PreprocessSuppressLineNumbers'] = 'false' + elif value == '2': # /EP /P + tool_settings['PreprocessToFile'] = 'true' + tool_settings['PreprocessSuppressLineNumbers'] = 'true' + else: + raise ValueError('value must be one of [0, 1, 2]; got %s' % value) + # Create a bogus validator that looks for '0', '1', or '2' + msvs_validator = _Enumeration(['a', 'b', 'c']).ValidateMSVS + _msvs_validators[tool.msvs_name][msvs_name] = msvs_validator + msbuild_validator = _boolean.ValidateMSBuild + msbuild_tool_validators = _msbuild_validators[tool.msbuild_name] + msbuild_tool_validators['PreprocessToFile'] = msbuild_validator + msbuild_tool_validators['PreprocessSuppressLineNumbers'] = msbuild_validator + _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate + + +fix_vc_macro_slashes_regex_list = ('IntDir', 'OutDir') +fix_vc_macro_slashes_regex = re.compile( + r'(\$\((?:%s)\))(?:[\\/]+)' % "|".join(fix_vc_macro_slashes_regex_list) +) + +# Regular expression to detect keys that were generated by exclusion lists +_EXCLUDED_SUFFIX_RE = re.compile('^(.*)_excluded$') + + +def _ValidateExclusionSetting(setting, settings, error_msg, stderr=sys.stderr): + """Verify that 'setting' is valid if it is generated from an exclusion list. + + If the setting appears to be generated from an exclusion list, the root name + is checked. + + Args: + setting: A string that is the setting name to validate + settings: A dictionary where the keys are valid settings + error_msg: The message to emit in the event of error + stderr: The stream receiving the error messages. + """ + # This may be unrecognized because it's an exclusion list. If the + # setting name has the _excluded suffix, then check the root name. + unrecognized = True + m = re.match(_EXCLUDED_SUFFIX_RE, setting) + if m: + root_setting = m.group(1) + unrecognized = root_setting not in settings + + if unrecognized: + # We don't know this setting. Give a warning. + print >> stderr, error_msg + + +def FixVCMacroSlashes(s): + """Replace macros which have excessive following slashes. + + These macros are known to have a built-in trailing slash. Furthermore, many + scripts hiccup on processing paths with extra slashes in the middle. + + This list is probably not exhaustive. Add as needed. + """ + if '$' in s: + s = fix_vc_macro_slashes_regex.sub(r'\1', s) + return s + + +def ConvertVCMacrosToMSBuild(s): + """Convert the MSVS macros found in the string to the MSBuild equivalent. + + This list is probably not exhaustive. Add as needed. + """ + if '$' in s: + replace_map = { + '$(ConfigurationName)': '$(Configuration)', + '$(InputDir)': '%(RelativeDir)', + '$(InputExt)': '%(Extension)', + '$(InputFileName)': '%(Filename)%(Extension)', + '$(InputName)': '%(Filename)', + '$(InputPath)': '%(Identity)', + '$(ParentName)': '$(ProjectFileName)', + '$(PlatformName)': '$(Platform)', + '$(SafeInputName)': '%(Filename)', + } + for old, new in replace_map.iteritems(): + s = s.replace(old, new) + s = FixVCMacroSlashes(s) + return s + + +def ConvertToMSBuildSettings(msvs_settings, stderr=sys.stderr): + """Converts MSVS settings (VS2008 and earlier) to MSBuild settings (VS2010+). + + Args: + msvs_settings: A dictionary. The key is the tool name. The values are + themselves dictionaries of settings and their values. + stderr: The stream receiving the error messages. + + Returns: + A dictionary of MSBuild settings. The key is either the MSBuild tool name + or the empty string (for the global settings). The values are themselves + dictionaries of settings and their values. + """ + msbuild_settings = {} + for msvs_tool_name, msvs_tool_settings in msvs_settings.iteritems(): + if msvs_tool_name in _msvs_to_msbuild_converters: + msvs_tool = _msvs_to_msbuild_converters[msvs_tool_name] + for msvs_setting, msvs_value in msvs_tool_settings.iteritems(): + if msvs_setting in msvs_tool: + # Invoke the translation function. + try: + msvs_tool[msvs_setting](msvs_value, msbuild_settings) + except ValueError, e: + print >> stderr, ('Warning: while converting %s/%s to MSBuild, ' + '%s' % (msvs_tool_name, msvs_setting, e)) + else: + _ValidateExclusionSetting(msvs_setting, + msvs_tool, + ('Warning: unrecognized setting %s/%s ' + 'while converting to MSBuild.' % + (msvs_tool_name, msvs_setting)), + stderr) + else: + print >> stderr, ('Warning: unrecognized tool %s while converting to ' + 'MSBuild.' % msvs_tool_name) + return msbuild_settings + + +def ValidateMSVSSettings(settings, stderr=sys.stderr): + """Validates that the names of the settings are valid for MSVS. + + Args: + settings: A dictionary. The key is the tool name. The values are + themselves dictionaries of settings and their values. + stderr: The stream receiving the error messages. + """ + _ValidateSettings(_msvs_validators, settings, stderr) + + +def ValidateMSBuildSettings(settings, stderr=sys.stderr): + """Validates that the names of the settings are valid for MSBuild. + + Args: + settings: A dictionary. The key is the tool name. The values are + themselves dictionaries of settings and their values. + stderr: The stream receiving the error messages. + """ + _ValidateSettings(_msbuild_validators, settings, stderr) + + +def _ValidateSettings(validators, settings, stderr): + """Validates that the settings are valid for MSBuild or MSVS. + + We currently only validate the names of the settings, not their values. + + Args: + validators: A dictionary of tools and their validators. + settings: A dictionary. The key is the tool name. The values are + themselves dictionaries of settings and their values. + stderr: The stream receiving the error messages. + """ + for tool_name in settings: + if tool_name in validators: + tool_validators = validators[tool_name] + for setting, value in settings[tool_name].iteritems(): + if setting in tool_validators: + try: + tool_validators[setting](value) + except ValueError, e: + print >> stderr, ('Warning: for %s/%s, %s' % + (tool_name, setting, e)) + else: + _ValidateExclusionSetting(setting, + tool_validators, + ('Warning: unrecognized setting %s/%s' % + (tool_name, setting)), + stderr) + + else: + print >> stderr, ('Warning: unrecognized tool %s' % tool_name) + + +# MSVS and MBuild names of the tools. +_compile = _Tool('VCCLCompilerTool', 'ClCompile') +_link = _Tool('VCLinkerTool', 'Link') +_midl = _Tool('VCMIDLTool', 'Midl') +_rc = _Tool('VCResourceCompilerTool', 'ResourceCompile') +_lib = _Tool('VCLibrarianTool', 'Lib') +_manifest = _Tool('VCManifestTool', 'Manifest') +_masm = _Tool('MASM', 'MASM') + + +_AddTool(_compile) +_AddTool(_link) +_AddTool(_midl) +_AddTool(_rc) +_AddTool(_lib) +_AddTool(_manifest) +_AddTool(_masm) +# Add sections only found in the MSBuild settings. +_msbuild_validators[''] = {} +_msbuild_validators['ProjectReference'] = {} +_msbuild_validators['ManifestResourceCompile'] = {} + +# Descriptions of the compiler options, i.e. VCCLCompilerTool in MSVS and +# ClCompile in MSBuild. +# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\cl.xml" for +# the schema of the MSBuild ClCompile settings. + +# Options that have the same name in MSVS and MSBuild +_Same(_compile, 'AdditionalIncludeDirectories', _folder_list) # /I +_Same(_compile, 'AdditionalOptions', _string_list) +_Same(_compile, 'AdditionalUsingDirectories', _folder_list) # /AI +_Same(_compile, 'AssemblerListingLocation', _file_name) # /Fa +_Same(_compile, 'BrowseInformationFile', _file_name) +_Same(_compile, 'BufferSecurityCheck', _boolean) # /GS +_Same(_compile, 'DisableLanguageExtensions', _boolean) # /Za +_Same(_compile, 'DisableSpecificWarnings', _string_list) # /wd +_Same(_compile, 'EnableFiberSafeOptimizations', _boolean) # /GT +_Same(_compile, 'EnablePREfast', _boolean) # /analyze Visible='false' +_Same(_compile, 'ExpandAttributedSource', _boolean) # /Fx +_Same(_compile, 'FloatingPointExceptions', _boolean) # /fp:except +_Same(_compile, 'ForceConformanceInForLoopScope', _boolean) # /Zc:forScope +_Same(_compile, 'ForcedIncludeFiles', _file_list) # /FI +_Same(_compile, 'ForcedUsingFiles', _file_list) # /FU +_Same(_compile, 'GenerateXMLDocumentationFiles', _boolean) # /doc +_Same(_compile, 'IgnoreStandardIncludePath', _boolean) # /X +_Same(_compile, 'MinimalRebuild', _boolean) # /Gm +_Same(_compile, 'OmitDefaultLibName', _boolean) # /Zl +_Same(_compile, 'OmitFramePointers', _boolean) # /Oy +_Same(_compile, 'PreprocessorDefinitions', _string_list) # /D +_Same(_compile, 'ProgramDataBaseFileName', _file_name) # /Fd +_Same(_compile, 'RuntimeTypeInfo', _boolean) # /GR +_Same(_compile, 'ShowIncludes', _boolean) # /showIncludes +_Same(_compile, 'SmallerTypeCheck', _boolean) # /RTCc +_Same(_compile, 'StringPooling', _boolean) # /GF +_Same(_compile, 'SuppressStartupBanner', _boolean) # /nologo +_Same(_compile, 'TreatWChar_tAsBuiltInType', _boolean) # /Zc:wchar_t +_Same(_compile, 'UndefineAllPreprocessorDefinitions', _boolean) # /u +_Same(_compile, 'UndefinePreprocessorDefinitions', _string_list) # /U +_Same(_compile, 'UseFullPaths', _boolean) # /FC +_Same(_compile, 'WholeProgramOptimization', _boolean) # /GL +_Same(_compile, 'XMLDocumentationFileName', _file_name) + +_Same(_compile, 'AssemblerOutput', + _Enumeration(['NoListing', + 'AssemblyCode', # /FA + 'All', # /FAcs + 'AssemblyAndMachineCode', # /FAc + 'AssemblyAndSourceCode'])) # /FAs +_Same(_compile, 'BasicRuntimeChecks', + _Enumeration(['Default', + 'StackFrameRuntimeCheck', # /RTCs + 'UninitializedLocalUsageCheck', # /RTCu + 'EnableFastChecks'])) # /RTC1 +_Same(_compile, 'BrowseInformation', + _Enumeration(['false', + 'true', # /FR + 'true'])) # /Fr +_Same(_compile, 'CallingConvention', + _Enumeration(['Cdecl', # /Gd + 'FastCall', # /Gr + 'StdCall', # /Gz + 'VectorCall'])) # /Gv +_Same(_compile, 'CompileAs', + _Enumeration(['Default', + 'CompileAsC', # /TC + 'CompileAsCpp'])) # /TP +_Same(_compile, 'DebugInformationFormat', + _Enumeration(['', # Disabled + 'OldStyle', # /Z7 + None, + 'ProgramDatabase', # /Zi + 'EditAndContinue'])) # /ZI +_Same(_compile, 'EnableEnhancedInstructionSet', + _Enumeration(['NotSet', + 'StreamingSIMDExtensions', # /arch:SSE + 'StreamingSIMDExtensions2', # /arch:SSE2 + 'AdvancedVectorExtensions', # /arch:AVX (vs2012+) + 'NoExtensions', # /arch:IA32 (vs2012+) + # This one only exists in the new msbuild format. + 'AdvancedVectorExtensions2', # /arch:AVX2 (vs2013r2+) + ])) +_Same(_compile, 'ErrorReporting', + _Enumeration(['None', # /errorReport:none + 'Prompt', # /errorReport:prompt + 'Queue'], # /errorReport:queue + new=['Send'])) # /errorReport:send" +_Same(_compile, 'ExceptionHandling', + _Enumeration(['false', + 'Sync', # /EHsc + 'Async'], # /EHa + new=['SyncCThrow'])) # /EHs +_Same(_compile, 'FavorSizeOrSpeed', + _Enumeration(['Neither', + 'Speed', # /Ot + 'Size'])) # /Os +_Same(_compile, 'FloatingPointModel', + _Enumeration(['Precise', # /fp:precise + 'Strict', # /fp:strict + 'Fast'])) # /fp:fast +_Same(_compile, 'InlineFunctionExpansion', + _Enumeration(['Default', + 'OnlyExplicitInline', # /Ob1 + 'AnySuitable'], # /Ob2 + new=['Disabled'])) # /Ob0 +_Same(_compile, 'Optimization', + _Enumeration(['Disabled', # /Od + 'MinSpace', # /O1 + 'MaxSpeed', # /O2 + 'Full'])) # /Ox +_Same(_compile, 'RuntimeLibrary', + _Enumeration(['MultiThreaded', # /MT + 'MultiThreadedDebug', # /MTd + 'MultiThreadedDLL', # /MD + 'MultiThreadedDebugDLL'])) # /MDd +_Same(_compile, 'StructMemberAlignment', + _Enumeration(['Default', + '1Byte', # /Zp1 + '2Bytes', # /Zp2 + '4Bytes', # /Zp4 + '8Bytes', # /Zp8 + '16Bytes'])) # /Zp16 +_Same(_compile, 'WarningLevel', + _Enumeration(['TurnOffAllWarnings', # /W0 + 'Level1', # /W1 + 'Level2', # /W2 + 'Level3', # /W3 + 'Level4'], # /W4 + new=['EnableAllWarnings'])) # /Wall + +# Options found in MSVS that have been renamed in MSBuild. +_Renamed(_compile, 'EnableFunctionLevelLinking', 'FunctionLevelLinking', + _boolean) # /Gy +_Renamed(_compile, 'EnableIntrinsicFunctions', 'IntrinsicFunctions', + _boolean) # /Oi +_Renamed(_compile, 'KeepComments', 'PreprocessKeepComments', _boolean) # /C +_Renamed(_compile, 'ObjectFile', 'ObjectFileName', _file_name) # /Fo +_Renamed(_compile, 'OpenMP', 'OpenMPSupport', _boolean) # /openmp +_Renamed(_compile, 'PrecompiledHeaderThrough', 'PrecompiledHeaderFile', + _file_name) # Used with /Yc and /Yu +_Renamed(_compile, 'PrecompiledHeaderFile', 'PrecompiledHeaderOutputFile', + _file_name) # /Fp +_Renamed(_compile, 'UsePrecompiledHeader', 'PrecompiledHeader', + _Enumeration(['NotUsing', # VS recognized '' for this value too. + 'Create', # /Yc + 'Use'])) # /Yu +_Renamed(_compile, 'WarnAsError', 'TreatWarningAsError', _boolean) # /WX + +_ConvertedToAdditionalOption(_compile, 'DefaultCharIsUnsigned', '/J') + +# MSVS options not found in MSBuild. +_MSVSOnly(_compile, 'Detect64BitPortabilityProblems', _boolean) +_MSVSOnly(_compile, 'UseUnicodeResponseFiles', _boolean) + +# MSBuild options not found in MSVS. +_MSBuildOnly(_compile, 'BuildingInIDE', _boolean) +_MSBuildOnly(_compile, 'CompileAsManaged', + _Enumeration([], new=['false', + 'true'])) # /clr +_MSBuildOnly(_compile, 'CreateHotpatchableImage', _boolean) # /hotpatch +_MSBuildOnly(_compile, 'MultiProcessorCompilation', _boolean) # /MP +_MSBuildOnly(_compile, 'PreprocessOutputPath', _string) # /Fi +_MSBuildOnly(_compile, 'ProcessorNumber', _integer) # the number of processors +_MSBuildOnly(_compile, 'TrackerLogDirectory', _folder_name) +_MSBuildOnly(_compile, 'TreatSpecificWarningsAsErrors', _string_list) # /we +_MSBuildOnly(_compile, 'UseUnicodeForAssemblerListing', _boolean) # /FAu + +# Defines a setting that needs very customized processing +_CustomGeneratePreprocessedFile(_compile, 'GeneratePreprocessedFile') + + +# Directives for converting MSVS VCLinkerTool to MSBuild Link. +# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\link.xml" for +# the schema of the MSBuild Link settings. + +# Options that have the same name in MSVS and MSBuild +_Same(_link, 'AdditionalDependencies', _file_list) +_Same(_link, 'AdditionalLibraryDirectories', _folder_list) # /LIBPATH +# /MANIFESTDEPENDENCY: +_Same(_link, 'AdditionalManifestDependencies', _file_list) +_Same(_link, 'AdditionalOptions', _string_list) +_Same(_link, 'AddModuleNamesToAssembly', _file_list) # /ASSEMBLYMODULE +_Same(_link, 'AllowIsolation', _boolean) # /ALLOWISOLATION +_Same(_link, 'AssemblyLinkResource', _file_list) # /ASSEMBLYLINKRESOURCE +_Same(_link, 'BaseAddress', _string) # /BASE +_Same(_link, 'CLRUnmanagedCodeCheck', _boolean) # /CLRUNMANAGEDCODECHECK +_Same(_link, 'DelayLoadDLLs', _file_list) # /DELAYLOAD +_Same(_link, 'DelaySign', _boolean) # /DELAYSIGN +_Same(_link, 'EmbedManagedResourceFile', _file_list) # /ASSEMBLYRESOURCE +_Same(_link, 'EnableUAC', _boolean) # /MANIFESTUAC +_Same(_link, 'EntryPointSymbol', _string) # /ENTRY +_Same(_link, 'ForceSymbolReferences', _file_list) # /INCLUDE +_Same(_link, 'FunctionOrder', _file_name) # /ORDER +_Same(_link, 'GenerateDebugInformation', _boolean) # /DEBUG +_Same(_link, 'GenerateMapFile', _boolean) # /MAP +_Same(_link, 'HeapCommitSize', _string) +_Same(_link, 'HeapReserveSize', _string) # /HEAP +_Same(_link, 'IgnoreAllDefaultLibraries', _boolean) # /NODEFAULTLIB +_Same(_link, 'IgnoreEmbeddedIDL', _boolean) # /IGNOREIDL +_Same(_link, 'ImportLibrary', _file_name) # /IMPLIB +_Same(_link, 'KeyContainer', _file_name) # /KEYCONTAINER +_Same(_link, 'KeyFile', _file_name) # /KEYFILE +_Same(_link, 'ManifestFile', _file_name) # /ManifestFile +_Same(_link, 'MapExports', _boolean) # /MAPINFO:EXPORTS +_Same(_link, 'MapFileName', _file_name) +_Same(_link, 'MergedIDLBaseFileName', _file_name) # /IDLOUT +_Same(_link, 'MergeSections', _string) # /MERGE +_Same(_link, 'MidlCommandFile', _file_name) # /MIDL +_Same(_link, 'ModuleDefinitionFile', _file_name) # /DEF +_Same(_link, 'OutputFile', _file_name) # /OUT +_Same(_link, 'PerUserRedirection', _boolean) +_Same(_link, 'Profile', _boolean) # /PROFILE +_Same(_link, 'ProfileGuidedDatabase', _file_name) # /PGD +_Same(_link, 'ProgramDatabaseFile', _file_name) # /PDB +_Same(_link, 'RegisterOutput', _boolean) +_Same(_link, 'SetChecksum', _boolean) # /RELEASE +_Same(_link, 'StackCommitSize', _string) +_Same(_link, 'StackReserveSize', _string) # /STACK +_Same(_link, 'StripPrivateSymbols', _file_name) # /PDBSTRIPPED +_Same(_link, 'SupportUnloadOfDelayLoadedDLL', _boolean) # /DELAY:UNLOAD +_Same(_link, 'SuppressStartupBanner', _boolean) # /NOLOGO +_Same(_link, 'SwapRunFromCD', _boolean) # /SWAPRUN:CD +_Same(_link, 'TurnOffAssemblyGeneration', _boolean) # /NOASSEMBLY +_Same(_link, 'TypeLibraryFile', _file_name) # /TLBOUT +_Same(_link, 'TypeLibraryResourceID', _integer) # /TLBID +_Same(_link, 'UACUIAccess', _boolean) # /uiAccess='true' +_Same(_link, 'Version', _string) # /VERSION + +_Same(_link, 'EnableCOMDATFolding', _newly_boolean) # /OPT:ICF +_Same(_link, 'FixedBaseAddress', _newly_boolean) # /FIXED +_Same(_link, 'LargeAddressAware', _newly_boolean) # /LARGEADDRESSAWARE +_Same(_link, 'OptimizeReferences', _newly_boolean) # /OPT:REF +_Same(_link, 'RandomizedBaseAddress', _newly_boolean) # /DYNAMICBASE +_Same(_link, 'TerminalServerAware', _newly_boolean) # /TSAWARE + +_subsystem_enumeration = _Enumeration( + ['NotSet', + 'Console', # /SUBSYSTEM:CONSOLE + 'Windows', # /SUBSYSTEM:WINDOWS + 'Native', # /SUBSYSTEM:NATIVE + 'EFI Application', # /SUBSYSTEM:EFI_APPLICATION + 'EFI Boot Service Driver', # /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER + 'EFI ROM', # /SUBSYSTEM:EFI_ROM + 'EFI Runtime', # /SUBSYSTEM:EFI_RUNTIME_DRIVER + 'WindowsCE'], # /SUBSYSTEM:WINDOWSCE + new=['POSIX']) # /SUBSYSTEM:POSIX + +_target_machine_enumeration = _Enumeration( + ['NotSet', + 'MachineX86', # /MACHINE:X86 + None, + 'MachineARM', # /MACHINE:ARM + 'MachineEBC', # /MACHINE:EBC + 'MachineIA64', # /MACHINE:IA64 + None, + 'MachineMIPS', # /MACHINE:MIPS + 'MachineMIPS16', # /MACHINE:MIPS16 + 'MachineMIPSFPU', # /MACHINE:MIPSFPU + 'MachineMIPSFPU16', # /MACHINE:MIPSFPU16 + None, + None, + None, + 'MachineSH4', # /MACHINE:SH4 + None, + 'MachineTHUMB', # /MACHINE:THUMB + 'MachineX64']) # /MACHINE:X64 + +_Same(_link, 'AssemblyDebug', + _Enumeration(['', + 'true', # /ASSEMBLYDEBUG + 'false'])) # /ASSEMBLYDEBUG:DISABLE +_Same(_link, 'CLRImageType', + _Enumeration(['Default', + 'ForceIJWImage', # /CLRIMAGETYPE:IJW + 'ForcePureILImage', # /Switch="CLRIMAGETYPE:PURE + 'ForceSafeILImage'])) # /Switch="CLRIMAGETYPE:SAFE +_Same(_link, 'CLRThreadAttribute', + _Enumeration(['DefaultThreadingAttribute', # /CLRTHREADATTRIBUTE:NONE + 'MTAThreadingAttribute', # /CLRTHREADATTRIBUTE:MTA + 'STAThreadingAttribute'])) # /CLRTHREADATTRIBUTE:STA +_Same(_link, 'DataExecutionPrevention', + _Enumeration(['', + 'false', # /NXCOMPAT:NO + 'true'])) # /NXCOMPAT +_Same(_link, 'Driver', + _Enumeration(['NotSet', + 'Driver', # /Driver + 'UpOnly', # /DRIVER:UPONLY + 'WDM'])) # /DRIVER:WDM +_Same(_link, 'LinkTimeCodeGeneration', + _Enumeration(['Default', + 'UseLinkTimeCodeGeneration', # /LTCG + 'PGInstrument', # /LTCG:PGInstrument + 'PGOptimization', # /LTCG:PGOptimize + 'PGUpdate'])) # /LTCG:PGUpdate +_Same(_link, 'ShowProgress', + _Enumeration(['NotSet', + 'LinkVerbose', # /VERBOSE + 'LinkVerboseLib'], # /VERBOSE:Lib + new=['LinkVerboseICF', # /VERBOSE:ICF + 'LinkVerboseREF', # /VERBOSE:REF + 'LinkVerboseSAFESEH', # /VERBOSE:SAFESEH + 'LinkVerboseCLR'])) # /VERBOSE:CLR +_Same(_link, 'SubSystem', _subsystem_enumeration) +_Same(_link, 'TargetMachine', _target_machine_enumeration) +_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. +_Renamed(_link, 'ErrorReporting', 'LinkErrorReporting', + _Enumeration(['NoErrorReport', # /ERRORREPORT:NONE + 'PromptImmediately', # /ERRORREPORT:PROMPT + 'QueueForNextLogin'], # /ERRORREPORT:QUEUE + new=['SendErrorReport'])) # /ERRORREPORT:SEND +_Renamed(_link, 'IgnoreDefaultLibraryNames', 'IgnoreSpecificDefaultLibraries', + _file_list) # /NODEFAULTLIB +_Renamed(_link, 'ResourceOnlyDLL', 'NoEntryPoint', _boolean) # /NOENTRY +_Renamed(_link, 'SwapRunFromNet', 'SwapRunFromNET', _boolean) # /SWAPRUN:NET + +_Moved(_link, 'GenerateManifest', '', _boolean) +_Moved(_link, 'IgnoreImportLibrary', '', _boolean) +_Moved(_link, 'LinkIncremental', '', _newly_boolean) +_Moved(_link, 'LinkLibraryDependencies', 'ProjectReference', _boolean) +_Moved(_link, 'UseLibraryDependencyInputs', 'ProjectReference', _boolean) + +# MSVS options not found in MSBuild. +_MSVSOnly(_link, 'OptimizeForWindows98', _newly_boolean) +_MSVSOnly(_link, 'UseUnicodeResponseFiles', _boolean) + +# MSBuild options not found in MSVS. +_MSBuildOnly(_link, 'BuildingInIDE', _boolean) +_MSBuildOnly(_link, 'ImageHasSafeExceptionHandlers', _boolean) # /SAFESEH +_MSBuildOnly(_link, 'LinkDLL', _boolean) # /DLL Visible='false' +_MSBuildOnly(_link, 'LinkStatus', _boolean) # /LTCG:STATUS +_MSBuildOnly(_link, 'PreventDllBinding', _boolean) # /ALLOWBIND +_MSBuildOnly(_link, 'SupportNobindOfDelayLoadedDLL', _boolean) # /DELAY:NOBIND +_MSBuildOnly(_link, 'TrackerLogDirectory', _folder_name) +_MSBuildOnly(_link, 'MSDOSStubFileName', _file_name) # /STUB Visible='false' +_MSBuildOnly(_link, 'SectionAlignment', _integer) # /ALIGN +_MSBuildOnly(_link, 'SpecifySectionAttributes', _string) # /SECTION +_MSBuildOnly(_link, 'ForceFileOutput', + _Enumeration([], new=['Enabled', # /FORCE + # /FORCE:MULTIPLE + 'MultiplyDefinedSymbolOnly', + 'UndefinedSymbolOnly'])) # /FORCE:UNRESOLVED +_MSBuildOnly(_link, 'CreateHotPatchableImage', + _Enumeration([], new=['Enabled', # /FUNCTIONPADMIN + 'X86Image', # /FUNCTIONPADMIN:5 + 'X64Image', # /FUNCTIONPADMIN:6 + 'ItaniumImage'])) # /FUNCTIONPADMIN:16 +_MSBuildOnly(_link, 'CLRSupportLastError', + _Enumeration([], new=['Enabled', # /CLRSupportLastError + 'Disabled', # /CLRSupportLastError:NO + # /CLRSupportLastError:SYSTEMDLL + 'SystemDlls'])) + + +# Directives for converting VCResourceCompilerTool to ResourceCompile. +# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\rc.xml" for +# the schema of the MSBuild ResourceCompile settings. + +_Same(_rc, 'AdditionalOptions', _string_list) +_Same(_rc, 'AdditionalIncludeDirectories', _folder_list) # /I +_Same(_rc, 'Culture', _Integer(msbuild_base=16)) +_Same(_rc, 'IgnoreStandardIncludePath', _boolean) # /X +_Same(_rc, 'PreprocessorDefinitions', _string_list) # /D +_Same(_rc, 'ResourceOutputFileName', _string) # /fo +_Same(_rc, 'ShowProgress', _boolean) # /v +# There is no UI in VisualStudio 2008 to set the following properties. +# However they are found in CL and other tools. Include them here for +# completeness, as they are very likely to have the same usage pattern. +_Same(_rc, 'SuppressStartupBanner', _boolean) # /nologo +_Same(_rc, 'UndefinePreprocessorDefinitions', _string_list) # /u + +# MSBuild options not found in MSVS. +_MSBuildOnly(_rc, 'NullTerminateStrings', _boolean) # /n +_MSBuildOnly(_rc, 'TrackerLogDirectory', _folder_name) + + +# Directives for converting VCMIDLTool to Midl. +# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\midl.xml" for +# the schema of the MSBuild Midl settings. + +_Same(_midl, 'AdditionalIncludeDirectories', _folder_list) # /I +_Same(_midl, 'AdditionalOptions', _string_list) +_Same(_midl, 'CPreprocessOptions', _string) # /cpp_opt +_Same(_midl, 'ErrorCheckAllocations', _boolean) # /error allocation +_Same(_midl, 'ErrorCheckBounds', _boolean) # /error bounds_check +_Same(_midl, 'ErrorCheckEnumRange', _boolean) # /error enum +_Same(_midl, 'ErrorCheckRefPointers', _boolean) # /error ref +_Same(_midl, 'ErrorCheckStubData', _boolean) # /error stub_data +_Same(_midl, 'GenerateStublessProxies', _boolean) # /Oicf +_Same(_midl, 'GenerateTypeLibrary', _boolean) +_Same(_midl, 'HeaderFileName', _file_name) # /h +_Same(_midl, 'IgnoreStandardIncludePath', _boolean) # /no_def_idir +_Same(_midl, 'InterfaceIdentifierFileName', _file_name) # /iid +_Same(_midl, 'MkTypLibCompatible', _boolean) # /mktyplib203 +_Same(_midl, 'OutputDirectory', _string) # /out +_Same(_midl, 'PreprocessorDefinitions', _string_list) # /D +_Same(_midl, 'ProxyFileName', _file_name) # /proxy +_Same(_midl, 'RedirectOutputAndErrors', _file_name) # /o +_Same(_midl, 'SuppressStartupBanner', _boolean) # /nologo +_Same(_midl, 'TypeLibraryName', _file_name) # /tlb +_Same(_midl, 'UndefinePreprocessorDefinitions', _string_list) # /U +_Same(_midl, 'WarnAsError', _boolean) # /WX + +_Same(_midl, 'DefaultCharType', + _Enumeration(['Unsigned', # /char unsigned + 'Signed', # /char signed + 'Ascii'])) # /char ascii7 +_Same(_midl, 'TargetEnvironment', + _Enumeration(['NotSet', + 'Win32', # /env win32 + 'Itanium', # /env ia64 + 'X64'])) # /env x64 +_Same(_midl, 'EnableErrorChecks', + _Enumeration(['EnableCustom', + 'None', # /error none + 'All'])) # /error all +_Same(_midl, 'StructMemberAlignment', + _Enumeration(['NotSet', + '1', # Zp1 + '2', # Zp2 + '4', # Zp4 + '8'])) # Zp8 +_Same(_midl, 'WarningLevel', + _Enumeration(['0', # /W0 + '1', # /W1 + '2', # /W2 + '3', # /W3 + '4'])) # /W4 + +_Renamed(_midl, 'DLLDataFileName', 'DllDataFileName', _file_name) # /dlldata +_Renamed(_midl, 'ValidateParameters', 'ValidateAllParameters', + _boolean) # /robust + +# MSBuild options not found in MSVS. +_MSBuildOnly(_midl, 'ApplicationConfigurationMode', _boolean) # /app_config +_MSBuildOnly(_midl, 'ClientStubFile', _file_name) # /cstub +_MSBuildOnly(_midl, 'GenerateClientFiles', + _Enumeration([], new=['Stub', # /client stub + 'None'])) # /client none +_MSBuildOnly(_midl, 'GenerateServerFiles', + _Enumeration([], new=['Stub', # /client stub + 'None'])) # /client none +_MSBuildOnly(_midl, 'LocaleID', _integer) # /lcid DECIMAL +_MSBuildOnly(_midl, 'ServerStubFile', _file_name) # /sstub +_MSBuildOnly(_midl, 'SuppressCompilerWarnings', _boolean) # /no_warn +_MSBuildOnly(_midl, 'TrackerLogDirectory', _folder_name) +_MSBuildOnly(_midl, 'TypeLibFormat', + _Enumeration([], new=['NewFormat', # /newtlb + 'OldFormat'])) # /oldtlb + + +# Directives for converting VCLibrarianTool to Lib. +# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\lib.xml" for +# the schema of the MSBuild Lib settings. + +_Same(_lib, 'AdditionalDependencies', _file_list) +_Same(_lib, 'AdditionalLibraryDirectories', _folder_list) # /LIBPATH +_Same(_lib, 'AdditionalOptions', _string_list) +_Same(_lib, 'ExportNamedFunctions', _string_list) # /EXPORT +_Same(_lib, 'ForceSymbolReferences', _string) # /INCLUDE +_Same(_lib, 'IgnoreAllDefaultLibraries', _boolean) # /NODEFAULTLIB +_Same(_lib, 'IgnoreSpecificDefaultLibraries', _file_list) # /NODEFAULTLIB +_Same(_lib, 'ModuleDefinitionFile', _file_name) # /DEF +_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. +_Moved(_lib, 'LinkLibraryDependencies', 'ProjectReference', _boolean) + +_MSBuildOnly(_lib, 'DisplayLibrary', _string) # /LIST Visible='false' +_MSBuildOnly(_lib, 'ErrorReporting', + _Enumeration([], new=['PromptImmediately', # /ERRORREPORT:PROMPT + 'QueueForNextLogin', # /ERRORREPORT:QUEUE + 'SendErrorReport', # /ERRORREPORT:SEND + 'NoErrorReport'])) # /ERRORREPORT:NONE +_MSBuildOnly(_lib, 'MinimumRequiredVersion', _string) +_MSBuildOnly(_lib, 'Name', _file_name) # /NAME +_MSBuildOnly(_lib, 'RemoveObjects', _file_list) # /REMOVE +_MSBuildOnly(_lib, 'SubSystem', _subsystem_enumeration) +_MSBuildOnly(_lib, 'TrackerLogDirectory', _folder_name) +_MSBuildOnly(_lib, 'TreatLibWarningAsErrors', _boolean) # /WX +_MSBuildOnly(_lib, 'Verbose', _boolean) + + +# Directives for converting VCManifestTool to Mt. +# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\mt.xml" for +# the schema of the MSBuild Lib settings. + +# Options that have the same name in MSVS and MSBuild +_Same(_manifest, 'AdditionalManifestFiles', _file_list) # /manifest +_Same(_manifest, 'AdditionalOptions', _string_list) +_Same(_manifest, 'AssemblyIdentity', _string) # /identity: +_Same(_manifest, 'ComponentFileName', _file_name) # /dll +_Same(_manifest, 'GenerateCatalogFiles', _boolean) # /makecdfs +_Same(_manifest, 'InputResourceManifests', _string) # /inputresource +_Same(_manifest, 'OutputManifestFile', _file_name) # /out +_Same(_manifest, 'RegistrarScriptFile', _file_name) # /rgs +_Same(_manifest, 'ReplacementsFile', _file_name) # /replacements +_Same(_manifest, 'SuppressStartupBanner', _boolean) # /nologo +_Same(_manifest, 'TypeLibraryFile', _file_name) # /tlb: +_Same(_manifest, 'UpdateFileHashes', _boolean) # /hashupdate +_Same(_manifest, 'UpdateFileHashesSearchPath', _file_name) +_Same(_manifest, 'VerboseOutput', _boolean) # /verbose + +# Options that have moved location. +_MovedAndRenamed(_manifest, 'ManifestResourceFile', + 'ManifestResourceCompile', + 'ResourceOutputFileName', + _file_name) +_Moved(_manifest, 'EmbedManifest', '', _boolean) + +# MSVS options not found in MSBuild. +_MSVSOnly(_manifest, 'DependencyInformationFile', _file_name) +_MSVSOnly(_manifest, 'UseFAT32Workaround', _boolean) +_MSVSOnly(_manifest, 'UseUnicodeResponseFiles', _boolean) + +# MSBuild options not found in MSVS. +_MSBuildOnly(_manifest, 'EnableDPIAwareness', _boolean) +_MSBuildOnly(_manifest, 'GenerateCategoryTags', _boolean) # /category +_MSBuildOnly(_manifest, 'ManifestFromManagedAssembly', + _file_name) # /managedassemblyname +_MSBuildOnly(_manifest, 'OutputResourceManifests', _string) # /outputresource +_MSBuildOnly(_manifest, 'SuppressDependencyElement', _boolean) # /nodependency +_MSBuildOnly(_manifest, 'TrackerLogDirectory', _folder_name) + + +# Directives for MASM. +# See "$(VCTargetsPath)\BuildCustomizations\masm.xml" for the schema of the +# MSBuild MASM settings. + +# Options that have the same name in MSVS and MSBuild. +_Same(_masm, 'UseSafeExceptionHandlers', _boolean) # /safeseh diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py new file mode 100755 index 0000000000000..bf6ea6b802ff9 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py @@ -0,0 +1,1483 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 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. + +"""Unit tests for the MSVSSettings.py file.""" + +import StringIO +import unittest +import gyp.MSVSSettings as MSVSSettings + + +class TestSequenceFunctions(unittest.TestCase): + + def setUp(self): + self.stderr = StringIO.StringIO() + + def _ExpectedWarnings(self, expected): + """Compares recorded lines to expected warnings.""" + self.stderr.seek(0) + actual = self.stderr.read().split('\n') + actual = [line for line in actual if line] + self.assertEqual(sorted(expected), sorted(actual)) + + def testValidateMSVSSettings_tool_names(self): + """Tests that only MSVS tool names are allowed.""" + MSVSSettings.ValidateMSVSSettings( + {'VCCLCompilerTool': {}, + 'VCLinkerTool': {}, + 'VCMIDLTool': {}, + 'foo': {}, + 'VCResourceCompilerTool': {}, + 'VCLibrarianTool': {}, + 'VCManifestTool': {}, + 'ClCompile': {}}, + self.stderr) + self._ExpectedWarnings([ + 'Warning: unrecognized tool foo', + 'Warning: unrecognized tool ClCompile']) + + def testValidateMSVSSettings_settings(self): + """Tests that for invalid MSVS settings.""" + MSVSSettings.ValidateMSVSSettings( + {'VCCLCompilerTool': { + 'AdditionalIncludeDirectories': 'folder1;folder2', + 'AdditionalOptions': ['string1', 'string2'], + 'AdditionalUsingDirectories': 'folder1;folder2', + 'AssemblerListingLocation': 'a_file_name', + 'AssemblerOutput': '0', + 'BasicRuntimeChecks': '5', + 'BrowseInformation': 'fdkslj', + 'BrowseInformationFile': 'a_file_name', + 'BufferSecurityCheck': 'true', + 'CallingConvention': '-1', + 'CompileAs': '1', + 'DebugInformationFormat': '2', + 'DefaultCharIsUnsigned': 'true', + 'Detect64BitPortabilityProblems': 'true', + 'DisableLanguageExtensions': 'true', + 'DisableSpecificWarnings': 'string1;string2', + 'EnableEnhancedInstructionSet': '1', + 'EnableFiberSafeOptimizations': 'true', + 'EnableFunctionLevelLinking': 'true', + 'EnableIntrinsicFunctions': 'true', + 'EnablePREfast': 'true', + 'Enableprefast': 'bogus', + 'ErrorReporting': '1', + 'ExceptionHandling': '1', + 'ExpandAttributedSource': 'true', + 'FavorSizeOrSpeed': '1', + 'FloatingPointExceptions': 'true', + 'FloatingPointModel': '1', + 'ForceConformanceInForLoopScope': 'true', + 'ForcedIncludeFiles': 'file1;file2', + 'ForcedUsingFiles': 'file1;file2', + 'GeneratePreprocessedFile': '1', + 'GenerateXMLDocumentationFiles': 'true', + 'IgnoreStandardIncludePath': 'true', + 'InlineFunctionExpansion': '1', + 'KeepComments': 'true', + 'MinimalRebuild': 'true', + 'ObjectFile': 'a_file_name', + 'OmitDefaultLibName': 'true', + 'OmitFramePointers': 'true', + 'OpenMP': 'true', + 'Optimization': '1', + 'PrecompiledHeaderFile': 'a_file_name', + 'PrecompiledHeaderThrough': 'a_file_name', + 'PreprocessorDefinitions': 'string1;string2', + 'ProgramDataBaseFileName': 'a_file_name', + 'RuntimeLibrary': '1', + 'RuntimeTypeInfo': 'true', + 'ShowIncludes': 'true', + 'SmallerTypeCheck': 'true', + 'StringPooling': 'true', + 'StructMemberAlignment': '1', + 'SuppressStartupBanner': 'true', + 'TreatWChar_tAsBuiltInType': 'true', + 'UndefineAllPreprocessorDefinitions': 'true', + 'UndefinePreprocessorDefinitions': 'string1;string2', + 'UseFullPaths': 'true', + 'UsePrecompiledHeader': '1', + 'UseUnicodeResponseFiles': 'true', + 'WarnAsError': 'true', + 'WarningLevel': '1', + 'WholeProgramOptimization': 'true', + 'XMLDocumentationFileName': 'a_file_name', + 'ZZXYZ': 'bogus'}, + 'VCLinkerTool': { + 'AdditionalDependencies': 'file1;file2', + 'AdditionalDependencies_excluded': 'file3', + 'AdditionalLibraryDirectories': 'folder1;folder2', + 'AdditionalManifestDependencies': 'file1;file2', + 'AdditionalOptions': 'a string1', + 'AddModuleNamesToAssembly': 'file1;file2', + 'AllowIsolation': 'true', + 'AssemblyDebug': '2', + 'AssemblyLinkResource': 'file1;file2', + 'BaseAddress': 'a string1', + 'CLRImageType': '2', + 'CLRThreadAttribute': '2', + 'CLRUnmanagedCodeCheck': 'true', + 'DataExecutionPrevention': '2', + 'DelayLoadDLLs': 'file1;file2', + 'DelaySign': 'true', + 'Driver': '2', + 'EmbedManagedResourceFile': 'file1;file2', + 'EnableCOMDATFolding': '2', + 'EnableUAC': 'true', + 'EntryPointSymbol': 'a string1', + 'ErrorReporting': '2', + 'FixedBaseAddress': '2', + 'ForceSymbolReferences': 'file1;file2', + 'FunctionOrder': 'a_file_name', + 'GenerateDebugInformation': 'true', + 'GenerateManifest': 'true', + 'GenerateMapFile': 'true', + 'HeapCommitSize': 'a string1', + 'HeapReserveSize': 'a string1', + 'IgnoreAllDefaultLibraries': 'true', + 'IgnoreDefaultLibraryNames': 'file1;file2', + 'IgnoreEmbeddedIDL': 'true', + 'IgnoreImportLibrary': 'true', + 'ImportLibrary': 'a_file_name', + 'KeyContainer': 'a_file_name', + 'KeyFile': 'a_file_name', + 'LargeAddressAware': '2', + 'LinkIncremental': '2', + 'LinkLibraryDependencies': 'true', + 'LinkTimeCodeGeneration': '2', + 'ManifestFile': 'a_file_name', + 'MapExports': 'true', + 'MapFileName': 'a_file_name', + 'MergedIDLBaseFileName': 'a_file_name', + 'MergeSections': 'a string1', + 'MidlCommandFile': 'a_file_name', + 'ModuleDefinitionFile': 'a_file_name', + 'OptimizeForWindows98': '1', + 'OptimizeReferences': '2', + 'OutputFile': 'a_file_name', + 'PerUserRedirection': 'true', + 'Profile': 'true', + 'ProfileGuidedDatabase': 'a_file_name', + 'ProgramDatabaseFile': 'a_file_name', + 'RandomizedBaseAddress': '2', + 'RegisterOutput': 'true', + 'ResourceOnlyDLL': 'true', + 'SetChecksum': 'true', + 'ShowProgress': '2', + 'StackCommitSize': 'a string1', + 'StackReserveSize': 'a string1', + 'StripPrivateSymbols': 'a_file_name', + 'SubSystem': '2', + 'SupportUnloadOfDelayLoadedDLL': 'true', + 'SuppressStartupBanner': 'true', + 'SwapRunFromCD': 'true', + 'SwapRunFromNet': 'true', + 'TargetMachine': '2', + 'TerminalServerAware': '2', + 'TurnOffAssemblyGeneration': 'true', + 'TypeLibraryFile': 'a_file_name', + 'TypeLibraryResourceID': '33', + 'UACExecutionLevel': '2', + 'UACUIAccess': 'true', + 'UseLibraryDependencyInputs': 'true', + 'UseUnicodeResponseFiles': 'true', + 'Version': 'a string1'}, + 'VCMIDLTool': { + 'AdditionalIncludeDirectories': 'folder1;folder2', + 'AdditionalOptions': 'a string1', + 'CPreprocessOptions': 'a string1', + 'DefaultCharType': '1', + 'DLLDataFileName': 'a_file_name', + 'EnableErrorChecks': '1', + 'ErrorCheckAllocations': 'true', + 'ErrorCheckBounds': 'true', + 'ErrorCheckEnumRange': 'true', + 'ErrorCheckRefPointers': 'true', + 'ErrorCheckStubData': 'true', + 'GenerateStublessProxies': 'true', + 'GenerateTypeLibrary': 'true', + 'HeaderFileName': 'a_file_name', + 'IgnoreStandardIncludePath': 'true', + 'InterfaceIdentifierFileName': 'a_file_name', + 'MkTypLibCompatible': 'true', + 'notgood': 'bogus', + 'OutputDirectory': 'a string1', + 'PreprocessorDefinitions': 'string1;string2', + 'ProxyFileName': 'a_file_name', + 'RedirectOutputAndErrors': 'a_file_name', + 'StructMemberAlignment': '1', + 'SuppressStartupBanner': 'true', + 'TargetEnvironment': '1', + 'TypeLibraryName': 'a_file_name', + 'UndefinePreprocessorDefinitions': 'string1;string2', + 'ValidateParameters': 'true', + 'WarnAsError': 'true', + 'WarningLevel': '1'}, + 'VCResourceCompilerTool': { + 'AdditionalOptions': 'a string1', + 'AdditionalIncludeDirectories': 'folder1;folder2', + 'Culture': '1003', + 'IgnoreStandardIncludePath': 'true', + 'notgood2': 'bogus', + 'PreprocessorDefinitions': 'string1;string2', + 'ResourceOutputFileName': 'a string1', + 'ShowProgress': 'true', + 'SuppressStartupBanner': 'true', + 'UndefinePreprocessorDefinitions': 'string1;string2'}, + 'VCLibrarianTool': { + 'AdditionalDependencies': 'file1;file2', + 'AdditionalLibraryDirectories': 'folder1;folder2', + 'AdditionalOptions': 'a string1', + 'ExportNamedFunctions': 'string1;string2', + 'ForceSymbolReferences': 'a string1', + 'IgnoreAllDefaultLibraries': 'true', + 'IgnoreSpecificDefaultLibraries': 'file1;file2', + 'LinkLibraryDependencies': 'true', + 'ModuleDefinitionFile': 'a_file_name', + 'OutputFile': 'a_file_name', + 'SuppressStartupBanner': 'true', + 'UseUnicodeResponseFiles': 'true'}, + 'VCManifestTool': { + 'AdditionalManifestFiles': 'file1;file2', + 'AdditionalOptions': 'a string1', + 'AssemblyIdentity': 'a string1', + 'ComponentFileName': 'a_file_name', + 'DependencyInformationFile': 'a_file_name', + 'GenerateCatalogFiles': 'true', + 'InputResourceManifests': 'a string1', + 'ManifestResourceFile': 'a_file_name', + 'OutputManifestFile': 'a_file_name', + 'RegistrarScriptFile': 'a_file_name', + 'ReplacementsFile': 'a_file_name', + 'SuppressStartupBanner': 'true', + 'TypeLibraryFile': 'a_file_name', + 'UpdateFileHashes': 'truel', + 'UpdateFileHashesSearchPath': 'a_file_name', + 'UseFAT32Workaround': 'true', + 'UseUnicodeResponseFiles': 'true', + 'VerboseOutput': 'true'}}, + self.stderr) + self._ExpectedWarnings([ + 'Warning: for VCCLCompilerTool/BasicRuntimeChecks, ' + 'index value (5) not in expected range [0, 4)', + 'Warning: for VCCLCompilerTool/BrowseInformation, ' + "invalid literal for int() with base 10: 'fdkslj'", + 'Warning: for VCCLCompilerTool/CallingConvention, ' + 'index value (-1) not in expected range [0, 4)', + 'Warning: for VCCLCompilerTool/DebugInformationFormat, ' + 'converted value for 2 not specified.', + 'Warning: unrecognized setting VCCLCompilerTool/Enableprefast', + 'Warning: unrecognized setting VCCLCompilerTool/ZZXYZ', + 'Warning: for VCLinkerTool/TargetMachine, ' + 'converted value for 2 not specified.', + 'Warning: unrecognized setting VCMIDLTool/notgood', + 'Warning: unrecognized setting VCResourceCompilerTool/notgood2', + 'Warning: for VCManifestTool/UpdateFileHashes, ' + "expected bool; got 'truel'" + '']) + + def testValidateMSBuildSettings_settings(self): + """Tests that for invalid MSBuild settings.""" + MSVSSettings.ValidateMSBuildSettings( + {'ClCompile': { + 'AdditionalIncludeDirectories': 'folder1;folder2', + 'AdditionalOptions': ['string1', 'string2'], + 'AdditionalUsingDirectories': 'folder1;folder2', + 'AssemblerListingLocation': 'a_file_name', + 'AssemblerOutput': 'NoListing', + 'BasicRuntimeChecks': 'StackFrameRuntimeCheck', + 'BrowseInformation': 'false', + 'BrowseInformationFile': 'a_file_name', + 'BufferSecurityCheck': 'true', + 'BuildingInIDE': 'true', + 'CallingConvention': 'Cdecl', + 'CompileAs': 'CompileAsC', + 'CompileAsManaged': 'true', + 'CreateHotpatchableImage': 'true', + 'DebugInformationFormat': 'ProgramDatabase', + 'DisableLanguageExtensions': 'true', + 'DisableSpecificWarnings': 'string1;string2', + 'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions', + 'EnableFiberSafeOptimizations': 'true', + 'EnablePREfast': 'true', + 'Enableprefast': 'bogus', + 'ErrorReporting': 'Prompt', + 'ExceptionHandling': 'SyncCThrow', + 'ExpandAttributedSource': 'true', + 'FavorSizeOrSpeed': 'Neither', + 'FloatingPointExceptions': 'true', + 'FloatingPointModel': 'Precise', + 'ForceConformanceInForLoopScope': 'true', + 'ForcedIncludeFiles': 'file1;file2', + 'ForcedUsingFiles': 'file1;file2', + 'FunctionLevelLinking': 'false', + 'GenerateXMLDocumentationFiles': 'true', + 'IgnoreStandardIncludePath': 'true', + 'InlineFunctionExpansion': 'OnlyExplicitInline', + 'IntrinsicFunctions': 'false', + 'MinimalRebuild': 'true', + 'MultiProcessorCompilation': 'true', + 'ObjectFileName': 'a_file_name', + 'OmitDefaultLibName': 'true', + 'OmitFramePointers': 'true', + 'OpenMPSupport': 'true', + 'Optimization': 'Disabled', + 'PrecompiledHeader': 'NotUsing', + 'PrecompiledHeaderFile': 'a_file_name', + 'PrecompiledHeaderOutputFile': 'a_file_name', + 'PreprocessKeepComments': 'true', + 'PreprocessorDefinitions': 'string1;string2', + 'PreprocessOutputPath': 'a string1', + 'PreprocessSuppressLineNumbers': 'false', + 'PreprocessToFile': 'false', + 'ProcessorNumber': '33', + 'ProgramDataBaseFileName': 'a_file_name', + 'RuntimeLibrary': 'MultiThreaded', + 'RuntimeTypeInfo': 'true', + 'ShowIncludes': 'true', + 'SmallerTypeCheck': 'true', + 'StringPooling': 'true', + 'StructMemberAlignment': '1Byte', + 'SuppressStartupBanner': 'true', + 'TrackerLogDirectory': 'a_folder', + 'TreatSpecificWarningsAsErrors': 'string1;string2', + 'TreatWarningAsError': 'true', + 'TreatWChar_tAsBuiltInType': 'true', + 'UndefineAllPreprocessorDefinitions': 'true', + 'UndefinePreprocessorDefinitions': 'string1;string2', + 'UseFullPaths': 'true', + 'UseUnicodeForAssemblerListing': 'true', + 'WarningLevel': 'TurnOffAllWarnings', + 'WholeProgramOptimization': 'true', + 'XMLDocumentationFileName': 'a_file_name', + 'ZZXYZ': 'bogus'}, + 'Link': { + 'AdditionalDependencies': 'file1;file2', + 'AdditionalLibraryDirectories': 'folder1;folder2', + 'AdditionalManifestDependencies': 'file1;file2', + 'AdditionalOptions': 'a string1', + 'AddModuleNamesToAssembly': 'file1;file2', + 'AllowIsolation': 'true', + 'AssemblyDebug': '', + 'AssemblyLinkResource': 'file1;file2', + 'BaseAddress': 'a string1', + 'BuildingInIDE': 'true', + 'CLRImageType': 'ForceIJWImage', + 'CLRSupportLastError': 'Enabled', + 'CLRThreadAttribute': 'MTAThreadingAttribute', + 'CLRUnmanagedCodeCheck': 'true', + 'CreateHotPatchableImage': 'X86Image', + 'DataExecutionPrevention': 'false', + 'DelayLoadDLLs': 'file1;file2', + 'DelaySign': 'true', + 'Driver': 'NotSet', + 'EmbedManagedResourceFile': 'file1;file2', + 'EnableCOMDATFolding': 'false', + 'EnableUAC': 'true', + 'EntryPointSymbol': 'a string1', + 'FixedBaseAddress': 'false', + 'ForceFileOutput': 'Enabled', + 'ForceSymbolReferences': 'file1;file2', + 'FunctionOrder': 'a_file_name', + 'GenerateDebugInformation': 'true', + 'GenerateMapFile': 'true', + 'HeapCommitSize': 'a string1', + 'HeapReserveSize': 'a string1', + 'IgnoreAllDefaultLibraries': 'true', + 'IgnoreEmbeddedIDL': 'true', + 'IgnoreSpecificDefaultLibraries': 'a_file_list', + 'ImageHasSafeExceptionHandlers': 'true', + 'ImportLibrary': 'a_file_name', + 'KeyContainer': 'a_file_name', + 'KeyFile': 'a_file_name', + 'LargeAddressAware': 'false', + 'LinkDLL': 'true', + 'LinkErrorReporting': 'SendErrorReport', + 'LinkStatus': 'true', + 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration', + 'ManifestFile': 'a_file_name', + 'MapExports': 'true', + 'MapFileName': 'a_file_name', + 'MergedIDLBaseFileName': 'a_file_name', + 'MergeSections': 'a string1', + 'MidlCommandFile': 'a_file_name', + 'MinimumRequiredVersion': 'a string1', + 'ModuleDefinitionFile': 'a_file_name', + 'MSDOSStubFileName': 'a_file_name', + 'NoEntryPoint': 'true', + 'OptimizeReferences': 'false', + 'OutputFile': 'a_file_name', + 'PerUserRedirection': 'true', + 'PreventDllBinding': 'true', + 'Profile': 'true', + 'ProfileGuidedDatabase': 'a_file_name', + 'ProgramDatabaseFile': 'a_file_name', + 'RandomizedBaseAddress': 'false', + 'RegisterOutput': 'true', + 'SectionAlignment': '33', + 'SetChecksum': 'true', + 'ShowProgress': 'LinkVerboseREF', + 'SpecifySectionAttributes': 'a string1', + 'StackCommitSize': 'a string1', + 'StackReserveSize': 'a string1', + 'StripPrivateSymbols': 'a_file_name', + 'SubSystem': 'Console', + 'SupportNobindOfDelayLoadedDLL': 'true', + 'SupportUnloadOfDelayLoadedDLL': 'true', + 'SuppressStartupBanner': 'true', + 'SwapRunFromCD': 'true', + 'SwapRunFromNET': 'true', + 'TargetMachine': 'MachineX86', + 'TerminalServerAware': 'false', + 'TrackerLogDirectory': 'a_folder', + 'TreatLinkerWarningAsErrors': 'true', + 'TurnOffAssemblyGeneration': 'true', + 'TypeLibraryFile': 'a_file_name', + 'TypeLibraryResourceID': '33', + 'UACExecutionLevel': 'AsInvoker', + 'UACUIAccess': 'true', + 'Version': 'a string1'}, + 'ResourceCompile': { + 'AdditionalIncludeDirectories': 'folder1;folder2', + 'AdditionalOptions': 'a string1', + 'Culture': '0x236', + 'IgnoreStandardIncludePath': 'true', + 'NullTerminateStrings': 'true', + 'PreprocessorDefinitions': 'string1;string2', + 'ResourceOutputFileName': 'a string1', + 'ShowProgress': 'true', + 'SuppressStartupBanner': 'true', + 'TrackerLogDirectory': 'a_folder', + 'UndefinePreprocessorDefinitions': 'string1;string2'}, + 'Midl': { + 'AdditionalIncludeDirectories': 'folder1;folder2', + 'AdditionalOptions': 'a string1', + 'ApplicationConfigurationMode': 'true', + 'ClientStubFile': 'a_file_name', + 'CPreprocessOptions': 'a string1', + 'DefaultCharType': 'Signed', + 'DllDataFileName': 'a_file_name', + 'EnableErrorChecks': 'EnableCustom', + 'ErrorCheckAllocations': 'true', + 'ErrorCheckBounds': 'true', + 'ErrorCheckEnumRange': 'true', + 'ErrorCheckRefPointers': 'true', + 'ErrorCheckStubData': 'true', + 'GenerateClientFiles': 'Stub', + 'GenerateServerFiles': 'None', + 'GenerateStublessProxies': 'true', + 'GenerateTypeLibrary': 'true', + 'HeaderFileName': 'a_file_name', + 'IgnoreStandardIncludePath': 'true', + 'InterfaceIdentifierFileName': 'a_file_name', + 'LocaleID': '33', + 'MkTypLibCompatible': 'true', + 'OutputDirectory': 'a string1', + 'PreprocessorDefinitions': 'string1;string2', + 'ProxyFileName': 'a_file_name', + 'RedirectOutputAndErrors': 'a_file_name', + 'ServerStubFile': 'a_file_name', + 'StructMemberAlignment': 'NotSet', + 'SuppressCompilerWarnings': 'true', + 'SuppressStartupBanner': 'true', + 'TargetEnvironment': 'Itanium', + 'TrackerLogDirectory': 'a_folder', + 'TypeLibFormat': 'NewFormat', + 'TypeLibraryName': 'a_file_name', + 'UndefinePreprocessorDefinitions': 'string1;string2', + 'ValidateAllParameters': 'true', + 'WarnAsError': 'true', + 'WarningLevel': '1'}, + 'Lib': { + 'AdditionalDependencies': 'file1;file2', + 'AdditionalLibraryDirectories': 'folder1;folder2', + 'AdditionalOptions': 'a string1', + 'DisplayLibrary': 'a string1', + 'ErrorReporting': 'PromptImmediately', + 'ExportNamedFunctions': 'string1;string2', + 'ForceSymbolReferences': 'a string1', + 'IgnoreAllDefaultLibraries': 'true', + 'IgnoreSpecificDefaultLibraries': 'file1;file2', + 'LinkTimeCodeGeneration': 'true', + 'MinimumRequiredVersion': 'a string1', + 'ModuleDefinitionFile': 'a_file_name', + 'Name': 'a_file_name', + 'OutputFile': 'a_file_name', + 'RemoveObjects': 'file1;file2', + 'SubSystem': 'Console', + 'SuppressStartupBanner': 'true', + 'TargetMachine': 'MachineX86i', + 'TrackerLogDirectory': 'a_folder', + 'TreatLibWarningAsErrors': 'true', + 'UseUnicodeResponseFiles': 'true', + 'Verbose': 'true'}, + 'Manifest': { + 'AdditionalManifestFiles': 'file1;file2', + 'AdditionalOptions': 'a string1', + 'AssemblyIdentity': 'a string1', + 'ComponentFileName': 'a_file_name', + 'EnableDPIAwareness': 'fal', + 'GenerateCatalogFiles': 'truel', + 'GenerateCategoryTags': 'true', + 'InputResourceManifests': 'a string1', + 'ManifestFromManagedAssembly': 'a_file_name', + 'notgood3': 'bogus', + 'OutputManifestFile': 'a_file_name', + 'OutputResourceManifests': 'a string1', + 'RegistrarScriptFile': 'a_file_name', + 'ReplacementsFile': 'a_file_name', + 'SuppressDependencyElement': 'true', + 'SuppressStartupBanner': 'true', + 'TrackerLogDirectory': 'a_folder', + 'TypeLibraryFile': 'a_file_name', + 'UpdateFileHashes': 'true', + 'UpdateFileHashesSearchPath': 'a_file_name', + 'VerboseOutput': 'true'}, + 'ProjectReference': { + 'LinkLibraryDependencies': 'true', + 'UseLibraryDependencyInputs': 'true'}, + 'ManifestResourceCompile': { + 'ResourceOutputFileName': 'a_file_name'}, + '': { + 'EmbedManifest': 'true', + 'GenerateManifest': 'true', + 'IgnoreImportLibrary': 'true', + 'LinkIncremental': 'false'}}, + self.stderr) + self._ExpectedWarnings([ + 'Warning: unrecognized setting ClCompile/Enableprefast', + 'Warning: unrecognized setting ClCompile/ZZXYZ', + 'Warning: unrecognized setting Manifest/notgood3', + 'Warning: for Manifest/GenerateCatalogFiles, ' + "expected bool; got 'truel'", + 'Warning: for Lib/TargetMachine, unrecognized enumerated value ' + 'MachineX86i', + "Warning: for Manifest/EnableDPIAwareness, expected bool; got 'fal'"]) + + def testConvertToMSBuildSettings_empty(self): + """Tests an empty conversion.""" + msvs_settings = {} + expected_msbuild_settings = {} + actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( + msvs_settings, + self.stderr) + self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) + self._ExpectedWarnings([]) + + def testConvertToMSBuildSettings_minimal(self): + """Tests a minimal conversion.""" + msvs_settings = { + 'VCCLCompilerTool': { + 'AdditionalIncludeDirectories': 'dir1', + 'AdditionalOptions': '/foo', + 'BasicRuntimeChecks': '0', + }, + 'VCLinkerTool': { + 'LinkTimeCodeGeneration': '1', + 'ErrorReporting': '1', + 'DataExecutionPrevention': '2', + }, + } + expected_msbuild_settings = { + 'ClCompile': { + 'AdditionalIncludeDirectories': 'dir1', + 'AdditionalOptions': '/foo', + 'BasicRuntimeChecks': 'Default', + }, + 'Link': { + 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration', + 'LinkErrorReporting': 'PromptImmediately', + 'DataExecutionPrevention': 'true', + }, + } + actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( + msvs_settings, + self.stderr) + self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) + self._ExpectedWarnings([]) + + def testConvertToMSBuildSettings_warnings(self): + """Tests conversion that generates warnings.""" + msvs_settings = { + 'VCCLCompilerTool': { + 'AdditionalIncludeDirectories': '1', + 'AdditionalOptions': '2', + # These are incorrect values: + 'BasicRuntimeChecks': '12', + 'BrowseInformation': '21', + 'UsePrecompiledHeader': '13', + 'GeneratePreprocessedFile': '14'}, + 'VCLinkerTool': { + # These are incorrect values: + 'Driver': '10', + 'LinkTimeCodeGeneration': '31', + 'ErrorReporting': '21', + 'FixedBaseAddress': '6'}, + 'VCResourceCompilerTool': { + # Custom + 'Culture': '1003'}} + expected_msbuild_settings = { + 'ClCompile': { + 'AdditionalIncludeDirectories': '1', + 'AdditionalOptions': '2'}, + 'Link': {}, + 'ResourceCompile': { + # Custom + 'Culture': '0x03eb'}} + actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( + msvs_settings, + self.stderr) + self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) + self._ExpectedWarnings([ + 'Warning: while converting VCCLCompilerTool/BasicRuntimeChecks to ' + 'MSBuild, index value (12) not in expected range [0, 4)', + 'Warning: while converting VCCLCompilerTool/BrowseInformation to ' + 'MSBuild, index value (21) not in expected range [0, 3)', + 'Warning: while converting VCCLCompilerTool/UsePrecompiledHeader to ' + 'MSBuild, index value (13) not in expected range [0, 3)', + 'Warning: while converting VCCLCompilerTool/GeneratePreprocessedFile to ' + 'MSBuild, value must be one of [0, 1, 2]; got 14', + + 'Warning: while converting VCLinkerTool/Driver to ' + 'MSBuild, index value (10) not in expected range [0, 4)', + 'Warning: while converting VCLinkerTool/LinkTimeCodeGeneration to ' + 'MSBuild, index value (31) not in expected range [0, 5)', + 'Warning: while converting VCLinkerTool/ErrorReporting to ' + 'MSBuild, index value (21) not in expected range [0, 3)', + 'Warning: while converting VCLinkerTool/FixedBaseAddress to ' + 'MSBuild, index value (6) not in expected range [0, 3)', + ]) + + def testConvertToMSBuildSettings_full_synthetic(self): + """Tests conversion of all the MSBuild settings.""" + msvs_settings = { + 'VCCLCompilerTool': { + 'AdditionalIncludeDirectories': 'folder1;folder2;folder3', + 'AdditionalOptions': 'a_string', + 'AdditionalUsingDirectories': 'folder1;folder2;folder3', + 'AssemblerListingLocation': 'a_file_name', + 'AssemblerOutput': '0', + 'BasicRuntimeChecks': '1', + 'BrowseInformation': '2', + 'BrowseInformationFile': 'a_file_name', + 'BufferSecurityCheck': 'true', + 'CallingConvention': '0', + 'CompileAs': '1', + 'DebugInformationFormat': '4', + 'DefaultCharIsUnsigned': 'true', + 'Detect64BitPortabilityProblems': 'true', + 'DisableLanguageExtensions': 'true', + 'DisableSpecificWarnings': 'd1;d2;d3', + 'EnableEnhancedInstructionSet': '0', + 'EnableFiberSafeOptimizations': 'true', + 'EnableFunctionLevelLinking': 'true', + 'EnableIntrinsicFunctions': 'true', + 'EnablePREfast': 'true', + 'ErrorReporting': '1', + 'ExceptionHandling': '2', + 'ExpandAttributedSource': 'true', + 'FavorSizeOrSpeed': '0', + 'FloatingPointExceptions': 'true', + 'FloatingPointModel': '1', + 'ForceConformanceInForLoopScope': 'true', + 'ForcedIncludeFiles': 'file1;file2;file3', + 'ForcedUsingFiles': 'file1;file2;file3', + 'GeneratePreprocessedFile': '1', + 'GenerateXMLDocumentationFiles': 'true', + 'IgnoreStandardIncludePath': 'true', + 'InlineFunctionExpansion': '2', + 'KeepComments': 'true', + 'MinimalRebuild': 'true', + 'ObjectFile': 'a_file_name', + 'OmitDefaultLibName': 'true', + 'OmitFramePointers': 'true', + 'OpenMP': 'true', + 'Optimization': '3', + 'PrecompiledHeaderFile': 'a_file_name', + 'PrecompiledHeaderThrough': 'a_file_name', + 'PreprocessorDefinitions': 'd1;d2;d3', + 'ProgramDataBaseFileName': 'a_file_name', + 'RuntimeLibrary': '0', + 'RuntimeTypeInfo': 'true', + 'ShowIncludes': 'true', + 'SmallerTypeCheck': 'true', + 'StringPooling': 'true', + 'StructMemberAlignment': '1', + 'SuppressStartupBanner': 'true', + 'TreatWChar_tAsBuiltInType': 'true', + 'UndefineAllPreprocessorDefinitions': 'true', + 'UndefinePreprocessorDefinitions': 'd1;d2;d3', + 'UseFullPaths': 'true', + 'UsePrecompiledHeader': '1', + 'UseUnicodeResponseFiles': 'true', + 'WarnAsError': 'true', + 'WarningLevel': '2', + 'WholeProgramOptimization': 'true', + 'XMLDocumentationFileName': 'a_file_name'}, + 'VCLinkerTool': { + 'AdditionalDependencies': 'file1;file2;file3', + 'AdditionalLibraryDirectories': 'folder1;folder2;folder3', + 'AdditionalLibraryDirectories_excluded': 'folder1;folder2;folder3', + 'AdditionalManifestDependencies': 'file1;file2;file3', + 'AdditionalOptions': 'a_string', + 'AddModuleNamesToAssembly': 'file1;file2;file3', + 'AllowIsolation': 'true', + 'AssemblyDebug': '0', + 'AssemblyLinkResource': 'file1;file2;file3', + 'BaseAddress': 'a_string', + 'CLRImageType': '1', + 'CLRThreadAttribute': '2', + 'CLRUnmanagedCodeCheck': 'true', + 'DataExecutionPrevention': '0', + 'DelayLoadDLLs': 'file1;file2;file3', + 'DelaySign': 'true', + 'Driver': '1', + 'EmbedManagedResourceFile': 'file1;file2;file3', + 'EnableCOMDATFolding': '0', + 'EnableUAC': 'true', + 'EntryPointSymbol': 'a_string', + 'ErrorReporting': '0', + 'FixedBaseAddress': '1', + 'ForceSymbolReferences': 'file1;file2;file3', + 'FunctionOrder': 'a_file_name', + 'GenerateDebugInformation': 'true', + 'GenerateManifest': 'true', + 'GenerateMapFile': 'true', + 'HeapCommitSize': 'a_string', + 'HeapReserveSize': 'a_string', + 'IgnoreAllDefaultLibraries': 'true', + 'IgnoreDefaultLibraryNames': 'file1;file2;file3', + 'IgnoreEmbeddedIDL': 'true', + 'IgnoreImportLibrary': 'true', + 'ImportLibrary': 'a_file_name', + 'KeyContainer': 'a_file_name', + 'KeyFile': 'a_file_name', + 'LargeAddressAware': '2', + 'LinkIncremental': '1', + 'LinkLibraryDependencies': 'true', + 'LinkTimeCodeGeneration': '2', + 'ManifestFile': 'a_file_name', + 'MapExports': 'true', + 'MapFileName': 'a_file_name', + 'MergedIDLBaseFileName': 'a_file_name', + 'MergeSections': 'a_string', + 'MidlCommandFile': 'a_file_name', + 'ModuleDefinitionFile': 'a_file_name', + 'OptimizeForWindows98': '1', + 'OptimizeReferences': '0', + 'OutputFile': 'a_file_name', + 'PerUserRedirection': 'true', + 'Profile': 'true', + 'ProfileGuidedDatabase': 'a_file_name', + 'ProgramDatabaseFile': 'a_file_name', + 'RandomizedBaseAddress': '1', + 'RegisterOutput': 'true', + 'ResourceOnlyDLL': 'true', + 'SetChecksum': 'true', + 'ShowProgress': '0', + 'StackCommitSize': 'a_string', + 'StackReserveSize': 'a_string', + 'StripPrivateSymbols': 'a_file_name', + 'SubSystem': '2', + 'SupportUnloadOfDelayLoadedDLL': 'true', + 'SuppressStartupBanner': 'true', + 'SwapRunFromCD': 'true', + 'SwapRunFromNet': 'true', + 'TargetMachine': '3', + 'TerminalServerAware': '2', + 'TurnOffAssemblyGeneration': 'true', + 'TypeLibraryFile': 'a_file_name', + 'TypeLibraryResourceID': '33', + 'UACExecutionLevel': '1', + 'UACUIAccess': 'true', + 'UseLibraryDependencyInputs': 'false', + 'UseUnicodeResponseFiles': 'true', + 'Version': 'a_string'}, + 'VCResourceCompilerTool': { + 'AdditionalIncludeDirectories': 'folder1;folder2;folder3', + 'AdditionalOptions': 'a_string', + 'Culture': '1003', + 'IgnoreStandardIncludePath': 'true', + 'PreprocessorDefinitions': 'd1;d2;d3', + 'ResourceOutputFileName': 'a_string', + 'ShowProgress': 'true', + 'SuppressStartupBanner': 'true', + 'UndefinePreprocessorDefinitions': 'd1;d2;d3'}, + 'VCMIDLTool': { + 'AdditionalIncludeDirectories': 'folder1;folder2;folder3', + 'AdditionalOptions': 'a_string', + 'CPreprocessOptions': 'a_string', + 'DefaultCharType': '0', + 'DLLDataFileName': 'a_file_name', + 'EnableErrorChecks': '2', + 'ErrorCheckAllocations': 'true', + 'ErrorCheckBounds': 'true', + 'ErrorCheckEnumRange': 'true', + 'ErrorCheckRefPointers': 'true', + 'ErrorCheckStubData': 'true', + 'GenerateStublessProxies': 'true', + 'GenerateTypeLibrary': 'true', + 'HeaderFileName': 'a_file_name', + 'IgnoreStandardIncludePath': 'true', + 'InterfaceIdentifierFileName': 'a_file_name', + 'MkTypLibCompatible': 'true', + 'OutputDirectory': 'a_string', + 'PreprocessorDefinitions': 'd1;d2;d3', + 'ProxyFileName': 'a_file_name', + 'RedirectOutputAndErrors': 'a_file_name', + 'StructMemberAlignment': '3', + 'SuppressStartupBanner': 'true', + 'TargetEnvironment': '1', + 'TypeLibraryName': 'a_file_name', + 'UndefinePreprocessorDefinitions': 'd1;d2;d3', + 'ValidateParameters': 'true', + 'WarnAsError': 'true', + 'WarningLevel': '4'}, + 'VCLibrarianTool': { + 'AdditionalDependencies': 'file1;file2;file3', + 'AdditionalLibraryDirectories': 'folder1;folder2;folder3', + 'AdditionalLibraryDirectories_excluded': 'folder1;folder2;folder3', + 'AdditionalOptions': 'a_string', + 'ExportNamedFunctions': 'd1;d2;d3', + 'ForceSymbolReferences': 'a_string', + 'IgnoreAllDefaultLibraries': 'true', + 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3', + 'LinkLibraryDependencies': 'true', + 'ModuleDefinitionFile': 'a_file_name', + 'OutputFile': 'a_file_name', + 'SuppressStartupBanner': 'true', + 'UseUnicodeResponseFiles': 'true'}, + 'VCManifestTool': { + 'AdditionalManifestFiles': 'file1;file2;file3', + 'AdditionalOptions': 'a_string', + 'AssemblyIdentity': 'a_string', + 'ComponentFileName': 'a_file_name', + 'DependencyInformationFile': 'a_file_name', + 'EmbedManifest': 'true', + 'GenerateCatalogFiles': 'true', + 'InputResourceManifests': 'a_string', + 'ManifestResourceFile': 'my_name', + 'OutputManifestFile': 'a_file_name', + 'RegistrarScriptFile': 'a_file_name', + 'ReplacementsFile': 'a_file_name', + 'SuppressStartupBanner': 'true', + 'TypeLibraryFile': 'a_file_name', + 'UpdateFileHashes': 'true', + 'UpdateFileHashesSearchPath': 'a_file_name', + 'UseFAT32Workaround': 'true', + 'UseUnicodeResponseFiles': 'true', + 'VerboseOutput': 'true'}} + expected_msbuild_settings = { + 'ClCompile': { + 'AdditionalIncludeDirectories': 'folder1;folder2;folder3', + 'AdditionalOptions': 'a_string /J', + 'AdditionalUsingDirectories': 'folder1;folder2;folder3', + 'AssemblerListingLocation': 'a_file_name', + 'AssemblerOutput': 'NoListing', + 'BasicRuntimeChecks': 'StackFrameRuntimeCheck', + 'BrowseInformation': 'true', + 'BrowseInformationFile': 'a_file_name', + 'BufferSecurityCheck': 'true', + 'CallingConvention': 'Cdecl', + 'CompileAs': 'CompileAsC', + 'DebugInformationFormat': 'EditAndContinue', + 'DisableLanguageExtensions': 'true', + 'DisableSpecificWarnings': 'd1;d2;d3', + 'EnableEnhancedInstructionSet': 'NotSet', + 'EnableFiberSafeOptimizations': 'true', + 'EnablePREfast': 'true', + 'ErrorReporting': 'Prompt', + 'ExceptionHandling': 'Async', + 'ExpandAttributedSource': 'true', + 'FavorSizeOrSpeed': 'Neither', + 'FloatingPointExceptions': 'true', + 'FloatingPointModel': 'Strict', + 'ForceConformanceInForLoopScope': 'true', + 'ForcedIncludeFiles': 'file1;file2;file3', + 'ForcedUsingFiles': 'file1;file2;file3', + 'FunctionLevelLinking': 'true', + 'GenerateXMLDocumentationFiles': 'true', + 'IgnoreStandardIncludePath': 'true', + 'InlineFunctionExpansion': 'AnySuitable', + 'IntrinsicFunctions': 'true', + 'MinimalRebuild': 'true', + 'ObjectFileName': 'a_file_name', + 'OmitDefaultLibName': 'true', + 'OmitFramePointers': 'true', + 'OpenMPSupport': 'true', + 'Optimization': 'Full', + 'PrecompiledHeader': 'Create', + 'PrecompiledHeaderFile': 'a_file_name', + 'PrecompiledHeaderOutputFile': 'a_file_name', + 'PreprocessKeepComments': 'true', + 'PreprocessorDefinitions': 'd1;d2;d3', + 'PreprocessSuppressLineNumbers': 'false', + 'PreprocessToFile': 'true', + 'ProgramDataBaseFileName': 'a_file_name', + 'RuntimeLibrary': 'MultiThreaded', + 'RuntimeTypeInfo': 'true', + 'ShowIncludes': 'true', + 'SmallerTypeCheck': 'true', + 'StringPooling': 'true', + 'StructMemberAlignment': '1Byte', + 'SuppressStartupBanner': 'true', + 'TreatWarningAsError': 'true', + 'TreatWChar_tAsBuiltInType': 'true', + 'UndefineAllPreprocessorDefinitions': 'true', + 'UndefinePreprocessorDefinitions': 'd1;d2;d3', + 'UseFullPaths': 'true', + 'WarningLevel': 'Level2', + 'WholeProgramOptimization': 'true', + 'XMLDocumentationFileName': 'a_file_name'}, + 'Link': { + 'AdditionalDependencies': 'file1;file2;file3', + 'AdditionalLibraryDirectories': 'folder1;folder2;folder3', + 'AdditionalManifestDependencies': 'file1;file2;file3', + 'AdditionalOptions': 'a_string', + 'AddModuleNamesToAssembly': 'file1;file2;file3', + 'AllowIsolation': 'true', + 'AssemblyDebug': '', + 'AssemblyLinkResource': 'file1;file2;file3', + 'BaseAddress': 'a_string', + 'CLRImageType': 'ForceIJWImage', + 'CLRThreadAttribute': 'STAThreadingAttribute', + 'CLRUnmanagedCodeCheck': 'true', + 'DataExecutionPrevention': '', + 'DelayLoadDLLs': 'file1;file2;file3', + 'DelaySign': 'true', + 'Driver': 'Driver', + 'EmbedManagedResourceFile': 'file1;file2;file3', + 'EnableCOMDATFolding': '', + 'EnableUAC': 'true', + 'EntryPointSymbol': 'a_string', + 'FixedBaseAddress': 'false', + 'ForceSymbolReferences': 'file1;file2;file3', + 'FunctionOrder': 'a_file_name', + 'GenerateDebugInformation': 'true', + 'GenerateMapFile': 'true', + 'HeapCommitSize': 'a_string', + 'HeapReserveSize': 'a_string', + 'IgnoreAllDefaultLibraries': 'true', + 'IgnoreEmbeddedIDL': 'true', + 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3', + 'ImportLibrary': 'a_file_name', + 'KeyContainer': 'a_file_name', + 'KeyFile': 'a_file_name', + 'LargeAddressAware': 'true', + 'LinkErrorReporting': 'NoErrorReport', + 'LinkTimeCodeGeneration': 'PGInstrument', + 'ManifestFile': 'a_file_name', + 'MapExports': 'true', + 'MapFileName': 'a_file_name', + 'MergedIDLBaseFileName': 'a_file_name', + 'MergeSections': 'a_string', + 'MidlCommandFile': 'a_file_name', + 'ModuleDefinitionFile': 'a_file_name', + 'NoEntryPoint': 'true', + 'OptimizeReferences': '', + 'OutputFile': 'a_file_name', + 'PerUserRedirection': 'true', + 'Profile': 'true', + 'ProfileGuidedDatabase': 'a_file_name', + 'ProgramDatabaseFile': 'a_file_name', + 'RandomizedBaseAddress': 'false', + 'RegisterOutput': 'true', + 'SetChecksum': 'true', + 'ShowProgress': 'NotSet', + 'StackCommitSize': 'a_string', + 'StackReserveSize': 'a_string', + 'StripPrivateSymbols': 'a_file_name', + 'SubSystem': 'Windows', + 'SupportUnloadOfDelayLoadedDLL': 'true', + 'SuppressStartupBanner': 'true', + 'SwapRunFromCD': 'true', + 'SwapRunFromNET': 'true', + 'TargetMachine': 'MachineARM', + 'TerminalServerAware': 'true', + 'TurnOffAssemblyGeneration': 'true', + 'TypeLibraryFile': 'a_file_name', + 'TypeLibraryResourceID': '33', + 'UACExecutionLevel': 'HighestAvailable', + 'UACUIAccess': 'true', + 'Version': 'a_string'}, + 'ResourceCompile': { + 'AdditionalIncludeDirectories': 'folder1;folder2;folder3', + 'AdditionalOptions': 'a_string', + 'Culture': '0x03eb', + 'IgnoreStandardIncludePath': 'true', + 'PreprocessorDefinitions': 'd1;d2;d3', + 'ResourceOutputFileName': 'a_string', + 'ShowProgress': 'true', + 'SuppressStartupBanner': 'true', + 'UndefinePreprocessorDefinitions': 'd1;d2;d3'}, + 'Midl': { + 'AdditionalIncludeDirectories': 'folder1;folder2;folder3', + 'AdditionalOptions': 'a_string', + 'CPreprocessOptions': 'a_string', + 'DefaultCharType': 'Unsigned', + 'DllDataFileName': 'a_file_name', + 'EnableErrorChecks': 'All', + 'ErrorCheckAllocations': 'true', + 'ErrorCheckBounds': 'true', + 'ErrorCheckEnumRange': 'true', + 'ErrorCheckRefPointers': 'true', + 'ErrorCheckStubData': 'true', + 'GenerateStublessProxies': 'true', + 'GenerateTypeLibrary': 'true', + 'HeaderFileName': 'a_file_name', + 'IgnoreStandardIncludePath': 'true', + 'InterfaceIdentifierFileName': 'a_file_name', + 'MkTypLibCompatible': 'true', + 'OutputDirectory': 'a_string', + 'PreprocessorDefinitions': 'd1;d2;d3', + 'ProxyFileName': 'a_file_name', + 'RedirectOutputAndErrors': 'a_file_name', + 'StructMemberAlignment': '4', + 'SuppressStartupBanner': 'true', + 'TargetEnvironment': 'Win32', + 'TypeLibraryName': 'a_file_name', + 'UndefinePreprocessorDefinitions': 'd1;d2;d3', + 'ValidateAllParameters': 'true', + 'WarnAsError': 'true', + 'WarningLevel': '4'}, + 'Lib': { + 'AdditionalDependencies': 'file1;file2;file3', + 'AdditionalLibraryDirectories': 'folder1;folder2;folder3', + 'AdditionalOptions': 'a_string', + 'ExportNamedFunctions': 'd1;d2;d3', + 'ForceSymbolReferences': 'a_string', + 'IgnoreAllDefaultLibraries': 'true', + 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3', + 'ModuleDefinitionFile': 'a_file_name', + 'OutputFile': 'a_file_name', + 'SuppressStartupBanner': 'true', + 'UseUnicodeResponseFiles': 'true'}, + 'Manifest': { + 'AdditionalManifestFiles': 'file1;file2;file3', + 'AdditionalOptions': 'a_string', + 'AssemblyIdentity': 'a_string', + 'ComponentFileName': 'a_file_name', + 'GenerateCatalogFiles': 'true', + 'InputResourceManifests': 'a_string', + 'OutputManifestFile': 'a_file_name', + 'RegistrarScriptFile': 'a_file_name', + 'ReplacementsFile': 'a_file_name', + 'SuppressStartupBanner': 'true', + 'TypeLibraryFile': 'a_file_name', + 'UpdateFileHashes': 'true', + 'UpdateFileHashesSearchPath': 'a_file_name', + 'VerboseOutput': 'true'}, + 'ManifestResourceCompile': { + 'ResourceOutputFileName': 'my_name'}, + 'ProjectReference': { + 'LinkLibraryDependencies': 'true', + 'UseLibraryDependencyInputs': 'false'}, + '': { + 'EmbedManifest': 'true', + 'GenerateManifest': 'true', + 'IgnoreImportLibrary': 'true', + 'LinkIncremental': 'false'}} + actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( + msvs_settings, + self.stderr) + self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) + self._ExpectedWarnings([]) + + def testConvertToMSBuildSettings_actual(self): + """Tests the conversion of an actual project. + + A VS2008 project with most of the options defined was created through the + VS2008 IDE. It was then converted to VS2010. The tool settings found in + the .vcproj and .vcxproj files were converted to the two dictionaries + msvs_settings and expected_msbuild_settings. + + Note that for many settings, the VS2010 converter adds macros like + %(AdditionalIncludeDirectories) to make sure than inherited values are + included. Since the Gyp projects we generate do not use inheritance, + we removed these macros. They were: + ClCompile: + AdditionalIncludeDirectories: ';%(AdditionalIncludeDirectories)' + AdditionalOptions: ' %(AdditionalOptions)' + AdditionalUsingDirectories: ';%(AdditionalUsingDirectories)' + DisableSpecificWarnings: ';%(DisableSpecificWarnings)', + ForcedIncludeFiles: ';%(ForcedIncludeFiles)', + ForcedUsingFiles: ';%(ForcedUsingFiles)', + PreprocessorDefinitions: ';%(PreprocessorDefinitions)', + UndefinePreprocessorDefinitions: + ';%(UndefinePreprocessorDefinitions)', + Link: + AdditionalDependencies: ';%(AdditionalDependencies)', + AdditionalLibraryDirectories: ';%(AdditionalLibraryDirectories)', + AdditionalManifestDependencies: + ';%(AdditionalManifestDependencies)', + AdditionalOptions: ' %(AdditionalOptions)', + AddModuleNamesToAssembly: ';%(AddModuleNamesToAssembly)', + AssemblyLinkResource: ';%(AssemblyLinkResource)', + DelayLoadDLLs: ';%(DelayLoadDLLs)', + EmbedManagedResourceFile: ';%(EmbedManagedResourceFile)', + ForceSymbolReferences: ';%(ForceSymbolReferences)', + IgnoreSpecificDefaultLibraries: + ';%(IgnoreSpecificDefaultLibraries)', + ResourceCompile: + AdditionalIncludeDirectories: ';%(AdditionalIncludeDirectories)', + AdditionalOptions: ' %(AdditionalOptions)', + PreprocessorDefinitions: ';%(PreprocessorDefinitions)', + Manifest: + AdditionalManifestFiles: ';%(AdditionalManifestFiles)', + AdditionalOptions: ' %(AdditionalOptions)', + InputResourceManifests: ';%(InputResourceManifests)', + """ + msvs_settings = { + 'VCCLCompilerTool': { + 'AdditionalIncludeDirectories': 'dir1', + 'AdditionalOptions': '/more', + 'AdditionalUsingDirectories': 'test', + 'AssemblerListingLocation': '$(IntDir)\\a', + 'AssemblerOutput': '1', + 'BasicRuntimeChecks': '3', + 'BrowseInformation': '1', + 'BrowseInformationFile': '$(IntDir)\\e', + 'BufferSecurityCheck': 'false', + 'CallingConvention': '1', + 'CompileAs': '1', + 'DebugInformationFormat': '4', + 'DefaultCharIsUnsigned': 'true', + 'Detect64BitPortabilityProblems': 'true', + 'DisableLanguageExtensions': 'true', + 'DisableSpecificWarnings': 'abc', + 'EnableEnhancedInstructionSet': '1', + 'EnableFiberSafeOptimizations': 'true', + 'EnableFunctionLevelLinking': 'true', + 'EnableIntrinsicFunctions': 'true', + 'EnablePREfast': 'true', + 'ErrorReporting': '2', + 'ExceptionHandling': '2', + 'ExpandAttributedSource': 'true', + 'FavorSizeOrSpeed': '2', + 'FloatingPointExceptions': 'true', + 'FloatingPointModel': '1', + 'ForceConformanceInForLoopScope': 'false', + 'ForcedIncludeFiles': 'def', + 'ForcedUsingFiles': 'ge', + 'GeneratePreprocessedFile': '2', + 'GenerateXMLDocumentationFiles': 'true', + 'IgnoreStandardIncludePath': 'true', + 'InlineFunctionExpansion': '1', + 'KeepComments': 'true', + 'MinimalRebuild': 'true', + 'ObjectFile': '$(IntDir)\\b', + 'OmitDefaultLibName': 'true', + 'OmitFramePointers': 'true', + 'OpenMP': 'true', + 'Optimization': '3', + 'PrecompiledHeaderFile': '$(IntDir)\\$(TargetName).pche', + 'PrecompiledHeaderThrough': 'StdAfx.hd', + 'PreprocessorDefinitions': 'WIN32;_DEBUG;_CONSOLE', + 'ProgramDataBaseFileName': '$(IntDir)\\vc90b.pdb', + 'RuntimeLibrary': '3', + 'RuntimeTypeInfo': 'false', + 'ShowIncludes': 'true', + 'SmallerTypeCheck': 'true', + 'StringPooling': 'true', + 'StructMemberAlignment': '3', + 'SuppressStartupBanner': 'false', + 'TreatWChar_tAsBuiltInType': 'false', + 'UndefineAllPreprocessorDefinitions': 'true', + 'UndefinePreprocessorDefinitions': 'wer', + 'UseFullPaths': 'true', + 'UsePrecompiledHeader': '0', + 'UseUnicodeResponseFiles': 'false', + 'WarnAsError': 'true', + 'WarningLevel': '3', + 'WholeProgramOptimization': 'true', + 'XMLDocumentationFileName': '$(IntDir)\\c'}, + 'VCLinkerTool': { + 'AdditionalDependencies': 'zx', + 'AdditionalLibraryDirectories': 'asd', + 'AdditionalManifestDependencies': 's2', + 'AdditionalOptions': '/mor2', + 'AddModuleNamesToAssembly': 'd1', + 'AllowIsolation': 'false', + 'AssemblyDebug': '1', + 'AssemblyLinkResource': 'd5', + 'BaseAddress': '23423', + 'CLRImageType': '3', + 'CLRThreadAttribute': '1', + 'CLRUnmanagedCodeCheck': 'true', + 'DataExecutionPrevention': '0', + 'DelayLoadDLLs': 'd4', + 'DelaySign': 'true', + 'Driver': '2', + 'EmbedManagedResourceFile': 'd2', + 'EnableCOMDATFolding': '1', + 'EnableUAC': 'false', + 'EntryPointSymbol': 'f5', + 'ErrorReporting': '2', + 'FixedBaseAddress': '1', + 'ForceSymbolReferences': 'd3', + 'FunctionOrder': 'fssdfsd', + 'GenerateDebugInformation': 'true', + 'GenerateManifest': 'false', + 'GenerateMapFile': 'true', + 'HeapCommitSize': '13', + 'HeapReserveSize': '12', + 'IgnoreAllDefaultLibraries': 'true', + 'IgnoreDefaultLibraryNames': 'flob;flok', + 'IgnoreEmbeddedIDL': 'true', + 'IgnoreImportLibrary': 'true', + 'ImportLibrary': 'f4', + 'KeyContainer': 'f7', + 'KeyFile': 'f6', + 'LargeAddressAware': '2', + 'LinkIncremental': '0', + 'LinkLibraryDependencies': 'false', + 'LinkTimeCodeGeneration': '1', + 'ManifestFile': + '$(IntDir)\\$(TargetFileName).2intermediate.manifest', + 'MapExports': 'true', + 'MapFileName': 'd5', + 'MergedIDLBaseFileName': 'f2', + 'MergeSections': 'f5', + 'MidlCommandFile': 'f1', + 'ModuleDefinitionFile': 'sdsd', + 'OptimizeForWindows98': '2', + 'OptimizeReferences': '2', + 'OutputFile': '$(OutDir)\\$(ProjectName)2.exe', + 'PerUserRedirection': 'true', + 'Profile': 'true', + 'ProfileGuidedDatabase': '$(TargetDir)$(TargetName).pgdd', + 'ProgramDatabaseFile': 'Flob.pdb', + 'RandomizedBaseAddress': '1', + 'RegisterOutput': 'true', + 'ResourceOnlyDLL': 'true', + 'SetChecksum': 'false', + 'ShowProgress': '1', + 'StackCommitSize': '15', + 'StackReserveSize': '14', + 'StripPrivateSymbols': 'd3', + 'SubSystem': '1', + 'SupportUnloadOfDelayLoadedDLL': 'true', + 'SuppressStartupBanner': 'false', + 'SwapRunFromCD': 'true', + 'SwapRunFromNet': 'true', + 'TargetMachine': '1', + 'TerminalServerAware': '1', + 'TurnOffAssemblyGeneration': 'true', + 'TypeLibraryFile': 'f3', + 'TypeLibraryResourceID': '12', + 'UACExecutionLevel': '2', + 'UACUIAccess': 'true', + 'UseLibraryDependencyInputs': 'true', + 'UseUnicodeResponseFiles': 'false', + 'Version': '333'}, + 'VCResourceCompilerTool': { + 'AdditionalIncludeDirectories': 'f3', + 'AdditionalOptions': '/more3', + 'Culture': '3084', + 'IgnoreStandardIncludePath': 'true', + 'PreprocessorDefinitions': '_UNICODE;UNICODE2', + 'ResourceOutputFileName': '$(IntDir)/$(InputName)3.res', + 'ShowProgress': 'true'}, + 'VCManifestTool': { + 'AdditionalManifestFiles': 'sfsdfsd', + 'AdditionalOptions': 'afdsdafsd', + 'AssemblyIdentity': 'sddfdsadfsa', + 'ComponentFileName': 'fsdfds', + 'DependencyInformationFile': '$(IntDir)\\mt.depdfd', + 'EmbedManifest': 'false', + 'GenerateCatalogFiles': 'true', + 'InputResourceManifests': 'asfsfdafs', + 'ManifestResourceFile': + '$(IntDir)\\$(TargetFileName).embed.manifest.resfdsf', + 'OutputManifestFile': '$(TargetPath).manifestdfs', + 'RegistrarScriptFile': 'sdfsfd', + 'ReplacementsFile': 'sdffsd', + 'SuppressStartupBanner': 'false', + 'TypeLibraryFile': 'sfsd', + 'UpdateFileHashes': 'true', + 'UpdateFileHashesSearchPath': 'sfsd', + 'UseFAT32Workaround': 'true', + 'UseUnicodeResponseFiles': 'false', + 'VerboseOutput': 'true'}} + expected_msbuild_settings = { + 'ClCompile': { + 'AdditionalIncludeDirectories': 'dir1', + 'AdditionalOptions': '/more /J', + 'AdditionalUsingDirectories': 'test', + 'AssemblerListingLocation': '$(IntDir)a', + 'AssemblerOutput': 'AssemblyCode', + 'BasicRuntimeChecks': 'EnableFastChecks', + 'BrowseInformation': 'true', + 'BrowseInformationFile': '$(IntDir)e', + 'BufferSecurityCheck': 'false', + 'CallingConvention': 'FastCall', + 'CompileAs': 'CompileAsC', + 'DebugInformationFormat': 'EditAndContinue', + 'DisableLanguageExtensions': 'true', + 'DisableSpecificWarnings': 'abc', + 'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions', + 'EnableFiberSafeOptimizations': 'true', + 'EnablePREfast': 'true', + 'ErrorReporting': 'Queue', + 'ExceptionHandling': 'Async', + 'ExpandAttributedSource': 'true', + 'FavorSizeOrSpeed': 'Size', + 'FloatingPointExceptions': 'true', + 'FloatingPointModel': 'Strict', + 'ForceConformanceInForLoopScope': 'false', + 'ForcedIncludeFiles': 'def', + 'ForcedUsingFiles': 'ge', + 'FunctionLevelLinking': 'true', + 'GenerateXMLDocumentationFiles': 'true', + 'IgnoreStandardIncludePath': 'true', + 'InlineFunctionExpansion': 'OnlyExplicitInline', + 'IntrinsicFunctions': 'true', + 'MinimalRebuild': 'true', + 'ObjectFileName': '$(IntDir)b', + 'OmitDefaultLibName': 'true', + 'OmitFramePointers': 'true', + 'OpenMPSupport': 'true', + 'Optimization': 'Full', + 'PrecompiledHeader': 'NotUsing', # Actual conversion gives '' + 'PrecompiledHeaderFile': 'StdAfx.hd', + 'PrecompiledHeaderOutputFile': '$(IntDir)$(TargetName).pche', + 'PreprocessKeepComments': 'true', + 'PreprocessorDefinitions': 'WIN32;_DEBUG;_CONSOLE', + 'PreprocessSuppressLineNumbers': 'true', + 'PreprocessToFile': 'true', + 'ProgramDataBaseFileName': '$(IntDir)vc90b.pdb', + 'RuntimeLibrary': 'MultiThreadedDebugDLL', + 'RuntimeTypeInfo': 'false', + 'ShowIncludes': 'true', + 'SmallerTypeCheck': 'true', + 'StringPooling': 'true', + 'StructMemberAlignment': '4Bytes', + 'SuppressStartupBanner': 'false', + 'TreatWarningAsError': 'true', + 'TreatWChar_tAsBuiltInType': 'false', + 'UndefineAllPreprocessorDefinitions': 'true', + 'UndefinePreprocessorDefinitions': 'wer', + 'UseFullPaths': 'true', + 'WarningLevel': 'Level3', + 'WholeProgramOptimization': 'true', + 'XMLDocumentationFileName': '$(IntDir)c'}, + 'Link': { + 'AdditionalDependencies': 'zx', + 'AdditionalLibraryDirectories': 'asd', + 'AdditionalManifestDependencies': 's2', + 'AdditionalOptions': '/mor2', + 'AddModuleNamesToAssembly': 'd1', + 'AllowIsolation': 'false', + 'AssemblyDebug': 'true', + 'AssemblyLinkResource': 'd5', + 'BaseAddress': '23423', + 'CLRImageType': 'ForceSafeILImage', + 'CLRThreadAttribute': 'MTAThreadingAttribute', + 'CLRUnmanagedCodeCheck': 'true', + 'DataExecutionPrevention': '', + 'DelayLoadDLLs': 'd4', + 'DelaySign': 'true', + 'Driver': 'UpOnly', + 'EmbedManagedResourceFile': 'd2', + 'EnableCOMDATFolding': 'false', + 'EnableUAC': 'false', + 'EntryPointSymbol': 'f5', + 'FixedBaseAddress': 'false', + 'ForceSymbolReferences': 'd3', + 'FunctionOrder': 'fssdfsd', + 'GenerateDebugInformation': 'true', + 'GenerateMapFile': 'true', + 'HeapCommitSize': '13', + 'HeapReserveSize': '12', + 'IgnoreAllDefaultLibraries': 'true', + 'IgnoreEmbeddedIDL': 'true', + 'IgnoreSpecificDefaultLibraries': 'flob;flok', + 'ImportLibrary': 'f4', + 'KeyContainer': 'f7', + 'KeyFile': 'f6', + 'LargeAddressAware': 'true', + 'LinkErrorReporting': 'QueueForNextLogin', + 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration', + 'ManifestFile': '$(IntDir)$(TargetFileName).2intermediate.manifest', + 'MapExports': 'true', + 'MapFileName': 'd5', + 'MergedIDLBaseFileName': 'f2', + 'MergeSections': 'f5', + 'MidlCommandFile': 'f1', + 'ModuleDefinitionFile': 'sdsd', + 'NoEntryPoint': 'true', + 'OptimizeReferences': 'true', + 'OutputFile': '$(OutDir)$(ProjectName)2.exe', + 'PerUserRedirection': 'true', + 'Profile': 'true', + 'ProfileGuidedDatabase': '$(TargetDir)$(TargetName).pgdd', + 'ProgramDatabaseFile': 'Flob.pdb', + 'RandomizedBaseAddress': 'false', + 'RegisterOutput': 'true', + 'SetChecksum': 'false', + 'ShowProgress': 'LinkVerbose', + 'StackCommitSize': '15', + 'StackReserveSize': '14', + 'StripPrivateSymbols': 'd3', + 'SubSystem': 'Console', + 'SupportUnloadOfDelayLoadedDLL': 'true', + 'SuppressStartupBanner': 'false', + 'SwapRunFromCD': 'true', + 'SwapRunFromNET': 'true', + 'TargetMachine': 'MachineX86', + 'TerminalServerAware': 'false', + 'TurnOffAssemblyGeneration': 'true', + 'TypeLibraryFile': 'f3', + 'TypeLibraryResourceID': '12', + 'UACExecutionLevel': 'RequireAdministrator', + 'UACUIAccess': 'true', + 'Version': '333'}, + 'ResourceCompile': { + 'AdditionalIncludeDirectories': 'f3', + 'AdditionalOptions': '/more3', + 'Culture': '0x0c0c', + 'IgnoreStandardIncludePath': 'true', + 'PreprocessorDefinitions': '_UNICODE;UNICODE2', + 'ResourceOutputFileName': '$(IntDir)%(Filename)3.res', + 'ShowProgress': 'true'}, + 'Manifest': { + 'AdditionalManifestFiles': 'sfsdfsd', + 'AdditionalOptions': 'afdsdafsd', + 'AssemblyIdentity': 'sddfdsadfsa', + 'ComponentFileName': 'fsdfds', + 'GenerateCatalogFiles': 'true', + 'InputResourceManifests': 'asfsfdafs', + 'OutputManifestFile': '$(TargetPath).manifestdfs', + 'RegistrarScriptFile': 'sdfsfd', + 'ReplacementsFile': 'sdffsd', + 'SuppressStartupBanner': 'false', + 'TypeLibraryFile': 'sfsd', + 'UpdateFileHashes': 'true', + 'UpdateFileHashesSearchPath': 'sfsd', + 'VerboseOutput': 'true'}, + 'ProjectReference': { + 'LinkLibraryDependencies': 'false', + 'UseLibraryDependencyInputs': 'true'}, + '': { + 'EmbedManifest': 'false', + 'GenerateManifest': 'false', + 'IgnoreImportLibrary': 'true', + 'LinkIncremental': '' + }, + 'ManifestResourceCompile': { + 'ResourceOutputFileName': + '$(IntDir)$(TargetFileName).embed.manifest.resfdsf'} + } + actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( + msvs_settings, + self.stderr) + self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) + self._ExpectedWarnings([]) + + +if __name__ == '__main__': + unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py new file mode 100644 index 0000000000000..74e529a17f1dc --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py @@ -0,0 +1,58 @@ +# Copyright (c) 2012 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. + +"""Visual Studio project reader/writer.""" + +import gyp.common +import gyp.easy_xml as easy_xml + + +class Writer(object): + """Visual Studio XML tool file writer.""" + + def __init__(self, tool_file_path, name): + """Initializes the tool file. + + Args: + tool_file_path: Path to the tool file. + name: Name of the tool file. + """ + self.tool_file_path = tool_file_path + self.name = name + self.rules_section = ['Rules'] + + def AddCustomBuildRule(self, name, cmd, description, + additional_dependencies, + outputs, extensions): + """Adds a rule to the tool file. + + Args: + name: Name of the rule. + description: Description of the rule. + cmd: Command line of the rule. + additional_dependencies: other files which may trigger the rule. + outputs: outputs of the rule. + extensions: extensions handled by the rule. + """ + rule = ['CustomBuildRule', + {'Name': name, + 'ExecutionDescription': description, + 'CommandLine': cmd, + 'Outputs': ';'.join(outputs), + 'FileExtensions': ';'.join(extensions), + 'AdditionalDependencies': + ';'.join(additional_dependencies) + }] + self.rules_section.append(rule) + + def WriteIfChanged(self): + """Writes the tool file.""" + content = ['VisualStudioToolFile', + {'Version': '8.00', + 'Name': self.name + }, + self.rules_section + ] + easy_xml.WriteXmlIfChanged(content, self.tool_file_path, + encoding="Windows-1252") diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py new file mode 100644 index 0000000000000..6c07e9a893bac --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py @@ -0,0 +1,147 @@ +# Copyright (c) 2012 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. + +"""Visual Studio user preferences file writer.""" + +import os +import re +import socket # for gethostname + +import gyp.common +import gyp.easy_xml as easy_xml + + +#------------------------------------------------------------------------------ + +def _FindCommandInPath(command): + """If there are no slashes in the command given, this function + searches the PATH env to find the given command, and converts it + to an absolute path. We have to do this because MSVS is looking + for an actual file to launch a debugger on, not just a command + line. Note that this happens at GYP time, so anything needing to + be built needs to have a full path.""" + if '/' in command or '\\' in command: + # If the command already has path elements (either relative or + # absolute), then assume it is constructed properly. + return command + else: + # Search through the path list and find an existing file that + # we can access. + paths = os.environ.get('PATH','').split(os.pathsep) + for path in paths: + item = os.path.join(path, command) + if os.path.isfile(item) and os.access(item, os.X_OK): + return item + return command + +def _QuoteWin32CommandLineArgs(args): + new_args = [] + for arg in args: + # Replace all double-quotes with double-double-quotes to escape + # them for cmd shell, and then quote the whole thing if there + # are any. + if arg.find('"') != -1: + arg = '""'.join(arg.split('"')) + arg = '"%s"' % arg + + # Otherwise, if there are any spaces, quote the whole arg. + elif re.search(r'[ \t\n]', arg): + arg = '"%s"' % arg + new_args.append(arg) + return new_args + +class Writer(object): + """Visual Studio XML user user file writer.""" + + def __init__(self, user_file_path, version, name): + """Initializes the user file. + + Args: + user_file_path: Path to the user file. + version: Version info. + name: Name of the user file. + """ + self.user_file_path = user_file_path + self.version = version + self.name = name + self.configurations = {} + + def AddConfig(self, name): + """Adds a configuration to the project. + + Args: + name: Configuration name. + """ + self.configurations[name] = ['Configuration', {'Name': name}] + + def AddDebugSettings(self, config_name, command, environment = {}, + working_directory=""): + """Adds a DebugSettings node to the user file for a particular config. + + Args: + command: command line to run. First element in the list is the + executable. All elements of the command will be quoted if + necessary. + working_directory: other files which may trigger the rule. (optional) + """ + command = _QuoteWin32CommandLineArgs(command) + + abs_command = _FindCommandInPath(command[0]) + + if environment and isinstance(environment, dict): + env_list = ['%s="%s"' % (key, val) + for (key,val) in environment.iteritems()] + environment = ' '.join(env_list) + else: + environment = '' + + n_cmd = ['DebugSettings', + {'Command': abs_command, + 'WorkingDirectory': working_directory, + 'CommandArguments': " ".join(command[1:]), + 'RemoteMachine': socket.gethostname(), + 'Environment': environment, + 'EnvironmentMerge': 'true', + # Currently these are all "dummy" values that we're just setting + # in the default manner that MSVS does it. We could use some of + # these to add additional capabilities, I suppose, but they might + # not have parity with other platforms then. + 'Attach': 'false', + 'DebuggerType': '3', # 'auto' debugger + 'Remote': '1', + 'RemoteCommand': '', + 'HttpUrl': '', + 'PDBPath': '', + 'SQLDebugging': '', + 'DebuggerFlavor': '0', + 'MPIRunCommand': '', + 'MPIRunArguments': '', + 'MPIRunWorkingDirectory': '', + 'ApplicationCommand': '', + 'ApplicationArguments': '', + 'ShimCommand': '', + 'MPIAcceptMode': '', + 'MPIAcceptFilter': '' + }] + + # Find the config, and add it if it doesn't exist. + if config_name not in self.configurations: + self.AddConfig(config_name) + + # Add the DebugSettings onto the appropriate config. + self.configurations[config_name].append(n_cmd) + + def WriteIfChanged(self): + """Writes the user file.""" + configs = ['Configurations'] + for config, spec in sorted(self.configurations.iteritems()): + configs.append(spec) + + content = ['VisualStudioUserFile', + {'Version': self.version.ProjectVersion(), + 'Name': self.name + }, + configs] + easy_xml.WriteXmlIfChanged(content, self.user_file_path, + encoding="Windows-1252") diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py new file mode 100644 index 0000000000000..0b32e91180784 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py @@ -0,0 +1,270 @@ +# 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. + +"""Utility functions shared amongst the Windows generators.""" + +import copy +import os + + +# A dictionary mapping supported target types to extensions. +TARGET_TYPE_EXT = { + 'executable': 'exe', + 'loadable_module': 'dll', + 'shared_library': 'dll', + 'static_library': 'lib', +} + + +def _GetLargePdbShimCcPath(): + """Returns the path of the large_pdb_shim.cc file.""" + this_dir = os.path.abspath(os.path.dirname(__file__)) + src_dir = os.path.abspath(os.path.join(this_dir, '..', '..')) + win_data_dir = os.path.join(src_dir, 'data', 'win') + large_pdb_shim_cc = os.path.join(win_data_dir, 'large-pdb-shim.cc') + return large_pdb_shim_cc + + +def _DeepCopySomeKeys(in_dict, keys): + """Performs a partial deep-copy on |in_dict|, only copying the keys in |keys|. + + Arguments: + in_dict: The dictionary to copy. + keys: The keys to be copied. If a key is in this list and doesn't exist in + |in_dict| this is not an error. + Returns: + The partially deep-copied dictionary. + """ + d = {} + for key in keys: + if key not in in_dict: + continue + d[key] = copy.deepcopy(in_dict[key]) + return d + + +def _SuffixName(name, suffix): + """Add a suffix to the end of a target. + + Arguments: + name: name of the target (foo#target) + suffix: the suffix to be added + Returns: + Target name with suffix added (foo_suffix#target) + """ + parts = name.rsplit('#', 1) + parts[0] = '%s_%s' % (parts[0], suffix) + return '#'.join(parts) + + +def _ShardName(name, number): + """Add a shard number to the end of a target. + + Arguments: + name: name of the target (foo#target) + number: shard number + Returns: + Target name with shard added (foo_1#target) + """ + return _SuffixName(name, str(number)) + + +def ShardTargets(target_list, target_dicts): + """Shard some targets apart to work around the linkers limits. + + Arguments: + target_list: List of target pairs: 'base/base.gyp:base'. + target_dicts: Dict of target properties keyed on target pair. + Returns: + Tuple of the new sharded versions of the inputs. + """ + # Gather the targets to shard, and how many pieces. + targets_to_shard = {} + for t in target_dicts: + shards = int(target_dicts[t].get('msvs_shard', 0)) + if shards: + targets_to_shard[t] = shards + # Shard target_list. + new_target_list = [] + for t in target_list: + if t in targets_to_shard: + for i in range(targets_to_shard[t]): + new_target_list.append(_ShardName(t, i)) + else: + new_target_list.append(t) + # Shard target_dict. + new_target_dicts = {} + for t in target_dicts: + if t in targets_to_shard: + for i in range(targets_to_shard[t]): + name = _ShardName(t, i) + new_target_dicts[name] = copy.copy(target_dicts[t]) + new_target_dicts[name]['target_name'] = _ShardName( + new_target_dicts[name]['target_name'], i) + sources = new_target_dicts[name].get('sources', []) + new_sources = [] + for pos in range(i, len(sources), targets_to_shard[t]): + new_sources.append(sources[pos]) + new_target_dicts[name]['sources'] = new_sources + else: + new_target_dicts[t] = target_dicts[t] + # Shard dependencies. + for t in new_target_dicts: + for deptype in ('dependencies', 'dependencies_original'): + dependencies = copy.copy(new_target_dicts[t].get(deptype, [])) + new_dependencies = [] + for d in dependencies: + if d in targets_to_shard: + for i in range(targets_to_shard[d]): + new_dependencies.append(_ShardName(d, i)) + else: + new_dependencies.append(d) + new_target_dicts[t][deptype] = new_dependencies + + return (new_target_list, new_target_dicts) + + +def _GetPdbPath(target_dict, config_name, vars): + """Returns the path to the PDB file that will be generated by a given + configuration. + + The lookup proceeds as follows: + - Look for an explicit path in the VCLinkerTool configuration block. + - Look for an 'msvs_large_pdb_path' variable. + - Use '<(PRODUCT_DIR)/<(product_name).(exe|dll).pdb' if 'product_name' is + specified. + - Use '<(PRODUCT_DIR)/<(target_name).(exe|dll).pdb'. + + Arguments: + target_dict: The target dictionary to be searched. + config_name: The name of the configuration of interest. + vars: A dictionary of common GYP variables with generator-specific values. + Returns: + The path of the corresponding PDB file. + """ + config = target_dict['configurations'][config_name] + msvs = config.setdefault('msvs_settings', {}) + + linker = msvs.get('VCLinkerTool', {}) + + pdb_path = linker.get('ProgramDatabaseFile') + if pdb_path: + return pdb_path + + variables = target_dict.get('variables', {}) + pdb_path = variables.get('msvs_large_pdb_path', None) + if pdb_path: + return pdb_path + + + pdb_base = target_dict.get('product_name', target_dict['target_name']) + pdb_base = '%s.%s.pdb' % (pdb_base, TARGET_TYPE_EXT[target_dict['type']]) + pdb_path = vars['PRODUCT_DIR'] + '/' + pdb_base + + return pdb_path + + +def InsertLargePdbShims(target_list, target_dicts, vars): + """Insert a shim target that forces the linker to use 4KB pagesize PDBs. + + This is a workaround for targets with PDBs greater than 1GB in size, the + limit for the 1KB pagesize PDBs created by the linker by default. + + Arguments: + target_list: List of target pairs: 'base/base.gyp:base'. + target_dicts: Dict of target properties keyed on target pair. + vars: A dictionary of common GYP variables with generator-specific values. + Returns: + Tuple of the shimmed version of the inputs. + """ + # Determine which targets need shimming. + targets_to_shim = [] + for t in target_dicts: + target_dict = target_dicts[t] + + # We only want to shim targets that have msvs_large_pdb enabled. + if not int(target_dict.get('msvs_large_pdb', 0)): + continue + # This is intended for executable, shared_library and loadable_module + # targets where every configuration is set up to produce a PDB output. + # If any of these conditions is not true then the shim logic will fail + # below. + targets_to_shim.append(t) + + large_pdb_shim_cc = _GetLargePdbShimCcPath() + + for t in targets_to_shim: + target_dict = target_dicts[t] + target_name = target_dict.get('target_name') + + base_dict = _DeepCopySomeKeys(target_dict, + ['configurations', 'default_configuration', 'toolset']) + + # This is the dict for copying the source file (part of the GYP tree) + # to the intermediate directory of the project. This is necessary because + # we can't always build a relative path to the shim source file (on Windows + # GYP and the project may be on different drives), and Ninja hates absolute + # paths (it ends up generating the .obj and .obj.d alongside the source + # file, polluting GYPs tree). + copy_suffix = 'large_pdb_copy' + copy_target_name = target_name + '_' + copy_suffix + full_copy_target_name = _SuffixName(t, copy_suffix) + shim_cc_basename = os.path.basename(large_pdb_shim_cc) + shim_cc_dir = vars['SHARED_INTERMEDIATE_DIR'] + '/' + copy_target_name + shim_cc_path = shim_cc_dir + '/' + shim_cc_basename + copy_dict = copy.deepcopy(base_dict) + copy_dict['target_name'] = copy_target_name + copy_dict['type'] = 'none' + copy_dict['sources'] = [ large_pdb_shim_cc ] + copy_dict['copies'] = [{ + 'destination': shim_cc_dir, + 'files': [ large_pdb_shim_cc ] + }] + + # This is the dict for the PDB generating shim target. It depends on the + # copy target. + shim_suffix = 'large_pdb_shim' + shim_target_name = target_name + '_' + shim_suffix + full_shim_target_name = _SuffixName(t, shim_suffix) + shim_dict = copy.deepcopy(base_dict) + shim_dict['target_name'] = shim_target_name + shim_dict['type'] = 'static_library' + shim_dict['sources'] = [ shim_cc_path ] + shim_dict['dependencies'] = [ full_copy_target_name ] + + # Set up the shim to output its PDB to the same location as the final linker + # target. + for config_name, config in shim_dict.get('configurations').iteritems(): + pdb_path = _GetPdbPath(target_dict, config_name, vars) + + # A few keys that we don't want to propagate. + for key in ['msvs_precompiled_header', 'msvs_precompiled_source', 'test']: + config.pop(key, None) + + msvs = config.setdefault('msvs_settings', {}) + + # Update the compiler directives in the shim target. + compiler = msvs.setdefault('VCCLCompilerTool', {}) + compiler['DebugInformationFormat'] = '3' + compiler['ProgramDataBaseFileName'] = pdb_path + + # Set the explicit PDB path in the appropriate configuration of the + # original target. + config = target_dict['configurations'][config_name] + msvs = config.setdefault('msvs_settings', {}) + linker = msvs.setdefault('VCLinkerTool', {}) + linker['GenerateDebugInformation'] = 'true' + linker['ProgramDatabaseFile'] = pdb_path + + # Add the new targets. They must go to the beginning of the list so that + # the dependency generation works as expected in ninja. + target_list.insert(0, full_copy_target_name) + target_list.insert(0, full_shim_target_name) + target_dicts[full_copy_target_name] = copy_dict + target_dicts[full_shim_target_name] = shim_dict + + # Update the original target to depend on the shim target. + target_dict.setdefault('dependencies', []).append(full_shim_target_name) + + return (target_list, target_dicts) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py new file mode 100644 index 0000000000000..d9bfa684fa30c --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py @@ -0,0 +1,443 @@ +# 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. + +"""Handle version information related to Visual Stuio.""" + +import errno +import os +import re +import subprocess +import sys +import gyp +import glob + + +class VisualStudioVersion(object): + """Information regarding a version of Visual Studio.""" + + def __init__(self, short_name, description, + solution_version, project_version, flat_sln, uses_vcxproj, + path, sdk_based, default_toolset=None): + self.short_name = short_name + self.description = description + self.solution_version = solution_version + self.project_version = project_version + self.flat_sln = flat_sln + self.uses_vcxproj = uses_vcxproj + self.path = path + self.sdk_based = sdk_based + self.default_toolset = default_toolset + + def ShortName(self): + return self.short_name + + def Description(self): + """Get the full description of the version.""" + return self.description + + def SolutionVersion(self): + """Get the version number of the sln files.""" + return self.solution_version + + def ProjectVersion(self): + """Get the version number of the vcproj or vcxproj files.""" + return self.project_version + + def FlatSolution(self): + return self.flat_sln + + def UsesVcxproj(self): + """Returns true if this version uses a vcxproj file.""" + return self.uses_vcxproj + + def ProjectExtension(self): + """Returns the file extension for the project.""" + return self.uses_vcxproj and '.vcxproj' or '.vcproj' + + def Path(self): + """Returns the path to Visual Studio installation.""" + return self.path + + def ToolPath(self, tool): + """Returns the path to a given compiler tool. """ + return os.path.normpath(os.path.join(self.path, "VC/bin", tool)) + + def DefaultToolset(self): + """Returns the msbuild toolset version that will be used in the absence + of a user override.""" + return self.default_toolset + + def SetupScript(self, target_arch): + """Returns a command (with arguments) to be used to set up the + environment.""" + # Check if we are running in the SDK command line environment and use + # the setup script from the SDK if so. |target_arch| should be either + # 'x86' or 'x64'. + assert target_arch in ('x86', 'x64') + sdk_dir = os.environ.get('WindowsSDKDir') + if self.sdk_based and sdk_dir: + return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')), + '/' + target_arch] + else: + # We don't use VC/vcvarsall.bat for x86 because vcvarsall calls + # vcvars32, which it can only find if VS??COMNTOOLS is set, which it + # isn't always. + if target_arch == 'x86': + if self.short_name >= '2013' and self.short_name[-1] != 'e' and ( + os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or + os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'): + # VS2013 and later, non-Express have a x64-x86 cross that we want + # to prefer. + return [os.path.normpath( + os.path.join(self.path, 'VC/vcvarsall.bat')), 'amd64_x86'] + # Otherwise, the standard x86 compiler. + return [os.path.normpath( + os.path.join(self.path, 'Common7/Tools/vsvars32.bat'))] + else: + assert target_arch == 'x64' + arg = 'x86_amd64' + # 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'): + arg = 'amd64' + return [os.path.normpath( + os.path.join(self.path, 'VC/vcvarsall.bat')), arg] + + +def _RegistryQueryBase(sysdir, key, value): + """Use reg.exe to read a particular key. + + While ideally we might use the win32 module, we would like gyp to be + python neutral, so for instance cygwin python lacks this module. + + Arguments: + sysdir: The system subdirectory to attempt to launch reg.exe from. + key: The registry key to read from. + value: The particular value to read. + Return: + stdout from reg.exe, or None for failure. + """ + # Skip if not on Windows or Python Win32 setup issue + if sys.platform not in ('win32', 'cygwin'): + return None + # Setup params to pass to and attempt to launch reg.exe + cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'), + 'query', key] + if value: + cmd.extend(['/v', value]) + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + # Obtain the stdout from reg.exe, reading to the end so p.returncode is valid + # Note that the error text may be in [1] in some cases + text = p.communicate()[0] + # Check return code from reg.exe; officially 0==success and 1==error + if p.returncode: + return None + return text + + +def _RegistryQuery(key, value=None): + r"""Use reg.exe to read a particular key through _RegistryQueryBase. + + First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If + that fails, it falls back to System32. Sysnative is available on Vista and + up and available on Windows Server 2003 and XP through KB patch 942589. Note + that Sysnative will always fail if using 64-bit python due to it being a + virtual directory and System32 will work correctly in the first place. + + KB 942589 - http://support.microsoft.com/kb/942589/en-us. + + Arguments: + key: The registry key. + value: The particular registry value to read (optional). + Return: + stdout from reg.exe, or None for failure. + """ + text = None + try: + text = _RegistryQueryBase('Sysnative', key, value) + except OSError, e: + if e.errno == errno.ENOENT: + text = _RegistryQueryBase('System32', key, value) + else: + raise + return text + + +def _RegistryGetValueUsingWinReg(key, value): + """Use the _winreg module to obtain the value of a registry key. + + Args: + key: The registry key. + value: The particular registry value to read. + Return: + contents of the registry key's value, or None on failure. Throws + ImportError if _winreg is unavailable. + """ + import _winreg + try: + root, subkey = key.split('\\', 1) + assert root == 'HKLM' # Only need HKLM for now. + with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey) as hkey: + return _winreg.QueryValueEx(hkey, value)[0] + except WindowsError: + return None + + +def _RegistryGetValue(key, value): + """Use _winreg or reg.exe to obtain the value of a registry key. + + Using _winreg is preferable because it solves an issue on some corporate + environments where access to reg.exe is locked down. However, we still need + to fallback to reg.exe for the case where the _winreg module is not available + (for example in cygwin python). + + Args: + key: The registry key. + value: The particular registry value to read. + Return: + contents of the registry key's value, or None on failure. + """ + try: + return _RegistryGetValueUsingWinReg(key, value) + except ImportError: + pass + + # Fallback to reg.exe if we fail to import _winreg. + text = _RegistryQuery(key, value) + if not text: + return None + # Extract value. + match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text) + if not match: + return None + return match.group(1) + + +def _CreateVersion(name, path, sdk_based=False): + """Sets up MSVS project generation. + + Setup is based off the GYP_MSVS_VERSION environment variable or whatever is + autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is + passed in that doesn't match a value in versions python will throw a error. + """ + if path: + path = os.path.normpath(path) + versions = { + '2015': VisualStudioVersion('2015', + 'Visual Studio 2015', + solution_version='12.00', + project_version='14.0', + flat_sln=False, + uses_vcxproj=True, + path=path, + sdk_based=sdk_based, + default_toolset='v140'), + '2013': VisualStudioVersion('2013', + 'Visual Studio 2013', + solution_version='13.00', + project_version='12.0', + flat_sln=False, + uses_vcxproj=True, + path=path, + sdk_based=sdk_based, + default_toolset='v120'), + '2013e': VisualStudioVersion('2013e', + 'Visual Studio 2013', + solution_version='13.00', + project_version='12.0', + flat_sln=True, + uses_vcxproj=True, + path=path, + sdk_based=sdk_based, + default_toolset='v120'), + '2012': VisualStudioVersion('2012', + 'Visual Studio 2012', + solution_version='12.00', + project_version='4.0', + flat_sln=False, + uses_vcxproj=True, + path=path, + sdk_based=sdk_based, + default_toolset='v110'), + '2012e': VisualStudioVersion('2012e', + 'Visual Studio 2012', + solution_version='12.00', + project_version='4.0', + flat_sln=True, + uses_vcxproj=True, + path=path, + sdk_based=sdk_based, + default_toolset='v110'), + '2010': VisualStudioVersion('2010', + 'Visual Studio 2010', + solution_version='11.00', + project_version='4.0', + flat_sln=False, + uses_vcxproj=True, + path=path, + sdk_based=sdk_based), + '2010e': VisualStudioVersion('2010e', + 'Visual C++ Express 2010', + solution_version='11.00', + project_version='4.0', + flat_sln=True, + uses_vcxproj=True, + path=path, + sdk_based=sdk_based), + '2008': VisualStudioVersion('2008', + 'Visual Studio 2008', + solution_version='10.00', + project_version='9.00', + flat_sln=False, + uses_vcxproj=False, + path=path, + sdk_based=sdk_based), + '2008e': VisualStudioVersion('2008e', + 'Visual Studio 2008', + solution_version='10.00', + project_version='9.00', + flat_sln=True, + uses_vcxproj=False, + path=path, + sdk_based=sdk_based), + '2005': VisualStudioVersion('2005', + 'Visual Studio 2005', + solution_version='9.00', + project_version='8.00', + flat_sln=False, + uses_vcxproj=False, + path=path, + sdk_based=sdk_based), + '2005e': VisualStudioVersion('2005e', + 'Visual Studio 2005', + solution_version='9.00', + project_version='8.00', + flat_sln=True, + uses_vcxproj=False, + path=path, + sdk_based=sdk_based), + } + return versions[str(name)] + + +def _ConvertToCygpath(path): + """Convert to cygwin path if we are using cygwin.""" + if sys.platform == 'cygwin': + p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE) + path = p.communicate()[0].strip() + return path + + +def _DetectVisualStudioVersions(versions_to_check, force_express): + """Collect the list of installed visual studio versions. + + Returns: + A list of visual studio versions installed in descending order of + usage preference. + Base this on the registry and a quick check if devenv.exe exists. + Only versions 8-10 are considered. + Possibilities are: + 2005(e) - Visual Studio 2005 (8) + 2008(e) - Visual Studio 2008 (9) + 2010(e) - Visual Studio 2010 (10) + 2012(e) - Visual Studio 2012 (11) + 2013(e) - Visual Studio 2013 (12) + 2015 - Visual Studio 2015 (14) + Where (e) is e for express editions of MSVS and blank otherwise. + """ + version_to_year = { + '8.0': '2005', + '9.0': '2008', + '10.0': '2010', + '11.0': '2012', + '12.0': '2013', + '14.0': '2015', + } + versions = [] + for version in versions_to_check: + # Old method of searching for which VS version is installed + # We don't use the 2010-encouraged-way because we also want to get the + # path to the binaries, which it doesn't offer. + keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version, + r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version, + r'HKLM\Software\Microsoft\VCExpress\%s' % version, + r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version] + for index in range(len(keys)): + path = _RegistryGetValue(keys[index], 'InstallDir') + if not path: + continue + path = _ConvertToCygpath(path) + # Check for full. + full_path = os.path.join(path, 'devenv.exe') + express_path = os.path.join(path, '*express.exe') + if not force_express and os.path.exists(full_path): + # Add this one. + versions.append(_CreateVersion(version_to_year[version], + os.path.join(path, '..', '..'))) + # Check for express. + elif glob.glob(express_path): + # Add this one. + versions.append(_CreateVersion(version_to_year[version] + 'e', + os.path.join(path, '..', '..'))) + + # The old method above does not work when only SDK is installed. + keys = [r'HKLM\Software\Microsoft\VisualStudio\SxS\VC7', + r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7'] + for index in range(len(keys)): + path = _RegistryGetValue(keys[index], version) + if not path: + continue + path = _ConvertToCygpath(path) + if version != '14.0': # There is no Express edition for 2015. + versions.append(_CreateVersion(version_to_year[version] + 'e', + os.path.join(path, '..'), sdk_based=True)) + + return versions + + +def SelectVisualStudioVersion(version='auto', allow_fallback=True): + """Select which version of Visual Studio projects to generate. + + Arguments: + version: Hook to allow caller to force a particular version (vs auto). + Returns: + An object representing a visual studio project format version. + """ + # In auto mode, check environment variable for override. + if version == 'auto': + version = os.environ.get('GYP_MSVS_VERSION', 'auto') + version_map = { + 'auto': ('14.0', '12.0', '10.0', '9.0', '8.0', '11.0'), + '2005': ('8.0',), + '2005e': ('8.0',), + '2008': ('9.0',), + '2008e': ('9.0',), + '2010': ('10.0',), + '2010e': ('10.0',), + '2012': ('11.0',), + '2012e': ('11.0',), + '2013': ('12.0',), + '2013e': ('12.0',), + '2015': ('14.0',), + } + override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH') + if override_path: + msvs_version = os.environ.get('GYP_MSVS_VERSION') + if not msvs_version: + raise ValueError('GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be ' + 'set to a particular version (e.g. 2010e).') + return _CreateVersion(msvs_version, override_path, sdk_based=True) + version = str(version) + versions = _DetectVisualStudioVersions(version_map[version], 'e' in version) + if not versions: + if not allow_fallback: + raise ValueError('Could not locate Visual Studio installation.') + if version == 'auto': + # Default to 2005 if we couldn't find anything + return _CreateVersion('2005', None) + else: + return _CreateVersion(version, None) + return versions[0] diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/__init__.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/__init__.py new file mode 100755 index 0000000000000..668f38b60d009 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/__init__.py @@ -0,0 +1,548 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 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. + +import copy +import gyp.input +import optparse +import os.path +import re +import shlex +import sys +import traceback +from gyp.common import GypError + +# Default debug modes for GYP +debug = {} + +# List of "official" debug modes, but you can use anything you like. +DEBUG_GENERAL = 'general' +DEBUG_VARIABLES = 'variables' +DEBUG_INCLUDES = 'includes' + + +def DebugOutput(mode, message, *args): + if 'all' in gyp.debug or mode in gyp.debug: + ctx = ('unknown', 0, 'unknown') + try: + f = traceback.extract_stack(limit=2) + if f: + ctx = f[0][:3] + except: + pass + if args: + message %= args + print '%s:%s:%d:%s %s' % (mode.upper(), os.path.basename(ctx[0]), + ctx[1], ctx[2], message) + +def FindBuildFiles(): + extension = '.gyp' + files = os.listdir(os.getcwd()) + build_files = [] + for file in files: + if file.endswith(extension): + build_files.append(file) + return build_files + + +def Load(build_files, format, default_variables={}, + includes=[], depth='.', params=None, check=False, + circular_check=True, duplicate_basename_check=True): + """ + Loads one or more specified build files. + default_variables and includes will be copied before use. + Returns the generator for the specified format and the + data returned by loading the specified build files. + """ + if params is None: + params = {} + + if '-' in format: + format, params['flavor'] = format.split('-', 1) + + default_variables = copy.copy(default_variables) + + # Default variables provided by this program and its modules should be + # named WITH_CAPITAL_LETTERS to provide a distinct "best practice" namespace, + # avoiding collisions with user and automatic variables. + default_variables['GENERATOR'] = format + default_variables['GENERATOR_FLAVOR'] = params.get('flavor', '') + + # Format can be a custom python file, or by default the name of a module + # within gyp.generator. + if format.endswith('.py'): + generator_name = os.path.splitext(format)[0] + path, generator_name = os.path.split(generator_name) + + # Make sure the path to the custom generator is in sys.path + # Don't worry about removing it once we are done. Keeping the path + # to each generator that is used in sys.path is likely harmless and + # arguably a good idea. + path = os.path.abspath(path) + if path not in sys.path: + sys.path.insert(0, path) + else: + generator_name = 'gyp.generator.' + format + + # These parameters are passed in order (as opposed to by key) + # because ActivePython cannot handle key parameters to __import__. + generator = __import__(generator_name, globals(), locals(), generator_name) + for (key, val) in generator.generator_default_variables.items(): + default_variables.setdefault(key, val) + + # Give the generator the opportunity to set additional variables based on + # the params it will receive in the output phase. + if getattr(generator, 'CalculateVariables', None): + generator.CalculateVariables(default_variables, params) + + # Give the generator the opportunity to set generator_input_info based on + # the params it will receive in the output phase. + if getattr(generator, 'CalculateGeneratorInputInfo', None): + generator.CalculateGeneratorInputInfo(params) + + # Fetch the generator specific info that gets fed to input, we use getattr + # so we can default things and the generators only have to provide what + # they need. + generator_input_info = { + 'non_configuration_keys': + getattr(generator, 'generator_additional_non_configuration_keys', []), + 'path_sections': + getattr(generator, 'generator_additional_path_sections', []), + 'extra_sources_for_rules': + getattr(generator, 'generator_extra_sources_for_rules', []), + 'generator_supports_multiple_toolsets': + getattr(generator, 'generator_supports_multiple_toolsets', False), + 'generator_wants_static_library_dependencies_adjusted': + getattr(generator, + 'generator_wants_static_library_dependencies_adjusted', True), + 'generator_wants_sorted_dependencies': + getattr(generator, 'generator_wants_sorted_dependencies', False), + 'generator_filelist_paths': + getattr(generator, 'generator_filelist_paths', None), + } + + # Process the input specific to this generator. + result = gyp.input.Load(build_files, default_variables, includes[:], + depth, generator_input_info, check, circular_check, + duplicate_basename_check, + params['parallel'], params['root_targets']) + return [generator] + result + +def NameValueListToDict(name_value_list): + """ + Takes an array of strings of the form 'NAME=VALUE' and creates a dictionary + of the pairs. If a string is simply NAME, then the value in the dictionary + is set to True. If VALUE can be converted to an integer, it is. + """ + result = { } + for item in name_value_list: + tokens = item.split('=', 1) + if len(tokens) == 2: + # If we can make it an int, use that, otherwise, use the string. + try: + token_value = int(tokens[1]) + except ValueError: + token_value = tokens[1] + # Set the variable to the supplied value. + result[tokens[0]] = token_value + else: + # No value supplied, treat it as a boolean and set it. + result[tokens[0]] = True + return result + +def ShlexEnv(env_name): + flags = os.environ.get(env_name, []) + if flags: + flags = shlex.split(flags) + return flags + +def FormatOpt(opt, value): + if opt.startswith('--'): + return '%s=%s' % (opt, value) + return opt + value + +def RegenerateAppendFlag(flag, values, predicate, env_name, options): + """Regenerate a list of command line flags, for an option of action='append'. + + The |env_name|, if given, is checked in the environment and used to generate + an initial list of options, then the options that were specified on the + command line (given in |values|) are appended. This matches the handling of + environment variables and command line flags where command line flags override + the environment, while not requiring the environment to be set when the flags + are used again. + """ + flags = [] + if options.use_environment and env_name: + for flag_value in ShlexEnv(env_name): + value = FormatOpt(flag, predicate(flag_value)) + if value in flags: + flags.remove(value) + flags.append(value) + if values: + for flag_value in values: + flags.append(FormatOpt(flag, predicate(flag_value))) + return flags + +def RegenerateFlags(options): + """Given a parsed options object, and taking the environment variables into + account, returns a list of flags that should regenerate an equivalent options + object (even in the absence of the environment variables.) + + Any path options will be normalized relative to depth. + + The format flag is not included, as it is assumed the calling generator will + set that as appropriate. + """ + def FixPath(path): + path = gyp.common.FixIfRelativePath(path, options.depth) + if not path: + return os.path.curdir + return path + + def Noop(value): + return value + + # We always want to ignore the environment when regenerating, to avoid + # duplicate or changed flags in the environment at the time of regeneration. + flags = ['--ignore-environment'] + for name, metadata in options._regeneration_metadata.iteritems(): + opt = metadata['opt'] + value = getattr(options, name) + value_predicate = metadata['type'] == 'path' and FixPath or Noop + action = metadata['action'] + env_name = metadata['env_name'] + if action == 'append': + flags.extend(RegenerateAppendFlag(opt, value, value_predicate, + env_name, options)) + elif action in ('store', None): # None is a synonym for 'store'. + if value: + flags.append(FormatOpt(opt, value_predicate(value))) + elif options.use_environment and env_name and os.environ.get(env_name): + flags.append(FormatOpt(opt, value_predicate(os.environ.get(env_name)))) + elif action in ('store_true', 'store_false'): + if ((action == 'store_true' and value) or + (action == 'store_false' and not value)): + flags.append(opt) + elif options.use_environment and env_name: + print >>sys.stderr, ('Warning: environment regeneration unimplemented ' + 'for %s flag %r env_name %r' % (action, opt, + env_name)) + else: + print >>sys.stderr, ('Warning: regeneration unimplemented for action %r ' + 'flag %r' % (action, opt)) + + return flags + +class RegeneratableOptionParser(optparse.OptionParser): + def __init__(self): + self.__regeneratable_options = {} + optparse.OptionParser.__init__(self) + + def add_option(self, *args, **kw): + """Add an option to the parser. + + This accepts the same arguments as OptionParser.add_option, plus the + following: + regenerate: can be set to False to prevent this option from being included + in regeneration. + env_name: name of environment variable that additional values for this + option come from. + type: adds type='path', to tell the regenerator that the values of + this option need to be made relative to options.depth + """ + env_name = kw.pop('env_name', None) + if 'dest' in kw and kw.pop('regenerate', True): + dest = kw['dest'] + + # The path type is needed for regenerating, for optparse we can just treat + # it as a string. + type = kw.get('type') + if type == 'path': + kw['type'] = 'string' + + self.__regeneratable_options[dest] = { + 'action': kw.get('action'), + 'type': type, + 'env_name': env_name, + 'opt': args[0], + } + + optparse.OptionParser.add_option(self, *args, **kw) + + def parse_args(self, *args): + values, args = optparse.OptionParser.parse_args(self, *args) + values._regeneration_metadata = self.__regeneratable_options + return values, args + +def gyp_main(args): + my_name = os.path.basename(sys.argv[0]) + + parser = RegeneratableOptionParser() + usage = 'usage: %s [options ...] [build_file ...]' + parser.set_usage(usage.replace('%s', '%prog')) + parser.add_option('--build', dest='configs', action='append', + help='configuration for build after project generation') + parser.add_option('--check', dest='check', action='store_true', + help='check format of gyp files') + parser.add_option('--config-dir', dest='config_dir', action='store', + env_name='GYP_CONFIG_DIR', default=None, + help='The location for configuration files like ' + 'include.gypi.') + parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE', + action='append', default=[], help='turn on a debugging ' + 'mode for debugging GYP. Supported modes are "variables", ' + '"includes" and "general" or "all" for all of them.') + parser.add_option('-D', dest='defines', action='append', metavar='VAR=VAL', + env_name='GYP_DEFINES', + help='sets variable VAR to value VAL') + parser.add_option('--depth', dest='depth', metavar='PATH', type='path', + help='set DEPTH gyp variable to a relative path to PATH') + parser.add_option('-f', '--format', dest='formats', action='append', + env_name='GYP_GENERATORS', regenerate=False, + help='output formats to generate') + parser.add_option('-G', dest='generator_flags', action='append', default=[], + metavar='FLAG=VAL', env_name='GYP_GENERATOR_FLAGS', + help='sets generator flag FLAG to VAL') + parser.add_option('--generator-output', dest='generator_output', + action='store', default=None, metavar='DIR', type='path', + env_name='GYP_GENERATOR_OUTPUT', + help='puts generated build files under DIR') + parser.add_option('--ignore-environment', dest='use_environment', + action='store_false', default=True, regenerate=False, + help='do not read options from environment variables') + parser.add_option('-I', '--include', dest='includes', action='append', + metavar='INCLUDE', type='path', + help='files to include in all loaded .gyp files') + # --no-circular-check disables the check for circular relationships between + # .gyp files. These relationships should not exist, but they've only been + # observed to be harmful with the Xcode generator. Chromium's .gyp files + # currently have some circular relationships on non-Mac platforms, so this + # option allows the strict behavior to be used on Macs and the lenient + # behavior to be used elsewhere. + # TODO(mark): Remove this option when http://crbug.com/35878 is fixed. + parser.add_option('--no-circular-check', dest='circular_check', + action='store_false', default=True, regenerate=False, + help="don't check for circular relationships between files") + # --no-duplicate-basename-check disables the check for duplicate basenames + # in a static_library/shared_library project. Visual C++ 2008 generator + # doesn't support this configuration. Libtool on Mac also generates warnings + # when duplicate basenames are passed into Make generator on Mac. + # TODO(yukawa): Remove this option when these legacy generators are + # deprecated. + parser.add_option('--no-duplicate-basename-check', + dest='duplicate_basename_check', action='store_false', + default=True, regenerate=False, + help="don't check for duplicate basenames") + parser.add_option('--no-parallel', action='store_true', default=False, + help='Disable multiprocessing') + parser.add_option('-S', '--suffix', dest='suffix', default='', + help='suffix to add to generated files') + parser.add_option('--toplevel-dir', dest='toplevel_dir', action='store', + default=None, metavar='DIR', type='path', + help='directory to use as the root of the source tree') + parser.add_option('-R', '--root-target', dest='root_targets', + action='append', metavar='TARGET', + help='include only TARGET and its deep dependencies') + + options, build_files_arg = parser.parse_args(args) + build_files = build_files_arg + + # Set up the configuration directory (defaults to ~/.gyp) + if not options.config_dir: + home = None + home_dot_gyp = None + if options.use_environment: + home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None) + if home_dot_gyp: + home_dot_gyp = os.path.expanduser(home_dot_gyp) + + if not home_dot_gyp: + home_vars = ['HOME'] + if sys.platform in ('cygwin', 'win32'): + home_vars.append('USERPROFILE') + for home_var in home_vars: + home = os.getenv(home_var) + if home != None: + home_dot_gyp = os.path.join(home, '.gyp') + if not os.path.exists(home_dot_gyp): + home_dot_gyp = None + else: + break + else: + home_dot_gyp = os.path.expanduser(options.config_dir) + + if home_dot_gyp and not os.path.exists(home_dot_gyp): + home_dot_gyp = None + + if not options.formats: + # If no format was given on the command line, then check the env variable. + generate_formats = [] + if options.use_environment: + generate_formats = os.environ.get('GYP_GENERATORS', []) + if generate_formats: + generate_formats = re.split(r'[\s,]', generate_formats) + if generate_formats: + options.formats = generate_formats + else: + # Nothing in the variable, default based on platform. + if sys.platform == 'darwin': + options.formats = ['xcode'] + elif sys.platform in ('win32', 'cygwin'): + options.formats = ['msvs'] + else: + options.formats = ['make'] + + if not options.generator_output and options.use_environment: + g_o = os.environ.get('GYP_GENERATOR_OUTPUT') + if g_o: + options.generator_output = g_o + + options.parallel = not options.no_parallel + + for mode in options.debug: + gyp.debug[mode] = 1 + + # Do an extra check to avoid work when we're not debugging. + if DEBUG_GENERAL in gyp.debug: + DebugOutput(DEBUG_GENERAL, 'running with these options:') + for option, value in sorted(options.__dict__.items()): + if option[0] == '_': + continue + if isinstance(value, basestring): + DebugOutput(DEBUG_GENERAL, " %s: '%s'", option, value) + else: + DebugOutput(DEBUG_GENERAL, " %s: %s", option, value) + + if not build_files: + build_files = FindBuildFiles() + if not build_files: + raise GypError((usage + '\n\n%s: error: no build_file') % + (my_name, my_name)) + + # TODO(mark): Chromium-specific hack! + # For Chromium, the gyp "depth" variable should always be a relative path + # to Chromium's top-level "src" directory. If no depth variable was set + # on the command line, try to find a "src" directory by looking at the + # absolute path to each build file's directory. The first "src" component + # found will be treated as though it were the path used for --depth. + if not options.depth: + for build_file in build_files: + build_file_dir = os.path.abspath(os.path.dirname(build_file)) + build_file_dir_components = build_file_dir.split(os.path.sep) + components_len = len(build_file_dir_components) + for index in xrange(components_len - 1, -1, -1): + if build_file_dir_components[index] == 'src': + options.depth = os.path.sep.join(build_file_dir_components) + break + del build_file_dir_components[index] + + # If the inner loop found something, break without advancing to another + # build file. + if options.depth: + break + + if not options.depth: + raise GypError('Could not automatically locate src directory. This is' + 'a temporary Chromium feature that will be removed. Use' + '--depth as a workaround.') + + # If toplevel-dir is not set, we assume that depth is the root of our source + # tree. + if not options.toplevel_dir: + options.toplevel_dir = options.depth + + # -D on the command line sets variable defaults - D isn't just for define, + # it's for default. Perhaps there should be a way to force (-F?) a + # variable's value so that it can't be overridden by anything else. + cmdline_default_variables = {} + defines = [] + if options.use_environment: + defines += ShlexEnv('GYP_DEFINES') + if options.defines: + defines += options.defines + cmdline_default_variables = NameValueListToDict(defines) + if DEBUG_GENERAL in gyp.debug: + DebugOutput(DEBUG_GENERAL, + "cmdline_default_variables: %s", cmdline_default_variables) + + # Set up includes. + includes = [] + + # If ~/.gyp/include.gypi exists, it'll be forcibly included into every + # .gyp file that's loaded, before anything else is included. + if home_dot_gyp != None: + default_include = os.path.join(home_dot_gyp, 'include.gypi') + if os.path.exists(default_include): + print 'Using overrides found in ' + default_include + includes.append(default_include) + + # Command-line --include files come after the default include. + if options.includes: + includes.extend(options.includes) + + # Generator flags should be prefixed with the target generator since they + # are global across all generator runs. + gen_flags = [] + if options.use_environment: + gen_flags += ShlexEnv('GYP_GENERATOR_FLAGS') + if options.generator_flags: + gen_flags += options.generator_flags + generator_flags = NameValueListToDict(gen_flags) + if DEBUG_GENERAL in gyp.debug.keys(): + DebugOutput(DEBUG_GENERAL, "generator_flags: %s", generator_flags) + + # Generate all requested formats (use a set in case we got one format request + # twice) + for format in set(options.formats): + params = {'options': options, + 'build_files': build_files, + 'generator_flags': generator_flags, + 'cwd': os.getcwd(), + 'build_files_arg': build_files_arg, + 'gyp_binary': sys.argv[0], + 'home_dot_gyp': home_dot_gyp, + 'parallel': options.parallel, + 'root_targets': options.root_targets, + 'target_arch': cmdline_default_variables.get('target_arch', '')} + + # Start with the default variables from the command line. + [generator, flat_list, targets, data] = Load( + build_files, format, cmdline_default_variables, includes, options.depth, + params, options.check, options.circular_check, + options.duplicate_basename_check) + + # TODO(mark): Pass |data| for now because the generator needs a list of + # build files that came in. In the future, maybe it should just accept + # a list, and not the whole data dict. + # NOTE: flat_list is the flattened dependency graph specifying the order + # that targets may be built. Build systems that operate serially or that + # need to have dependencies defined before dependents reference them should + # generate targets in the order specified in flat_list. + generator.GenerateOutput(flat_list, targets, data, params) + + if options.configs: + valid_configs = targets[flat_list[0]]['configurations'].keys() + for conf in options.configs: + if conf not in valid_configs: + raise GypError('Invalid config specified via --build: %s' % conf) + generator.PerformBuild(data, options.configs, params) + + # Done + return 0 + + +def main(args): + try: + return gyp_main(args) + except GypError, e: + sys.stderr.write("gyp: %s\n" % e) + return 1 + +# NOTE: setuptools generated console_scripts calls function with no arguments +def script_main(): + return main(sys.argv[1:]) + +if __name__ == '__main__': + sys.exit(script_main()) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common.py new file mode 100644 index 0000000000000..501118796f00d --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common.py @@ -0,0 +1,612 @@ +# Copyright (c) 2012 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. + +from __future__ import with_statement + +import collections +import errno +import filecmp +import os.path +import re +import tempfile +import sys + + +# A minimal memoizing decorator. It'll blow up if the args aren't immutable, +# among other "problems". +class memoize(object): + def __init__(self, func): + self.func = func + self.cache = {} + def __call__(self, *args): + try: + return self.cache[args] + except KeyError: + result = self.func(*args) + self.cache[args] = result + return result + + +class GypError(Exception): + """Error class representing an error, which is to be presented + to the user. The main entry point will catch and display this. + """ + pass + + +def ExceptionAppend(e, msg): + """Append a message to the given exception's message.""" + if not e.args: + e.args = (msg,) + elif len(e.args) == 1: + e.args = (str(e.args[0]) + ' ' + msg,) + else: + e.args = (str(e.args[0]) + ' ' + msg,) + e.args[1:] + + +def FindQualifiedTargets(target, qualified_list): + """ + Given a list of qualified targets, return the qualified targets for the + specified |target|. + """ + return [t for t in qualified_list if ParseQualifiedTarget(t)[1] == target] + + +def ParseQualifiedTarget(target): + # Splits a qualified target into a build file, target name and toolset. + + # NOTE: rsplit is used to disambiguate the Windows drive letter separator. + target_split = target.rsplit(':', 1) + if len(target_split) == 2: + [build_file, target] = target_split + else: + build_file = None + + target_split = target.rsplit('#', 1) + if len(target_split) == 2: + [target, toolset] = target_split + else: + toolset = None + + return [build_file, target, toolset] + + +def ResolveTarget(build_file, target, toolset): + # This function resolves a target into a canonical form: + # - a fully defined build file, either absolute or relative to the current + # directory + # - a target name + # - a toolset + # + # build_file is the file relative to which 'target' is defined. + # target is the qualified target. + # toolset is the default toolset for that target. + [parsed_build_file, target, parsed_toolset] = ParseQualifiedTarget(target) + + if parsed_build_file: + if build_file: + # If a relative path, parsed_build_file is relative to the directory + # containing build_file. If build_file is not in the current directory, + # parsed_build_file is not a usable path as-is. Resolve it by + # interpreting it as relative to build_file. If parsed_build_file is + # absolute, it is usable as a path regardless of the current directory, + # and os.path.join will return it as-is. + build_file = os.path.normpath(os.path.join(os.path.dirname(build_file), + parsed_build_file)) + # Further (to handle cases like ../cwd), make it relative to cwd) + if not os.path.isabs(build_file): + build_file = RelativePath(build_file, '.') + else: + build_file = parsed_build_file + + if parsed_toolset: + toolset = parsed_toolset + + return [build_file, target, toolset] + + +def BuildFile(fully_qualified_target): + # Extracts the build file from the fully qualified target. + return ParseQualifiedTarget(fully_qualified_target)[0] + + +def GetEnvironFallback(var_list, default): + """Look up a key in the environment, with fallback to secondary keys + and finally falling back to a default value.""" + for var in var_list: + if var in os.environ: + return os.environ[var] + return default + + +def QualifiedTarget(build_file, target, toolset): + # "Qualified" means the file that a target was defined in and the target + # name, separated by a colon, suffixed by a # and the toolset name: + # /path/to/file.gyp:target_name#toolset + fully_qualified = build_file + ':' + target + if toolset: + fully_qualified = fully_qualified + '#' + toolset + return fully_qualified + + +@memoize +def RelativePath(path, relative_to, follow_path_symlink=True): + # Assuming both |path| and |relative_to| are relative to the current + # directory, returns a relative path that identifies path relative to + # relative_to. + # If |follow_symlink_path| is true (default) and |path| is a symlink, then + # this method returns a path to the real file represented by |path|. If it is + # false, this method returns a path to the symlink. If |path| is not a + # symlink, this option has no effect. + + # Convert to normalized (and therefore absolute paths). + if follow_path_symlink: + path = os.path.realpath(path) + else: + path = os.path.abspath(path) + relative_to = os.path.realpath(relative_to) + + # On Windows, we can't create a relative path to a different drive, so just + # use the absolute path. + if sys.platform == 'win32': + if (os.path.splitdrive(path)[0].lower() != + os.path.splitdrive(relative_to)[0].lower()): + return path + + # Split the paths into components. + path_split = path.split(os.path.sep) + relative_to_split = relative_to.split(os.path.sep) + + # Determine how much of the prefix the two paths share. + prefix_len = len(os.path.commonprefix([path_split, relative_to_split])) + + # Put enough ".." components to back up out of relative_to to the common + # prefix, and then append the part of path_split after the common prefix. + relative_split = [os.path.pardir] * (len(relative_to_split) - prefix_len) + \ + path_split[prefix_len:] + + if len(relative_split) == 0: + # The paths were the same. + return '' + + # Turn it back into a string and we're done. + return os.path.join(*relative_split) + + +@memoize +def InvertRelativePath(path, toplevel_dir=None): + """Given a path like foo/bar that is relative to toplevel_dir, return + the inverse relative path back to the toplevel_dir. + + E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path))) + should always produce the empty string, unless the path contains symlinks. + """ + if not path: + return path + toplevel_dir = '.' if toplevel_dir is None else toplevel_dir + return RelativePath(toplevel_dir, os.path.join(toplevel_dir, path)) + + +def FixIfRelativePath(path, relative_to): + # Like RelativePath but returns |path| unchanged if it is absolute. + if os.path.isabs(path): + return path + return RelativePath(path, relative_to) + + +def UnrelativePath(path, relative_to): + # Assuming that |relative_to| is relative to the current directory, and |path| + # is a path relative to the dirname of |relative_to|, returns a path that + # identifies |path| relative to the current directory. + rel_dir = os.path.dirname(relative_to) + return os.path.normpath(os.path.join(rel_dir, path)) + + +# re objects used by EncodePOSIXShellArgument. See IEEE 1003.1 XCU.2.2 at +# http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_02 +# and the documentation for various shells. + +# _quote is a pattern that should match any argument that needs to be quoted +# with double-quotes by EncodePOSIXShellArgument. It matches the following +# characters appearing anywhere in an argument: +# \t, \n, space parameter separators +# # comments +# $ expansions (quoted to always expand within one argument) +# % called out by IEEE 1003.1 XCU.2.2 +# & job control +# ' quoting +# (, ) subshell execution +# *, ?, [ pathname expansion +# ; command delimiter +# <, >, | redirection +# = assignment +# {, } brace expansion (bash) +# ~ tilde expansion +# It also matches the empty string, because "" (or '') is the only way to +# represent an empty string literal argument to a POSIX shell. +# +# This does not match the characters in _escape, because those need to be +# backslash-escaped regardless of whether they appear in a double-quoted +# string. +_quote = re.compile('[\t\n #$%&\'()*;<=>?[{|}~]|^$') + +# _escape is a pattern that should match any character that needs to be +# escaped with a backslash, whether or not the argument matched the _quote +# pattern. _escape is used with re.sub to backslash anything in _escape's +# first match group, hence the (parentheses) in the regular expression. +# +# _escape matches the following characters appearing anywhere in an argument: +# " to prevent POSIX shells from interpreting this character for quoting +# \ to prevent POSIX shells from interpreting this character for escaping +# ` to prevent POSIX shells from interpreting this character for command +# substitution +# Missing from this list is $, because the desired behavior of +# EncodePOSIXShellArgument is to permit parameter (variable) expansion. +# +# Also missing from this list is !, which bash will interpret as the history +# expansion character when history is enabled. bash does not enable history +# by default in non-interactive shells, so this is not thought to be a problem. +# ! was omitted from this list because bash interprets "\!" as a literal string +# including the backslash character (avoiding history expansion but retaining +# the backslash), which would not be correct for argument encoding. Handling +# this case properly would also be problematic because bash allows the history +# character to be changed with the histchars shell variable. Fortunately, +# as history is not enabled in non-interactive shells and +# EncodePOSIXShellArgument is only expected to encode for non-interactive +# shells, there is no room for error here by ignoring !. +_escape = re.compile(r'(["\\`])') + +def EncodePOSIXShellArgument(argument): + """Encodes |argument| suitably for consumption by POSIX shells. + + argument may be quoted and escaped as necessary to ensure that POSIX shells + treat the returned value as a literal representing the argument passed to + this function. Parameter (variable) expansions beginning with $ are allowed + to remain intact without escaping the $, to allow the argument to contain + references to variables to be expanded by the shell. + """ + + if not isinstance(argument, str): + argument = str(argument) + + if _quote.search(argument): + quote = '"' + else: + quote = '' + + encoded = quote + re.sub(_escape, r'\\\1', argument) + quote + + return encoded + + +def EncodePOSIXShellList(list): + """Encodes |list| suitably for consumption by POSIX shells. + + Returns EncodePOSIXShellArgument for each item in list, and joins them + together using the space character as an argument separator. + """ + + encoded_arguments = [] + for argument in list: + encoded_arguments.append(EncodePOSIXShellArgument(argument)) + return ' '.join(encoded_arguments) + + +def DeepDependencyTargets(target_dicts, roots): + """Returns the recursive list of target dependencies.""" + dependencies = set() + pending = set(roots) + while pending: + # Pluck out one. + r = pending.pop() + # Skip if visited already. + if r in dependencies: + continue + # Add it. + dependencies.add(r) + # Add its children. + spec = target_dicts[r] + pending.update(set(spec.get('dependencies', []))) + pending.update(set(spec.get('dependencies_original', []))) + return list(dependencies - set(roots)) + + +def BuildFileTargets(target_list, build_file): + """From a target_list, returns the subset from the specified build_file. + """ + return [p for p in target_list if BuildFile(p) == build_file] + + +def AllTargets(target_list, target_dicts, build_file): + """Returns all targets (direct and dependencies) for the specified build_file. + """ + bftargets = BuildFileTargets(target_list, build_file) + deptargets = DeepDependencyTargets(target_dicts, bftargets) + return bftargets + deptargets + + +def WriteOnDiff(filename): + """Write to a file only if the new contents differ. + + Arguments: + filename: name of the file to potentially write to. + Returns: + A file like object which will write to temporary file and only overwrite + the target if it differs (on close). + """ + + class Writer(object): + """Wrapper around file which only covers the target if it differs.""" + def __init__(self): + # Pick temporary file. + tmp_fd, self.tmp_path = tempfile.mkstemp( + suffix='.tmp', + prefix=os.path.split(filename)[1] + '.gyp.', + dir=os.path.split(filename)[0]) + try: + self.tmp_file = os.fdopen(tmp_fd, 'wb') + except Exception: + # Don't leave turds behind. + os.unlink(self.tmp_path) + raise + + def __getattr__(self, attrname): + # Delegate everything else to self.tmp_file + return getattr(self.tmp_file, attrname) + + def close(self): + try: + # Close tmp file. + self.tmp_file.close() + # Determine if different. + same = False + try: + same = filecmp.cmp(self.tmp_path, filename, False) + except OSError, e: + if e.errno != errno.ENOENT: + raise + + if same: + # The new file is identical to the old one, just get rid of the new + # one. + os.unlink(self.tmp_path) + else: + # The new file is different from the old one, or there is no old one. + # Rename the new file to the permanent name. + # + # tempfile.mkstemp uses an overly restrictive mode, resulting in a + # file that can only be read by the owner, regardless of the umask. + # There's no reason to not respect the umask here, which means that + # an extra hoop is required to fetch it and reset the new file's mode. + # + # No way to get the umask without setting a new one? Set a safe one + # and then set it back to the old value. + umask = os.umask(077) + os.umask(umask) + os.chmod(self.tmp_path, 0666 & ~umask) + if sys.platform == 'win32' and os.path.exists(filename): + # NOTE: on windows (but not cygwin) rename will not replace an + # existing file, so it must be preceded with a remove. Sadly there + # is no way to make the switch atomic. + os.remove(filename) + os.rename(self.tmp_path, filename) + except Exception: + # Don't leave turds behind. + os.unlink(self.tmp_path) + raise + + 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 = { + 'cygwin': 'win', + 'win32': 'win', + 'darwin': 'mac', + } + + if 'flavor' in params: + return params['flavor'] + if sys.platform in flavors: + return flavors[sys.platform] + if sys.platform.startswith('sunos'): + return 'solaris' + if sys.platform.startswith('freebsd'): + return 'freebsd' + if sys.platform.startswith('openbsd'): + return 'openbsd' + if sys.platform.startswith('netbsd'): + return 'netbsd' + if sys.platform.startswith('aix'): + return 'aix' + if sys.platform.startswith('zos'): + return 'zos' + if sys.platform.startswith('os390'): + return 'zos' + + return 'linux' + + +def CopyTool(flavor, out_path): + """Finds (flock|mac|win)_tool.gyp in the gyp directory and copies it + to |out_path|.""" + # aix and solaris just need flock emulation. mac and win use more complicated + # support scripts. + prefix = { + 'aix': 'flock', + 'solaris': 'flock', + 'mac': 'mac', + 'win': 'win' + }.get(flavor, None) + if not prefix: + return + + # Slurp input file. + source_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), '%s_tool.py' % prefix) + with open(source_path) as source_file: + source = source_file.readlines() + + # Add header and write it out. + tool_path = os.path.join(out_path, 'gyp-%s-tool' % prefix) + with open(tool_path, 'w') as tool_file: + tool_file.write( + ''.join([source[0], '# Generated by gyp. Do not edit.\n'] + source[1:])) + + # Make file executable. + os.chmod(tool_path, 0755) + + +# From Alex Martelli, +# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560 +# ASPN: Python Cookbook: Remove duplicates from a sequence +# First comment, dated 2001/10/13. +# (Also in the printed Python Cookbook.) + +def uniquer(seq, idfun=None): + if idfun is None: + idfun = lambda x: x + seen = {} + result = [] + for item in seq: + marker = idfun(item) + if marker in seen: continue + seen[marker] = 1 + result.append(item) + return result + + +# 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 __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 discard(self, key): + if key in self.map: + key, prev_item, next_item = self.map.pop(key) + prev_item[2] = next_item + next_item[1] = prev_item + + def __iter__(self): + end = self.end + curr = end[2] + while curr is not end: + yield curr[0] + curr = curr[2] + + def __reversed__(self): + end = self.end + curr = end[1] + while curr is not end: + yield curr[0] + curr = curr[1] + + # The second argument is an addition that causes a pylint warning. + def pop(self, last=True): # pylint: disable=W0221 + if not self: + raise KeyError('set is empty') + key = self.end[1][0] if last else self.end[2][0] + self.discard(key) + return key + + def __repr__(self): + if not self: + return '%s()' % (self.__class__.__name__,) + return '%s(%r)' % (self.__class__.__name__, list(self)) + + def __eq__(self, other): + if isinstance(other, OrderedSet): + return len(self) == len(other) and list(self) == list(other) + return set(self) == set(other) + + # Extensions to the recipe. + def update(self, iterable): + for i in iterable: + if i not in self: + self.add(i) + + +class CycleError(Exception): + """An exception raised when an unexpected cycle is detected.""" + def __init__(self, nodes): + self.nodes = nodes + def __str__(self): + return 'CycleError: cycle involving: ' + str(self.nodes) + + +def TopologicallySorted(graph, get_edges): + r"""Topologically sort based on a user provided edge definition. + + Args: + graph: A list of node names. + get_edges: A function mapping from node name to a hashable collection + of node names which this node has outgoing edges to. + Returns: + A list containing all of the node in graph in topological order. + It is assumed that calling get_edges once for each node and caching is + cheaper than repeatedly calling get_edges. + Raises: + CycleError in the event of a cycle. + Example: + graph = {'a': '$(b) $(c)', 'b': 'hi', 'c': '$(b)'} + def GetEdges(node): + return re.findall(r'\$\(([^))]\)', graph[node]) + print TopologicallySorted(graph.keys(), GetEdges) + ==> + ['a', 'c', b'] + """ + get_edges = memoize(get_edges) + visited = set() + visiting = set() + ordered_nodes = [] + def Visit(node): + if node in visiting: + raise CycleError(visiting) + if node in visited: + return + visited.add(node) + visiting.add(node) + for neighbor in get_edges(node): + Visit(neighbor) + visiting.remove(node) + ordered_nodes.insert(0, node) + for node in sorted(graph): + Visit(node) + return ordered_nodes + +def CrossCompileRequested(): + # TODO: figure out how to not build extra host objects in the + # non-cross-compile case when this is enabled, and enable unconditionally. + return (os.environ.get('GYP_CROSSCOMPILE') or + os.environ.get('AR_host') or + os.environ.get('CC_host') or + os.environ.get('CXX_host') or + os.environ.get('AR_target') or + os.environ.get('CC_target') or + os.environ.get('CXX_target')) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common_test.py new file mode 100755 index 0000000000000..ad6f9a1438f30 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common_test.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 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. + +"""Unit tests for the common.py file.""" + +import gyp.common +import unittest +import sys + + +class TestTopologicallySorted(unittest.TestCase): + def test_Valid(self): + """Test that sorting works on a valid graph with one possible order.""" + graph = { + 'a': ['b', 'c'], + 'b': [], + 'c': ['d'], + 'd': ['b'], + } + def GetEdge(node): + return tuple(graph[node]) + self.assertEqual( + gyp.common.TopologicallySorted(graph.keys(), GetEdge), + ['a', 'c', 'd', 'b']) + + def test_Cycle(self): + """Test that an exception is thrown on a cyclic graph.""" + graph = { + 'a': ['b'], + 'b': ['c'], + 'c': ['d'], + 'd': ['a'], + } + def GetEdge(node): + return tuple(graph[node]) + self.assertRaises( + gyp.common.CycleError, gyp.common.TopologicallySorted, + graph.keys(), GetEdge) + + +class TestGetFlavor(unittest.TestCase): + """Test that gyp.common.GetFlavor works as intended""" + original_platform = '' + + def setUp(self): + self.original_platform = sys.platform + + def tearDown(self): + sys.platform = self.original_platform + + def assertFlavor(self, expected, argument, param): + sys.platform = argument + self.assertEqual(expected, gyp.common.GetFlavor(param)) + + def test_platform_default(self): + self.assertFlavor('freebsd', 'freebsd9' , {}) + self.assertFlavor('freebsd', 'freebsd10', {}) + self.assertFlavor('openbsd', 'openbsd5' , {}) + self.assertFlavor('solaris', 'sunos5' , {}); + self.assertFlavor('solaris', 'sunos' , {}); + self.assertFlavor('linux' , 'linux2' , {}); + self.assertFlavor('linux' , 'linux3' , {}); + + def test_param(self): + self.assertFlavor('foobar', 'linux2' , {'flavor': 'foobar'}) + + +if __name__ == '__main__': + unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py new file mode 100644 index 0000000000000..841f31f925b05 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py @@ -0,0 +1,162 @@ +# Copyright (c) 2011 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. + +import re +import os +import locale + + +def XmlToString(content, encoding='utf-8', pretty=False): + """ Writes the XML content to disk, touching the file only if it has changed. + + Visual Studio files have a lot of pre-defined structures. This function makes + it easy to represent these structures as Python data structures, instead of + having to create a lot of function calls. + + Each XML element of the content is represented as a list composed of: + 1. The name of the element, a string, + 2. The attributes of the element, a dictionary (optional), and + 3+. The content of the element, if any. Strings are simple text nodes and + lists are child elements. + + Example 1: + + becomes + ['test'] + + Example 2: + + This is + it! + + + becomes + ['myelement', {'a':'value1', 'b':'value2'}, + ['childtype', 'This is'], + ['childtype', 'it!'], + ] + + Args: + content: The structured content to be converted. + encoding: The encoding to report on the first XML line. + pretty: True if we want pretty printing with indents and new lines. + + Returns: + The XML content as a string. + """ + # We create a huge list of all the elements of the file. + xml_parts = ['' % encoding] + if pretty: + xml_parts.append('\n') + _ConstructContentList(xml_parts, content, pretty) + + # Convert it to a string + return ''.join(xml_parts) + + +def _ConstructContentList(xml_parts, specification, pretty, level=0): + """ Appends the XML parts corresponding to the specification. + + Args: + xml_parts: A list of XML parts to be appended to. + specification: The specification of the element. See EasyXml docs. + pretty: True if we want pretty printing with indents and new lines. + level: Indentation level. + """ + # The first item in a specification is the name of the element. + if pretty: + indentation = ' ' * level + new_line = '\n' + else: + indentation = '' + new_line = '' + name = specification[0] + if not isinstance(name, str): + raise Exception('The first item of an EasyXml specification should be ' + 'a string. Specification was ' + str(specification)) + xml_parts.append(indentation + '<' + name) + + # Optionally in second position is a dictionary of the attributes. + rest = specification[1:] + if rest and isinstance(rest[0], dict): + for at, val in sorted(rest[0].iteritems()): + xml_parts.append(' %s="%s"' % (at, _XmlEscape(val, attr=True))) + rest = rest[1:] + if rest: + xml_parts.append('>') + all_strings = reduce(lambda x, y: x and isinstance(y, str), rest, True) + multi_line = not all_strings + if multi_line and new_line: + xml_parts.append(new_line) + for child_spec in rest: + # If it's a string, append a text node. + # Otherwise recurse over that child definition + if isinstance(child_spec, str): + xml_parts.append(_XmlEscape(child_spec)) + else: + _ConstructContentList(xml_parts, child_spec, pretty, level + 1) + if multi_line and indentation: + xml_parts.append(indentation) + xml_parts.append('%s' % (name, new_line)) + else: + xml_parts.append('/>%s' % new_line) + + +def WriteXmlIfChanged(content, path, encoding='utf-8', pretty=False, + win32=False): + """ Writes the XML content to disk, touching the file only if it has changed. + + Args: + content: The structured content to be written. + path: Location of the file. + encoding: The encoding to report on the first line of the XML file. + pretty: True if we want pretty printing with indents and new lines. + """ + xml_string = XmlToString(content, encoding, pretty) + if win32 and os.linesep != '\r\n': + xml_string = xml_string.replace('\n', '\r\n') + + default_encoding = locale.getdefaultlocale()[1] + if default_encoding.upper() != encoding.upper(): + xml_string = xml_string.decode(default_encoding).encode(encoding) + + # Get the old content + try: + f = open(path, 'r') + existing = f.read() + f.close() + except: + existing = None + + # It has changed, write it + if existing != xml_string: + f = open(path, 'w') + f.write(xml_string) + f.close() + + +_xml_escape_map = { + '"': '"', + "'": ''', + '<': '<', + '>': '>', + '&': '&', + '\n': ' ', + '\r': ' ', +} + + +_xml_escape_re = re.compile( + "(%s)" % "|".join(map(re.escape, _xml_escape_map.keys()))) + + +def _XmlEscape(value, attr=False): + """ Escape a string for inclusion in XML.""" + def replace(match): + m = match.string[match.start() : match.end()] + # don't replace single quotes in attrs + if attr and m == "'": + return m + return _xml_escape_map[m] + return _xml_escape_re.sub(replace, value) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py new file mode 100755 index 0000000000000..df64354982c01 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py @@ -0,0 +1,103 @@ +#!/usr/bin/env python + +# Copyright (c) 2011 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. + +""" Unit tests for the easy_xml.py file. """ + +import gyp.easy_xml as easy_xml +import unittest +import StringIO + + +class TestSequenceFunctions(unittest.TestCase): + + def setUp(self): + self.stderr = StringIO.StringIO() + + def test_EasyXml_simple(self): + self.assertEqual( + easy_xml.XmlToString(['test']), + '') + + self.assertEqual( + easy_xml.XmlToString(['test'], encoding='Windows-1252'), + '') + + def test_EasyXml_simple_with_attributes(self): + self.assertEqual( + easy_xml.XmlToString(['test2', {'a': 'value1', 'b': 'value2'}]), + '') + + def test_EasyXml_escaping(self): + original = '\'"\r&\nfoo' + converted = '<test>\'" & foo' + converted_apos = converted.replace("'", ''') + self.assertEqual( + easy_xml.XmlToString(['test3', {'a': original}, original]), + '%s' % + (converted, converted_apos)) + + def test_EasyXml_pretty(self): + self.assertEqual( + easy_xml.XmlToString( + ['test3', + ['GrandParent', + ['Parent1', + ['Child'] + ], + ['Parent2'] + ] + ], + pretty=True), + '\n' + '\n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + ' \n' + '\n') + + + def test_EasyXml_complex(self): + # We want to create: + target = ( + '' + '' + '' + '{D2250C20-3A94-4FB9-AF73-11BC5B73884B}' + 'Win32Proj' + 'automated_ui_tests' + '' + '' + '' + 'Application' + 'Unicode' + '' + '') + + xml = easy_xml.XmlToString( + ['Project', + ['PropertyGroup', {'Label': 'Globals'}, + ['ProjectGuid', '{D2250C20-3A94-4FB9-AF73-11BC5B73884B}'], + ['Keyword', 'Win32Proj'], + ['RootNamespace', 'automated_ui_tests'] + ], + ['Import', {'Project': '$(VCTargetsPath)\\Microsoft.Cpp.props'}], + ['PropertyGroup', + {'Condition': "'$(Configuration)|$(Platform)'=='Debug|Win32'", + 'Label': 'Configuration'}, + ['ConfigurationType', 'Application'], + ['CharacterSet', 'Unicode'] + ] + ]) + self.assertEqual(xml, target) + + +if __name__ == '__main__': + unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py new file mode 100755 index 0000000000000..b38d8660f7285 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py @@ -0,0 +1,54 @@ +#!/usr/bin/env python +# Copyright (c) 2011 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. + +"""These functions are executed via gyp-flock-tool when using the Makefile +generator. Used on systems that don't have a built-in flock.""" + +import fcntl +import os +import struct +import subprocess +import sys + + +def main(args): + executor = FlockTool() + executor.Dispatch(args) + + +class FlockTool(object): + """This class emulates the 'flock' command.""" + def Dispatch(self, args): + """Dispatches a string command to a method.""" + if len(args) < 1: + raise Exception("Not enough arguments") + + method = "Exec%s" % self._CommandifyName(args[0]) + getattr(self, method)(*args[1:]) + + def _CommandifyName(self, name_string): + """Transforms a tool name like copy-info-plist to CopyInfoPlist""" + return name_string.title().replace('-', '') + + def ExecFlock(self, lockfile, *cmd_list): + """Emulates the most basic behavior of Linux's flock(1).""" + # Rely on exception handling to report errors. + # Note that the stock python on SunOS has a bug + # where fcntl.flock(fd, LOCK_EX) always fails + # with EBADF, that's why we use this F_SETLK + # hack instead. + fd = os.open(lockfile, os.O_WRONLY|os.O_NOCTTY|os.O_CREAT, 0666) + if sys.platform.startswith('aix'): + # Python on AIX is compiled with LARGEFILE support, which changes the + # struct size. + op = struct.pack('hhIllqq', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0) + else: + op = struct.pack('hhllhhl', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0) + fcntl.fcntl(fd, fcntl.F_SETLK, op) + return subprocess.call(cmd_list) + + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py new file mode 100644 index 0000000000000..921c1a6b71432 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py @@ -0,0 +1,741 @@ +# Copyright (c) 2014 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. + +""" +This script is intended for use as a GYP_GENERATOR. It takes as input (by way of +the generator flag config_path) the path of a json file that dictates the files +and targets to search for. The following keys are supported: +files: list of paths (relative) of the files to search for. +test_targets: unqualified target names to search for. Any target in this list +that depends upon a file in |files| is output regardless of the type of target +or chain of dependencies. +additional_compile_targets: Unqualified targets to search for in addition to +test_targets. Targets in the combined list that depend upon a file in |files| +are not necessarily output. For example, if the target is of type none then the +target is not output (but one of the descendants of the target will be). + +The following is output: +error: only supplied if there is an error. +compile_targets: minimal set of targets that directly or indirectly (for + targets of type none) depend on the files in |files| and is one of the + supplied targets or a target that one of the supplied targets depends on. + The expectation is this set of targets is passed into a build step. This list + always contains the output of test_targets as well. +test_targets: set of targets from the supplied |test_targets| that either + directly or indirectly depend upon a file in |files|. This list if useful + if additional processing needs to be done for certain targets after the + build, such as running tests. +status: outputs one of three values: none of the supplied files were found, + one of the include files changed so that it should be assumed everything + changed (in this case test_targets and compile_targets are not output) or at + least one file was found. +invalid_targets: list of supplied targets that were not found. + +Example: +Consider a graph like the following: + A D + / \ +B C +A depends upon both B and C, A is of type none and B and C are executables. +D is an executable, has no dependencies and nothing depends on it. +If |additional_compile_targets| = ["A"], |test_targets| = ["B", "C"] and +files = ["b.cc", "d.cc"] (B depends upon b.cc and D depends upon d.cc), then +the following is output: +|compile_targets| = ["B"] B must built as it depends upon the changed file b.cc +and the supplied target A depends upon it. A is not output as a build_target +as it is of type none with no rules and actions. +|test_targets| = ["B"] B directly depends upon the change file b.cc. + +Even though the file d.cc, which D depends upon, has changed D is not output +as it was not supplied by way of |additional_compile_targets| or |test_targets|. + +If the generator flag analyzer_output_path is specified, output is written +there. Otherwise output is written to stdout. + +In Gyp the "all" target is shorthand for the root targets in the files passed +to gyp. For example, if file "a.gyp" contains targets "a1" and +"a2", and file "b.gyp" contains targets "b1" and "b2" and "a2" has a dependency +on "b2" and gyp is supplied "a.gyp" then "all" consists of "a1" and "a2". +Notice that "b1" and "b2" are not in the "all" target as "b.gyp" was not +directly supplied to gyp. OTOH if both "a.gyp" and "b.gyp" are supplied to gyp +then the "all" target includes "b1" and "b2". +""" + +import gyp.common +import gyp.ninja_syntax as ninja_syntax +import json +import os +import posixpath +import sys + +debug = False + +found_dependency_string = 'Found dependency' +no_dependency_string = 'No dependencies' +# Status when it should be assumed that everything has changed. +all_changed_string = 'Found dependency (all)' + +# MatchStatus is used indicate if and how a target depends upon the supplied +# sources. +# The target's sources contain one of the supplied paths. +MATCH_STATUS_MATCHES = 1 +# The target has a dependency on another target that contains one of the +# supplied paths. +MATCH_STATUS_MATCHES_BY_DEPENDENCY = 2 +# The target's sources weren't in the supplied paths and none of the target's +# dependencies depend upon a target that matched. +MATCH_STATUS_DOESNT_MATCH = 3 +# The target doesn't contain the source, but the dependent targets have not yet +# been visited to determine a more specific status yet. +MATCH_STATUS_TBD = 4 + +generator_supports_multiple_toolsets = gyp.common.CrossCompileRequested() + +generator_wants_static_library_dependencies_adjusted = False + +generator_default_variables = { +} +for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR', + 'LIB_DIR', 'SHARED_LIB_DIR']: + generator_default_variables[dirname] = '!!!' + +for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', + 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', + 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX', + 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX', + 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX', + 'CONFIGURATION_NAME']: + generator_default_variables[unused] = '' + + +def _ToGypPath(path): + """Converts a path to the format used by gyp.""" + if os.sep == '\\' and os.altsep == '/': + return path.replace('\\', '/') + return path + + +def _ResolveParent(path, base_path_components): + """Resolves |path|, which starts with at least one '../'. Returns an empty + string if the path shouldn't be considered. See _AddSources() for a + description of |base_path_components|.""" + depth = 0 + while path.startswith('../'): + depth += 1 + path = path[3:] + # Relative includes may go outside the source tree. For example, an action may + # have inputs in /usr/include, which are not in the source tree. + if depth > len(base_path_components): + return '' + if depth == len(base_path_components): + return path + return '/'.join(base_path_components[0:len(base_path_components) - depth]) + \ + '/' + path + + +def _AddSources(sources, base_path, base_path_components, result): + """Extracts valid sources from |sources| and adds them to |result|. Each + source file is relative to |base_path|, but may contain '..'. To make + resolving '..' easier |base_path_components| contains each of the + directories in |base_path|. Additionally each source may contain variables. + Such sources are ignored as it is assumed dependencies on them are expressed + and tracked in some other means.""" + # NOTE: gyp paths are always posix style. + for source in sources: + if not len(source) or source.startswith('!!!') or source.startswith('$'): + continue + # variable expansion may lead to //. + org_source = source + source = source[0] + source[1:].replace('//', '/') + if source.startswith('../'): + source = _ResolveParent(source, base_path_components) + if len(source): + result.append(source) + continue + result.append(base_path + source) + if debug: + print 'AddSource', org_source, result[len(result) - 1] + + +def _ExtractSourcesFromAction(action, base_path, base_path_components, + results): + if 'inputs' in action: + _AddSources(action['inputs'], base_path, base_path_components, results) + + +def _ToLocalPath(toplevel_dir, path): + """Converts |path| to a path relative to |toplevel_dir|.""" + if path == toplevel_dir: + return '' + if path.startswith(toplevel_dir + '/'): + return path[len(toplevel_dir) + len('/'):] + return path + + +def _ExtractSources(target, target_dict, toplevel_dir): + # |target| is either absolute or relative and in the format of the OS. Gyp + # source paths are always posix. Convert |target| to a posix path relative to + # |toplevel_dir_|. This is done to make it easy to build source paths. + base_path = posixpath.dirname(_ToLocalPath(toplevel_dir, _ToGypPath(target))) + base_path_components = base_path.split('/') + + # Add a trailing '/' so that _AddSources() can easily build paths. + if len(base_path): + base_path += '/' + + if debug: + print 'ExtractSources', target, base_path + + results = [] + if 'sources' in target_dict: + _AddSources(target_dict['sources'], base_path, base_path_components, + results) + # Include the inputs from any actions. Any changes to these affect the + # resulting output. + if 'actions' in target_dict: + for action in target_dict['actions']: + _ExtractSourcesFromAction(action, base_path, base_path_components, + results) + if 'rules' in target_dict: + for rule in target_dict['rules']: + _ExtractSourcesFromAction(rule, base_path, base_path_components, results) + + return results + + +class Target(object): + """Holds information about a particular target: + deps: set of Targets this Target depends upon. This is not recursive, only the + direct dependent Targets. + match_status: one of the MatchStatus values. + back_deps: set of Targets that have a dependency on this Target. + visited: used during iteration to indicate whether we've visited this target. + This is used for two iterations, once in building the set of Targets and + again in _GetBuildTargets(). + name: fully qualified name of the target. + requires_build: True if the target type is such that it needs to be built. + See _DoesTargetTypeRequireBuild for details. + added_to_compile_targets: used when determining if the target was added to the + set of targets that needs to be built. + in_roots: true if this target is a descendant of one of the root nodes. + is_executable: true if the type of target is executable. + is_static_library: true if the type of target is static_library. + is_or_has_linked_ancestor: true if the target does a link (eg executable), or + if there is a target in back_deps that does a link.""" + def __init__(self, name): + self.deps = set() + self.match_status = MATCH_STATUS_TBD + self.back_deps = set() + self.name = name + # TODO(sky): I don't like hanging this off Target. This state is specific + # to certain functions and should be isolated there. + self.visited = False + self.requires_build = False + self.added_to_compile_targets = False + self.in_roots = False + self.is_executable = False + self.is_static_library = False + self.is_or_has_linked_ancestor = False + + +class Config(object): + """Details what we're looking for + files: set of files to search for + targets: see file description for details.""" + def __init__(self): + self.files = [] + self.targets = set() + self.additional_compile_target_names = set() + self.test_target_names = set() + + def Init(self, params): + """Initializes Config. This is a separate method as it raises an exception + if there is a parse error.""" + generator_flags = params.get('generator_flags', {}) + config_path = generator_flags.get('config_path', None) + if not config_path: + return + try: + f = open(config_path, 'r') + config = json.load(f) + f.close() + except IOError: + raise Exception('Unable to open file ' + config_path) + except ValueError as e: + raise Exception('Unable to parse config file ' + config_path + str(e)) + if not isinstance(config, dict): + raise Exception('config_path must be a JSON file containing a dictionary') + self.files = config.get('files', []) + self.additional_compile_target_names = set( + config.get('additional_compile_targets', [])) + self.test_target_names = set(config.get('test_targets', [])) + + +def _WasBuildFileModified(build_file, data, files, toplevel_dir): + """Returns true if the build file |build_file| is either in |files| or + one of the files included by |build_file| is in |files|. |toplevel_dir| is + the root of the source tree.""" + if _ToLocalPath(toplevel_dir, _ToGypPath(build_file)) in files: + if debug: + print 'gyp file modified', build_file + return True + + # First element of included_files is the file itself. + if len(data[build_file]['included_files']) <= 1: + return False + + for include_file in data[build_file]['included_files'][1:]: + # |included_files| are relative to the directory of the |build_file|. + rel_include_file = \ + _ToGypPath(gyp.common.UnrelativePath(include_file, build_file)) + if _ToLocalPath(toplevel_dir, rel_include_file) in files: + if debug: + print 'included gyp file modified, gyp_file=', build_file, \ + 'included file=', rel_include_file + return True + return False + + +def _GetOrCreateTargetByName(targets, target_name): + """Creates or returns the Target at targets[target_name]. If there is no + Target for |target_name| one is created. Returns a tuple of whether a new + Target was created and the Target.""" + if target_name in targets: + return False, targets[target_name] + target = Target(target_name) + targets[target_name] = target + return True, target + + +def _DoesTargetTypeRequireBuild(target_dict): + """Returns true if the target type is such that it needs to be built.""" + # If a 'none' target has rules or actions we assume it requires a build. + return bool(target_dict['type'] != 'none' or + target_dict.get('actions') or target_dict.get('rules')) + + +def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files, + build_files): + """Returns a tuple of the following: + . A dictionary mapping from fully qualified name to Target. + . A list of the targets that have a source file in |files|. + . Targets that constitute the 'all' target. See description at top of file + for details on the 'all' target. + This sets the |match_status| of the targets that contain any of the source + files in |files| to MATCH_STATUS_MATCHES. + |toplevel_dir| is the root of the source tree.""" + # Maps from target name to Target. + name_to_target = {} + + # Targets that matched. + matching_targets = [] + + # Queue of targets to visit. + targets_to_visit = target_list[:] + + # Maps from build file to a boolean indicating whether the build file is in + # |files|. + build_file_in_files = {} + + # Root targets across all files. + roots = set() + + # Set of Targets in |build_files|. + build_file_targets = set() + + while len(targets_to_visit) > 0: + target_name = targets_to_visit.pop() + created_target, target = _GetOrCreateTargetByName(name_to_target, + target_name) + if created_target: + roots.add(target) + elif target.visited: + continue + + target.visited = True + target.requires_build = _DoesTargetTypeRequireBuild( + target_dicts[target_name]) + target_type = target_dicts[target_name]['type'] + target.is_executable = target_type == 'executable' + target.is_static_library = target_type == 'static_library' + target.is_or_has_linked_ancestor = (target_type == 'executable' or + target_type == 'shared_library') + + build_file = gyp.common.ParseQualifiedTarget(target_name)[0] + if not build_file in build_file_in_files: + build_file_in_files[build_file] = \ + _WasBuildFileModified(build_file, data, files, toplevel_dir) + + if build_file in build_files: + build_file_targets.add(target) + + # If a build file (or any of its included files) is modified we assume all + # targets in the file are modified. + if build_file_in_files[build_file]: + print 'matching target from modified build file', target_name + target.match_status = MATCH_STATUS_MATCHES + matching_targets.append(target) + else: + sources = _ExtractSources(target_name, target_dicts[target_name], + toplevel_dir) + for source in sources: + if _ToGypPath(os.path.normpath(source)) in files: + print 'target', target_name, 'matches', source + target.match_status = MATCH_STATUS_MATCHES + matching_targets.append(target) + break + + # Add dependencies to visit as well as updating back pointers for deps. + for dep in target_dicts[target_name].get('dependencies', []): + targets_to_visit.append(dep) + + created_dep_target, dep_target = _GetOrCreateTargetByName(name_to_target, + dep) + if not created_dep_target: + roots.discard(dep_target) + + target.deps.add(dep_target) + dep_target.back_deps.add(target) + + return name_to_target, matching_targets, roots & build_file_targets + + +def _GetUnqualifiedToTargetMapping(all_targets, to_find): + """Returns a tuple of the following: + . mapping (dictionary) from unqualified name to Target for all the + Targets in |to_find|. + . any target names not found. If this is empty all targets were found.""" + result = {} + if not to_find: + return {}, [] + to_find = set(to_find) + for target_name in all_targets.keys(): + extracted = gyp.common.ParseQualifiedTarget(target_name) + if len(extracted) > 1 and extracted[1] in to_find: + to_find.remove(extracted[1]) + result[extracted[1]] = all_targets[target_name] + if not to_find: + return result, [] + return result, [x for x in to_find] + + +def _DoesTargetDependOnMatchingTargets(target): + """Returns true if |target| or any of its dependencies is one of the + targets containing the files supplied as input to analyzer. This updates + |matches| of the Targets as it recurses. + target: the Target to look for.""" + if target.match_status == MATCH_STATUS_DOESNT_MATCH: + return False + if target.match_status == MATCH_STATUS_MATCHES or \ + target.match_status == MATCH_STATUS_MATCHES_BY_DEPENDENCY: + return True + for dep in target.deps: + if _DoesTargetDependOnMatchingTargets(dep): + target.match_status = MATCH_STATUS_MATCHES_BY_DEPENDENCY + print '\t', target.name, 'matches by dep', dep.name + return True + target.match_status = MATCH_STATUS_DOESNT_MATCH + return False + + +def _GetTargetsDependingOnMatchingTargets(possible_targets): + """Returns the list of Targets in |possible_targets| that depend (either + directly on indirectly) on at least one of the targets containing the files + supplied as input to analyzer. + possible_targets: targets to search from.""" + found = [] + print 'Targets that matched by dependency:' + for target in possible_targets: + if _DoesTargetDependOnMatchingTargets(target): + found.append(target) + return found + + +def _AddCompileTargets(target, roots, add_if_no_ancestor, result): + """Recurses through all targets that depend on |target|, adding all targets + that need to be built (and are in |roots|) to |result|. + roots: set of root targets. + add_if_no_ancestor: If true and there are no ancestors of |target| then add + |target| to |result|. |target| must still be in |roots|. + result: targets that need to be built are added here.""" + if target.visited: + return + + target.visited = True + target.in_roots = target in roots + + for back_dep_target in target.back_deps: + _AddCompileTargets(back_dep_target, roots, False, result) + target.added_to_compile_targets |= back_dep_target.added_to_compile_targets + target.in_roots |= back_dep_target.in_roots + target.is_or_has_linked_ancestor |= ( + back_dep_target.is_or_has_linked_ancestor) + + # Always add 'executable' targets. Even though they may be built by other + # targets that depend upon them it makes detection of what is going to be + # built easier. + # And always add static_libraries that have no dependencies on them from + # linkables. This is necessary as the other dependencies on them may be + # static libraries themselves, which are not compile time dependencies. + if target.in_roots and \ + (target.is_executable or + (not target.added_to_compile_targets and + (add_if_no_ancestor or target.requires_build)) or + (target.is_static_library and add_if_no_ancestor and + not target.is_or_has_linked_ancestor)): + print '\t\tadding to compile targets', target.name, 'executable', \ + target.is_executable, 'added_to_compile_targets', \ + target.added_to_compile_targets, 'add_if_no_ancestor', \ + add_if_no_ancestor, 'requires_build', target.requires_build, \ + 'is_static_library', target.is_static_library, \ + 'is_or_has_linked_ancestor', target.is_or_has_linked_ancestor + result.add(target) + target.added_to_compile_targets = True + + +def _GetCompileTargets(matching_targets, supplied_targets): + """Returns the set of Targets that require a build. + matching_targets: targets that changed and need to be built. + supplied_targets: set of targets supplied to analyzer to search from.""" + result = set() + for target in matching_targets: + print 'finding compile targets for match', target.name + _AddCompileTargets(target, supplied_targets, True, result) + return result + + +def _WriteOutput(params, **values): + """Writes the output, either to stdout or a file is specified.""" + if 'error' in values: + print 'Error:', values['error'] + if 'status' in values: + print values['status'] + if 'targets' in values: + values['targets'].sort() + print 'Supplied targets that depend on changed files:' + for target in values['targets']: + print '\t', target + if 'invalid_targets' in values: + values['invalid_targets'].sort() + print 'The following targets were not found:' + for target in values['invalid_targets']: + print '\t', target + if 'build_targets' in values: + values['build_targets'].sort() + print 'Targets that require a build:' + for target in values['build_targets']: + print '\t', target + if 'compile_targets' in values: + values['compile_targets'].sort() + print 'Targets that need to be built:' + for target in values['compile_targets']: + print '\t', target + if 'test_targets' in values: + values['test_targets'].sort() + print 'Test targets:' + for target in values['test_targets']: + print '\t', target + + output_path = params.get('generator_flags', {}).get( + 'analyzer_output_path', None) + if not output_path: + print json.dumps(values) + return + try: + f = open(output_path, 'w') + f.write(json.dumps(values) + '\n') + f.close() + except IOError as e: + print 'Error writing to output file', output_path, str(e) + + +def _WasGypIncludeFileModified(params, files): + """Returns true if one of the files in |files| is in the set of included + files.""" + if params['options'].includes: + for include in params['options'].includes: + if _ToGypPath(os.path.normpath(include)) in files: + print 'Include file modified, assuming all changed', include + return True + return False + + +def _NamesNotIn(names, mapping): + """Returns a list of the values in |names| that are not in |mapping|.""" + return [name for name in names if name not in mapping] + + +def _LookupTargets(names, mapping): + """Returns a list of the mapping[name] for each value in |names| that is in + |mapping|.""" + return [mapping[name] for name in names if name in mapping] + + +def CalculateVariables(default_variables, params): + """Calculate additional variables for use in the build (called by gyp).""" + flavor = gyp.common.GetFlavor(params) + if flavor == 'mac': + default_variables.setdefault('OS', 'mac') + elif flavor == 'win': + default_variables.setdefault('OS', 'win') + # Copy additional generator configuration data from VS, which is shared + # by the Windows Ninja generator. + import gyp.generator.msvs as msvs_generator + generator_additional_non_configuration_keys = getattr(msvs_generator, + 'generator_additional_non_configuration_keys', []) + generator_additional_path_sections = getattr(msvs_generator, + 'generator_additional_path_sections', []) + + gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) + else: + operating_system = flavor + if flavor == 'android': + operating_system = 'linux' # Keep this legacy behavior for now. + default_variables.setdefault('OS', operating_system) + + +class TargetCalculator(object): + """Calculates the matching test_targets and matching compile_targets.""" + def __init__(self, files, additional_compile_target_names, test_target_names, + data, target_list, target_dicts, toplevel_dir, build_files): + self._additional_compile_target_names = set(additional_compile_target_names) + self._test_target_names = set(test_target_names) + self._name_to_target, self._changed_targets, self._root_targets = ( + _GenerateTargets(data, target_list, target_dicts, toplevel_dir, + frozenset(files), build_files)) + self._unqualified_mapping, self.invalid_targets = ( + _GetUnqualifiedToTargetMapping(self._name_to_target, + self._supplied_target_names_no_all())) + + def _supplied_target_names(self): + return self._additional_compile_target_names | self._test_target_names + + def _supplied_target_names_no_all(self): + """Returns the supplied test targets without 'all'.""" + result = self._supplied_target_names(); + result.discard('all') + return result + + def is_build_impacted(self): + """Returns true if the supplied files impact the build at all.""" + return self._changed_targets + + def find_matching_test_target_names(self): + """Returns the set of output test targets.""" + assert self.is_build_impacted() + # Find the test targets first. 'all' is special cased to mean all the + # root targets. To deal with all the supplied |test_targets| are expanded + # to include the root targets during lookup. If any of the root targets + # match, we remove it and replace it with 'all'. + test_target_names_no_all = set(self._test_target_names) + test_target_names_no_all.discard('all') + test_targets_no_all = _LookupTargets(test_target_names_no_all, + self._unqualified_mapping) + test_target_names_contains_all = 'all' in self._test_target_names + if test_target_names_contains_all: + test_targets = [x for x in (set(test_targets_no_all) | + set(self._root_targets))] + else: + test_targets = [x for x in test_targets_no_all] + print 'supplied test_targets' + for target_name in self._test_target_names: + print '\t', target_name + print 'found test_targets' + for target in test_targets: + print '\t', target.name + print 'searching for matching test targets' + matching_test_targets = _GetTargetsDependingOnMatchingTargets(test_targets) + matching_test_targets_contains_all = (test_target_names_contains_all and + set(matching_test_targets) & + set(self._root_targets)) + if matching_test_targets_contains_all: + # Remove any of the targets for all that were not explicitly supplied, + # 'all' is subsequentely added to the matching names below. + matching_test_targets = [x for x in (set(matching_test_targets) & + set(test_targets_no_all))] + print 'matched test_targets' + for target in matching_test_targets: + print '\t', target.name + matching_target_names = [gyp.common.ParseQualifiedTarget(target.name)[1] + for target in matching_test_targets] + if matching_test_targets_contains_all: + matching_target_names.append('all') + print '\tall' + return matching_target_names + + def find_matching_compile_target_names(self): + """Returns the set of output compile targets.""" + assert self.is_build_impacted(); + # Compile targets are found by searching up from changed targets. + # Reset the visited status for _GetBuildTargets. + for target in self._name_to_target.itervalues(): + target.visited = False + + supplied_targets = _LookupTargets(self._supplied_target_names_no_all(), + self._unqualified_mapping) + if 'all' in self._supplied_target_names(): + supplied_targets = [x for x in (set(supplied_targets) | + set(self._root_targets))] + print 'Supplied test_targets & compile_targets' + for target in supplied_targets: + print '\t', target.name + print 'Finding compile targets' + compile_targets = _GetCompileTargets(self._changed_targets, + supplied_targets) + return [gyp.common.ParseQualifiedTarget(target.name)[1] + for target in compile_targets] + + +def GenerateOutput(target_list, target_dicts, data, params): + """Called by gyp as the final stage. Outputs results.""" + config = Config() + try: + config.Init(params) + + if not config.files: + raise Exception('Must specify files to analyze via config_path generator ' + 'flag') + + toplevel_dir = _ToGypPath(os.path.abspath(params['options'].toplevel_dir)) + if debug: + print 'toplevel_dir', toplevel_dir + + if _WasGypIncludeFileModified(params, config.files): + result_dict = { 'status': all_changed_string, + 'test_targets': list(config.test_target_names), + 'compile_targets': list( + config.additional_compile_target_names | + config.test_target_names) } + _WriteOutput(params, **result_dict) + return + + calculator = TargetCalculator(config.files, + config.additional_compile_target_names, + config.test_target_names, data, + target_list, target_dicts, toplevel_dir, + params['build_files']) + if not calculator.is_build_impacted(): + result_dict = { 'status': no_dependency_string, + 'test_targets': [], + 'compile_targets': [] } + if calculator.invalid_targets: + result_dict['invalid_targets'] = calculator.invalid_targets + _WriteOutput(params, **result_dict) + return + + test_target_names = calculator.find_matching_test_target_names() + compile_target_names = calculator.find_matching_compile_target_names() + found_at_least_one_target = compile_target_names or test_target_names + result_dict = { 'test_targets': test_target_names, + 'status': found_dependency_string if + found_at_least_one_target else no_dependency_string, + 'compile_targets': list( + set(compile_target_names) | + set(test_target_names)) } + if calculator.invalid_targets: + result_dict['invalid_targets'] = calculator.invalid_targets + _WriteOutput(params, **result_dict) + + except Exception as e: + _WriteOutput(params, error=str(e)) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py new file mode 100644 index 0000000000000..5b26cc785a80e --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py @@ -0,0 +1,1095 @@ +# Copyright (c) 2012 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. + +# Notes: +# +# This generates makefiles suitable for inclusion into the Android build system +# via an Android.mk file. It is based on make.py, the standard makefile +# generator. +# +# The code below generates a separate .mk file for each target, but +# all are sourced by the top-level GypAndroid.mk. This means that all +# variables in .mk-files clobber one another, and furthermore that any +# variables set potentially clash with other Android build system variables. +# Try to avoid setting global variables where possible. + +import gyp +import gyp.common +import gyp.generator.make as make # Reuse global functions from make backend. +import os +import re +import subprocess + +generator_default_variables = { + 'OS': 'android', + 'EXECUTABLE_PREFIX': '', + 'EXECUTABLE_SUFFIX': '', + 'STATIC_LIB_PREFIX': 'lib', + 'SHARED_LIB_PREFIX': 'lib', + 'STATIC_LIB_SUFFIX': '.a', + 'SHARED_LIB_SUFFIX': '.so', + 'INTERMEDIATE_DIR': '$(gyp_intermediate_dir)', + 'SHARED_INTERMEDIATE_DIR': '$(gyp_shared_intermediate_dir)', + 'PRODUCT_DIR': '$(gyp_shared_intermediate_dir)', + 'SHARED_LIB_DIR': '$(builddir)/lib.$(TOOLSET)', + 'LIB_DIR': '$(obj).$(TOOLSET)', + 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python. + 'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s', # This gets expanded by Python. + 'RULE_INPUT_PATH': '$(RULE_SOURCES)', + 'RULE_INPUT_EXT': '$(suffix $<)', + 'RULE_INPUT_NAME': '$(notdir $<)', + 'CONFIGURATION_NAME': '$(GYP_CONFIGURATION)', +} + +# Make supports multiple toolsets +generator_supports_multiple_toolsets = True + + +# Generator-specific gyp specs. +generator_additional_non_configuration_keys = [ + # Boolean to declare that this target does not want its name mangled. + 'android_unmangled_name', + # Map of android build system variables to set. + 'aosp_build_settings', +] +generator_additional_path_sections = [] +generator_extra_sources_for_rules = [] + + +ALL_MODULES_FOOTER = """\ +# "gyp_all_modules" is a concatenation of the "gyp_all_modules" targets from +# all the included sub-makefiles. This is just here to clarify. +gyp_all_modules: +""" + +header = """\ +# This file is generated by gyp; do not edit. + +""" + +# Map gyp target types to Android module classes. +MODULE_CLASSES = { + 'static_library': 'STATIC_LIBRARIES', + 'shared_library': 'SHARED_LIBRARIES', + 'executable': 'EXECUTABLES', +} + + +def IsCPPExtension(ext): + return make.COMPILABLE_EXTENSIONS.get(ext) == 'cxx' + + +def Sourceify(path): + """Convert a path to its source directory form. The Android backend does not + support options.generator_output, so this function is a noop.""" + return path + + +# Map from qualified target to path to output. +# For Android, the target of these maps is a tuple ('static', 'modulename'), +# ('dynamic', 'modulename'), or ('path', 'some/path') instead of a string, +# since we link by module. +target_outputs = {} +# Map from qualified target to any linkable output. A subset +# of target_outputs. E.g. when mybinary depends on liba, we want to +# include liba in the linker line; when otherbinary depends on +# mybinary, we just want to build mybinary first. +target_link_deps = {} + + +class AndroidMkWriter(object): + """AndroidMkWriter packages up the writing of one target-specific Android.mk. + + Its only real entry point is Write(), and is mostly used for namespacing. + """ + + def __init__(self, android_top_dir): + self.android_top_dir = android_top_dir + + def Write(self, qualified_target, relative_target, base_path, output_filename, + spec, configs, part_of_all, write_alias_target, sdk_version): + """The main entry point: writes a .mk file for a single target. + + Arguments: + qualified_target: target we're generating + relative_target: qualified target name relative to the root + base_path: path relative to source root we're building in, used to resolve + target-relative paths + output_filename: output .mk file name to write + spec, configs: gyp info + part_of_all: flag indicating this target is part of 'all' + write_alias_target: flag indicating whether to create short aliases for + this target + sdk_version: what to emit for LOCAL_SDK_VERSION in output + """ + gyp.common.EnsureDirExists(output_filename) + + self.fp = open(output_filename, 'w') + + self.fp.write(header) + + self.qualified_target = qualified_target + self.relative_target = relative_target + self.path = base_path + self.target = spec['target_name'] + self.type = spec['type'] + self.toolset = spec['toolset'] + + deps, link_deps = self.ComputeDeps(spec) + + # Some of the generation below can add extra output, sources, or + # link dependencies. All of the out params of the functions that + # follow use names like extra_foo. + extra_outputs = [] + extra_sources = [] + + self.android_class = MODULE_CLASSES.get(self.type, 'GYP') + self.android_module = self.ComputeAndroidModule(spec) + (self.android_stem, self.android_suffix) = self.ComputeOutputParts(spec) + self.output = self.output_binary = self.ComputeOutput(spec) + + # Standard header. + self.WriteLn('include $(CLEAR_VARS)\n') + + # Module class and name. + self.WriteLn('LOCAL_MODULE_CLASS := ' + self.android_class) + self.WriteLn('LOCAL_MODULE := ' + self.android_module) + # Only emit LOCAL_MODULE_STEM if it's different to LOCAL_MODULE. + # The library module classes fail if the stem is set. ComputeOutputParts + # makes sure that stem == modulename in these cases. + if self.android_stem != self.android_module: + self.WriteLn('LOCAL_MODULE_STEM := ' + self.android_stem) + self.WriteLn('LOCAL_MODULE_SUFFIX := ' + self.android_suffix) + if self.toolset == 'host': + self.WriteLn('LOCAL_IS_HOST_MODULE := true') + self.WriteLn('LOCAL_MULTILIB := $(GYP_HOST_MULTILIB)') + elif sdk_version > 0: + self.WriteLn('LOCAL_MODULE_TARGET_ARCH := ' + '$(TARGET_$(GYP_VAR_PREFIX)ARCH)') + self.WriteLn('LOCAL_SDK_VERSION := %s' % sdk_version) + + # Grab output directories; needed for Actions and Rules. + if self.toolset == 'host': + self.WriteLn('gyp_intermediate_dir := ' + '$(call local-intermediates-dir,,$(GYP_HOST_VAR_PREFIX))') + else: + self.WriteLn('gyp_intermediate_dir := ' + '$(call local-intermediates-dir,,$(GYP_VAR_PREFIX))') + self.WriteLn('gyp_shared_intermediate_dir := ' + '$(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))') + self.WriteLn() + + # List files this target depends on so that actions/rules/copies/sources + # can depend on the list. + # TODO: doesn't pull in things through transitive link deps; needed? + target_dependencies = [x[1] for x in deps if x[0] == 'path'] + self.WriteLn('# Make sure our deps are built first.') + self.WriteList(target_dependencies, 'GYP_TARGET_DEPENDENCIES', + local_pathify=True) + + # Actions must come first, since they can generate more OBJs for use below. + if 'actions' in spec: + self.WriteActions(spec['actions'], extra_sources, extra_outputs) + + # Rules must be early like actions. + if 'rules' in spec: + self.WriteRules(spec['rules'], extra_sources, extra_outputs) + + if 'copies' in spec: + self.WriteCopies(spec['copies'], extra_outputs) + + # GYP generated outputs. + self.WriteList(extra_outputs, 'GYP_GENERATED_OUTPUTS', local_pathify=True) + + # Set LOCAL_ADDITIONAL_DEPENDENCIES so that Android's build rules depend + # on both our dependency targets and our generated files. + self.WriteLn('# Make sure our deps and generated files are built first.') + self.WriteLn('LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) ' + '$(GYP_GENERATED_OUTPUTS)') + self.WriteLn() + + # Sources. + if spec.get('sources', []) or extra_sources: + self.WriteSources(spec, configs, extra_sources) + + self.WriteTarget(spec, configs, deps, link_deps, part_of_all, + write_alias_target) + + # Update global list of target outputs, used in dependency tracking. + target_outputs[qualified_target] = ('path', self.output_binary) + + # Update global list of link dependencies. + if self.type == 'static_library': + target_link_deps[qualified_target] = ('static', self.android_module) + elif self.type == 'shared_library': + target_link_deps[qualified_target] = ('shared', self.android_module) + + self.fp.close() + return self.android_module + + + def WriteActions(self, actions, extra_sources, extra_outputs): + """Write Makefile code for any 'actions' from the gyp input. + + extra_sources: a list that will be filled in with newly generated source + files, if any + extra_outputs: a list that will be filled in with any outputs of these + actions (used to make other pieces dependent on these + actions) + """ + for action in actions: + name = make.StringToMakefileVariable('%s_%s' % (self.relative_target, + action['action_name'])) + self.WriteLn('### Rules for action "%s":' % action['action_name']) + inputs = action['inputs'] + outputs = action['outputs'] + + # Build up a list of outputs. + # Collect the output dirs we'll need. + dirs = set() + for out in outputs: + if not out.startswith('$'): + print ('WARNING: Action for target "%s" writes output to local path ' + '"%s".' % (self.target, out)) + dir = os.path.split(out)[0] + if dir: + dirs.add(dir) + if int(action.get('process_outputs_as_sources', False)): + extra_sources += outputs + + # Prepare the actual command. + command = gyp.common.EncodePOSIXShellList(action['action']) + if 'message' in action: + quiet_cmd = 'Gyp action: %s ($@)' % action['message'] + else: + quiet_cmd = 'Gyp action: %s ($@)' % name + if len(dirs) > 0: + command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command + + cd_action = 'cd $(gyp_local_path)/%s; ' % self.path + command = cd_action + command + + # The makefile rules are all relative to the top dir, but the gyp actions + # are defined relative to their containing dir. This replaces the gyp_* + # variables for the action rule with an absolute version so that the + # output goes in the right place. + # Only write the gyp_* rules for the "primary" output (:1); + # it's superfluous for the "extra outputs", and this avoids accidentally + # writing duplicate dummy rules for those outputs. + main_output = make.QuoteSpaces(self.LocalPathify(outputs[0])) + self.WriteLn('%s: gyp_local_path := $(LOCAL_PATH)' % main_output) + self.WriteLn('%s: gyp_var_prefix := $(GYP_VAR_PREFIX)' % main_output) + self.WriteLn('%s: gyp_intermediate_dir := ' + '$(abspath $(gyp_intermediate_dir))' % main_output) + self.WriteLn('%s: gyp_shared_intermediate_dir := ' + '$(abspath $(gyp_shared_intermediate_dir))' % main_output) + + # Android's envsetup.sh adds a number of directories to the path including + # the built host binary directory. This causes actions/rules invoked by + # gyp to sometimes use these instead of system versions, e.g. bison. + # The built host binaries may not be suitable, and can cause errors. + # So, we remove them from the PATH using the ANDROID_BUILD_PATHS variable + # set by envsetup. + self.WriteLn('%s: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))' + % main_output) + + # Don't allow spaces in input/output filenames, but make an exception for + # filenames which start with '$(' since it's okay for there to be spaces + # inside of make function/macro invocations. + for input in inputs: + if not input.startswith('$(') and ' ' in input: + raise gyp.common.GypError( + 'Action input filename "%s" in target %s contains a space' % + (input, self.target)) + for output in outputs: + if not output.startswith('$(') and ' ' in output: + raise gyp.common.GypError( + 'Action output filename "%s" in target %s contains a space' % + (output, self.target)) + + self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' % + (main_output, ' '.join(map(self.LocalPathify, inputs)))) + self.WriteLn('\t@echo "%s"' % quiet_cmd) + self.WriteLn('\t$(hide)%s\n' % command) + for output in outputs[1:]: + # Make each output depend on the main output, with an empty command + # to force make to notice that the mtime has changed. + self.WriteLn('%s: %s ;' % (self.LocalPathify(output), main_output)) + + extra_outputs += outputs + self.WriteLn() + + self.WriteLn() + + + def WriteRules(self, rules, extra_sources, extra_outputs): + """Write Makefile code for any 'rules' from the gyp input. + + extra_sources: a list that will be filled in with newly generated source + files, if any + extra_outputs: a list that will be filled in with any outputs of these + rules (used to make other pieces dependent on these rules) + """ + if len(rules) == 0: + return + + for rule in rules: + if len(rule.get('rule_sources', [])) == 0: + continue + name = make.StringToMakefileVariable('%s_%s' % (self.relative_target, + rule['rule_name'])) + self.WriteLn('\n### Generated for rule "%s":' % name) + self.WriteLn('# "%s":' % rule) + + inputs = rule.get('inputs') + for rule_source in rule.get('rule_sources', []): + (rule_source_dirname, rule_source_basename) = os.path.split(rule_source) + (rule_source_root, rule_source_ext) = \ + os.path.splitext(rule_source_basename) + + outputs = [self.ExpandInputRoot(out, rule_source_root, + rule_source_dirname) + for out in rule['outputs']] + + dirs = set() + for out in outputs: + if not out.startswith('$'): + print ('WARNING: Rule for target %s writes output to local path %s' + % (self.target, out)) + dir = os.path.dirname(out) + if dir: + dirs.add(dir) + extra_outputs += outputs + if int(rule.get('process_outputs_as_sources', False)): + extra_sources.extend(outputs) + + components = [] + for component in rule['action']: + component = self.ExpandInputRoot(component, rule_source_root, + rule_source_dirname) + if '$(RULE_SOURCES)' in component: + component = component.replace('$(RULE_SOURCES)', + rule_source) + components.append(component) + + command = gyp.common.EncodePOSIXShellList(components) + cd_action = 'cd $(gyp_local_path)/%s; ' % self.path + command = cd_action + command + if dirs: + command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command + + # We set up a rule to build the first output, and then set up + # a rule for each additional output to depend on the first. + outputs = map(self.LocalPathify, outputs) + main_output = outputs[0] + self.WriteLn('%s: gyp_local_path := $(LOCAL_PATH)' % main_output) + self.WriteLn('%s: gyp_var_prefix := $(GYP_VAR_PREFIX)' % main_output) + self.WriteLn('%s: gyp_intermediate_dir := ' + '$(abspath $(gyp_intermediate_dir))' % main_output) + self.WriteLn('%s: gyp_shared_intermediate_dir := ' + '$(abspath $(gyp_shared_intermediate_dir))' % main_output) + + # See explanation in WriteActions. + self.WriteLn('%s: export PATH := ' + '$(subst $(ANDROID_BUILD_PATHS),,$(PATH))' % main_output) + + main_output_deps = self.LocalPathify(rule_source) + if inputs: + main_output_deps += ' ' + main_output_deps += ' '.join([self.LocalPathify(f) for f in inputs]) + + self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' % + (main_output, main_output_deps)) + self.WriteLn('\t%s\n' % command) + for output in outputs[1:]: + # Make each output depend on the main output, with an empty command + # to force make to notice that the mtime has changed. + self.WriteLn('%s: %s ;' % (output, main_output)) + self.WriteLn() + + self.WriteLn() + + + def WriteCopies(self, copies, extra_outputs): + """Write Makefile code for any 'copies' from the gyp input. + + extra_outputs: a list that will be filled in with any outputs of this action + (used to make other pieces dependent on this action) + """ + self.WriteLn('### Generated for copy rule.') + + variable = make.StringToMakefileVariable(self.relative_target + '_copies') + outputs = [] + for copy in copies: + for path in copy['files']: + # The Android build system does not allow generation of files into the + # source tree. The destination should start with a variable, which will + # typically be $(gyp_intermediate_dir) or + # $(gyp_shared_intermediate_dir). Note that we can't use an assertion + # because some of the gyp tests depend on this. + if not copy['destination'].startswith('$'): + print ('WARNING: Copy rule for target %s writes output to ' + 'local path %s' % (self.target, copy['destination'])) + + # LocalPathify() calls normpath, stripping trailing slashes. + path = Sourceify(self.LocalPathify(path)) + filename = os.path.split(path)[1] + output = Sourceify(self.LocalPathify(os.path.join(copy['destination'], + filename))) + + self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES) | $(ACP)' % + (output, path)) + self.WriteLn('\t@echo Copying: $@') + self.WriteLn('\t$(hide) mkdir -p $(dir $@)') + self.WriteLn('\t$(hide) $(ACP) -rpf $< $@') + self.WriteLn() + outputs.append(output) + self.WriteLn('%s = %s' % (variable, + ' '.join(map(make.QuoteSpaces, outputs)))) + extra_outputs.append('$(%s)' % variable) + self.WriteLn() + + + def WriteSourceFlags(self, spec, configs): + """Write out the flags and include paths used to compile source files for + the current target. + + Args: + spec, configs: input from gyp. + """ + for configname, config in sorted(configs.iteritems()): + extracted_includes = [] + + self.WriteLn('\n# Flags passed to both C and C++ files.') + cflags, includes_from_cflags = self.ExtractIncludesFromCFlags( + config.get('cflags', []) + config.get('cflags_c', [])) + extracted_includes.extend(includes_from_cflags) + self.WriteList(cflags, 'MY_CFLAGS_%s' % configname) + + self.WriteList(config.get('defines'), 'MY_DEFS_%s' % configname, + prefix='-D', quoter=make.EscapeCppDefine) + + self.WriteLn('\n# Include paths placed before CFLAGS/CPPFLAGS') + includes = list(config.get('include_dirs', [])) + includes.extend(extracted_includes) + includes = map(Sourceify, map(self.LocalPathify, includes)) + includes = self.NormalizeIncludePaths(includes) + self.WriteList(includes, 'LOCAL_C_INCLUDES_%s' % configname) + + self.WriteLn('\n# Flags passed to only C++ (and not C) files.') + self.WriteList(config.get('cflags_cc'), 'LOCAL_CPPFLAGS_%s' % configname) + + self.WriteLn('\nLOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) ' + '$(MY_DEFS_$(GYP_CONFIGURATION))') + # Undefine ANDROID for host modules + # TODO: the source code should not use macro ANDROID to tell if it's host + # or target module. + if self.toolset == 'host': + self.WriteLn('# Undefine ANDROID for host modules') + self.WriteLn('LOCAL_CFLAGS += -UANDROID') + self.WriteLn('LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) ' + '$(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))') + self.WriteLn('LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))') + # Android uses separate flags for assembly file invocations, but gyp expects + # the same CFLAGS to be applied: + self.WriteLn('LOCAL_ASFLAGS := $(LOCAL_CFLAGS)') + + + def WriteSources(self, spec, configs, extra_sources): + """Write Makefile code for any 'sources' from the gyp input. + These are source files necessary to build the current target. + We need to handle shared_intermediate directory source files as + a special case by copying them to the intermediate directory and + treating them as a genereated sources. Otherwise the Android build + rules won't pick them up. + + Args: + spec, configs: input from gyp. + extra_sources: Sources generated from Actions or Rules. + """ + sources = filter(make.Compilable, spec.get('sources', [])) + generated_not_sources = [x for x in extra_sources if not make.Compilable(x)] + extra_sources = filter(make.Compilable, extra_sources) + + # Determine and output the C++ extension used by these sources. + # We simply find the first C++ file and use that extension. + all_sources = sources + extra_sources + local_cpp_extension = '.cpp' + for source in all_sources: + (root, ext) = os.path.splitext(source) + if IsCPPExtension(ext): + local_cpp_extension = ext + break + if local_cpp_extension != '.cpp': + self.WriteLn('LOCAL_CPP_EXTENSION := %s' % local_cpp_extension) + + # We need to move any non-generated sources that are coming from the + # shared intermediate directory out of LOCAL_SRC_FILES and put them + # into LOCAL_GENERATED_SOURCES. We also need to move over any C++ files + # that don't match our local_cpp_extension, since Android will only + # generate Makefile rules for a single LOCAL_CPP_EXTENSION. + local_files = [] + for source in sources: + (root, ext) = os.path.splitext(source) + if '$(gyp_shared_intermediate_dir)' in source: + extra_sources.append(source) + elif '$(gyp_intermediate_dir)' in source: + extra_sources.append(source) + elif IsCPPExtension(ext) and ext != local_cpp_extension: + extra_sources.append(source) + else: + local_files.append(os.path.normpath(os.path.join(self.path, source))) + + # For any generated source, if it is coming from the shared intermediate + # directory then we add a Make rule to copy them to the local intermediate + # directory first. This is because the Android LOCAL_GENERATED_SOURCES + # must be in the local module intermediate directory for the compile rules + # to work properly. If the file has the wrong C++ extension, then we add + # a rule to copy that to intermediates and use the new version. + final_generated_sources = [] + # If a source file gets copied, we still need to add the orginal source + # directory as header search path, for GCC searches headers in the + # directory that contains the source file by default. + origin_src_dirs = [] + for source in extra_sources: + local_file = source + if not '$(gyp_intermediate_dir)/' in local_file: + basename = os.path.basename(local_file) + local_file = '$(gyp_intermediate_dir)/' + basename + (root, ext) = os.path.splitext(local_file) + if IsCPPExtension(ext) and ext != local_cpp_extension: + local_file = root + local_cpp_extension + if local_file != source: + self.WriteLn('%s: %s' % (local_file, self.LocalPathify(source))) + self.WriteLn('\tmkdir -p $(@D); cp $< $@') + origin_src_dirs.append(os.path.dirname(source)) + final_generated_sources.append(local_file) + + # We add back in all of the non-compilable stuff to make sure that the + # make rules have dependencies on them. + final_generated_sources.extend(generated_not_sources) + self.WriteList(final_generated_sources, 'LOCAL_GENERATED_SOURCES') + + origin_src_dirs = gyp.common.uniquer(origin_src_dirs) + origin_src_dirs = map(Sourceify, map(self.LocalPathify, origin_src_dirs)) + self.WriteList(origin_src_dirs, 'GYP_COPIED_SOURCE_ORIGIN_DIRS') + + self.WriteList(local_files, 'LOCAL_SRC_FILES') + + # Write out the flags used to compile the source; this must be done last + # so that GYP_COPIED_SOURCE_ORIGIN_DIRS can be used as an include path. + self.WriteSourceFlags(spec, configs) + + + def ComputeAndroidModule(self, spec): + """Return the Android module name used for a gyp spec. + + We use the complete qualified target name to avoid collisions between + duplicate targets in different directories. We also add a suffix to + distinguish gyp-generated module names. + """ + + if int(spec.get('android_unmangled_name', 0)): + assert self.type != 'shared_library' or self.target.startswith('lib') + return self.target + + if self.type == 'shared_library': + # For reasons of convention, the Android build system requires that all + # shared library modules are named 'libfoo' when generating -l flags. + prefix = 'lib_' + else: + prefix = '' + + if spec['toolset'] == 'host': + suffix = '_$(TARGET_$(GYP_VAR_PREFIX)ARCH)_host_gyp' + else: + suffix = '_gyp' + + if self.path: + middle = make.StringToMakefileVariable('%s_%s' % (self.path, self.target)) + else: + middle = make.StringToMakefileVariable(self.target) + + return ''.join([prefix, middle, suffix]) + + + def ComputeOutputParts(self, spec): + """Return the 'output basename' of a gyp spec, split into filename + ext. + + Android libraries must be named the same thing as their module name, + otherwise the linker can't find them, so product_name and so on must be + ignored if we are building a library, and the "lib" prepending is + not done for Android. + """ + assert self.type != 'loadable_module' # TODO: not supported? + + target = spec['target_name'] + target_prefix = '' + target_ext = '' + if self.type == 'static_library': + target = self.ComputeAndroidModule(spec) + target_ext = '.a' + elif self.type == 'shared_library': + target = self.ComputeAndroidModule(spec) + target_ext = '.so' + elif self.type == 'none': + target_ext = '.stamp' + elif self.type != 'executable': + print ("ERROR: What output file should be generated?", + "type", self.type, "target", target) + + if self.type != 'static_library' and self.type != 'shared_library': + target_prefix = spec.get('product_prefix', target_prefix) + target = spec.get('product_name', target) + product_ext = spec.get('product_extension') + if product_ext: + target_ext = '.' + product_ext + + target_stem = target_prefix + target + return (target_stem, target_ext) + + + def ComputeOutputBasename(self, spec): + """Return the 'output basename' of a gyp spec. + + E.g., the loadable module 'foobar' in directory 'baz' will produce + 'libfoobar.so' + """ + return ''.join(self.ComputeOutputParts(spec)) + + + def ComputeOutput(self, spec): + """Return the 'output' (full output path) of a gyp spec. + + E.g., the loadable module 'foobar' in directory 'baz' will produce + '$(obj)/baz/libfoobar.so' + """ + if self.type == 'executable': + # We install host executables into shared_intermediate_dir so they can be + # run by gyp rules that refer to PRODUCT_DIR. + path = '$(gyp_shared_intermediate_dir)' + elif self.type == 'shared_library': + if self.toolset == 'host': + path = '$($(GYP_HOST_VAR_PREFIX)HOST_OUT_INTERMEDIATE_LIBRARIES)' + else: + path = '$($(GYP_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)' + else: + # Other targets just get built into their intermediate dir. + if self.toolset == 'host': + path = ('$(call intermediates-dir-for,%s,%s,true,,' + '$(GYP_HOST_VAR_PREFIX))' % (self.android_class, + self.android_module)) + else: + path = ('$(call intermediates-dir-for,%s,%s,,,$(GYP_VAR_PREFIX))' + % (self.android_class, self.android_module)) + + assert spec.get('product_dir') is None # TODO: not supported? + return os.path.join(path, self.ComputeOutputBasename(spec)) + + def NormalizeIncludePaths(self, include_paths): + """ Normalize include_paths. + Convert absolute paths to relative to the Android top directory. + + Args: + include_paths: A list of unprocessed include paths. + Returns: + A list of normalized include paths. + """ + normalized = [] + for path in include_paths: + if path[0] == '/': + path = gyp.common.RelativePath(path, self.android_top_dir) + normalized.append(path) + return normalized + + def ExtractIncludesFromCFlags(self, cflags): + """Extract includes "-I..." out from cflags + + Args: + cflags: A list of compiler flags, which may be mixed with "-I.." + Returns: + A tuple of lists: (clean_clfags, include_paths). "-I.." is trimmed. + """ + clean_cflags = [] + include_paths = [] + for flag in cflags: + if flag.startswith('-I'): + include_paths.append(flag[2:]) + else: + clean_cflags.append(flag) + + return (clean_cflags, include_paths) + + def FilterLibraries(self, libraries): + """Filter the 'libraries' key to separate things that shouldn't be ldflags. + + Library entries that look like filenames should be converted to android + module names instead of being passed to the linker as flags. + + Args: + libraries: the value of spec.get('libraries') + Returns: + A tuple (static_lib_modules, dynamic_lib_modules, ldflags) + """ + static_lib_modules = [] + dynamic_lib_modules = [] + ldflags = [] + for libs in libraries: + # Libs can have multiple words. + for lib in libs.split(): + # Filter the system libraries, which are added by default by the Android + # build system. + if (lib == '-lc' or lib == '-lstdc++' or lib == '-lm' or + lib.endswith('libgcc.a')): + continue + match = re.search(r'([^/]+)\.a$', lib) + if match: + static_lib_modules.append(match.group(1)) + continue + match = re.search(r'([^/]+)\.so$', lib) + if match: + dynamic_lib_modules.append(match.group(1)) + continue + if lib.startswith('-l'): + ldflags.append(lib) + return (static_lib_modules, dynamic_lib_modules, ldflags) + + + def ComputeDeps(self, spec): + """Compute the dependencies of a gyp spec. + + Returns a tuple (deps, link_deps), where each is a list of + filenames that will need to be put in front of make for either + building (deps) or linking (link_deps). + """ + deps = [] + link_deps = [] + if 'dependencies' in spec: + deps.extend([target_outputs[dep] for dep in spec['dependencies'] + if target_outputs[dep]]) + for dep in spec['dependencies']: + if dep in target_link_deps: + link_deps.append(target_link_deps[dep]) + deps.extend(link_deps) + return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps)) + + + def WriteTargetFlags(self, spec, configs, link_deps): + """Write Makefile code to specify the link flags and library dependencies. + + spec, configs: input from gyp. + link_deps: link dependency list; see ComputeDeps() + """ + # Libraries (i.e. -lfoo) + # These must be included even for static libraries as some of them provide + # implicit include paths through the build system. + libraries = gyp.common.uniquer(spec.get('libraries', [])) + static_libs, dynamic_libs, ldflags_libs = self.FilterLibraries(libraries) + + if self.type != 'static_library': + for configname, config in sorted(configs.iteritems()): + ldflags = list(config.get('ldflags', [])) + self.WriteLn('') + self.WriteList(ldflags, 'LOCAL_LDFLAGS_%s' % configname) + self.WriteList(ldflags_libs, 'LOCAL_GYP_LIBS') + self.WriteLn('LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION)) ' + '$(LOCAL_GYP_LIBS)') + + # Link dependencies (i.e. other gyp targets this target depends on) + # These need not be included for static libraries as within the gyp build + # we do not use the implicit include path mechanism. + if self.type != 'static_library': + static_link_deps = [x[1] for x in link_deps if x[0] == 'static'] + shared_link_deps = [x[1] for x in link_deps if x[0] == 'shared'] + else: + static_link_deps = [] + shared_link_deps = [] + + # Only write the lists if they are non-empty. + if static_libs or static_link_deps: + self.WriteLn('') + self.WriteList(static_libs + static_link_deps, + 'LOCAL_STATIC_LIBRARIES') + self.WriteLn('# Enable grouping to fix circular references') + self.WriteLn('LOCAL_GROUP_STATIC_LIBRARIES := true') + if dynamic_libs or shared_link_deps: + self.WriteLn('') + self.WriteList(dynamic_libs + shared_link_deps, + 'LOCAL_SHARED_LIBRARIES') + + + def WriteTarget(self, spec, configs, deps, link_deps, part_of_all, + write_alias_target): + """Write Makefile code to produce the final target of the gyp spec. + + spec, configs: input from gyp. + deps, link_deps: dependency lists; see ComputeDeps() + part_of_all: flag indicating this target is part of 'all' + write_alias_target: flag indicating whether to create short aliases for this + target + """ + self.WriteLn('### Rules for final target.') + + if self.type != 'none': + self.WriteTargetFlags(spec, configs, link_deps) + + settings = spec.get('aosp_build_settings', {}) + if settings: + self.WriteLn('### Set directly by aosp_build_settings.') + for k, v in settings.iteritems(): + if isinstance(v, list): + self.WriteList(v, k) + else: + self.WriteLn('%s := %s' % (k, make.QuoteIfNecessary(v))) + self.WriteLn('') + + # Add to the set of targets which represent the gyp 'all' target. We use the + # name 'gyp_all_modules' as the Android build system doesn't allow the use + # of the Make target 'all' and because 'all_modules' is the equivalent of + # the Make target 'all' on Android. + if part_of_all and write_alias_target: + self.WriteLn('# Add target alias to "gyp_all_modules" target.') + self.WriteLn('.PHONY: gyp_all_modules') + self.WriteLn('gyp_all_modules: %s' % self.android_module) + self.WriteLn('') + + # Add an alias from the gyp target name to the Android module name. This + # simplifies manual builds of the target, and is required by the test + # framework. + if self.target != self.android_module and write_alias_target: + self.WriteLn('# Alias gyp target name.') + self.WriteLn('.PHONY: %s' % self.target) + self.WriteLn('%s: %s' % (self.target, self.android_module)) + self.WriteLn('') + + # Add the command to trigger build of the target type depending + # on the toolset. Ex: BUILD_STATIC_LIBRARY vs. BUILD_HOST_STATIC_LIBRARY + # NOTE: This has to come last! + modifier = '' + if self.toolset == 'host': + modifier = 'HOST_' + if self.type == 'static_library': + self.WriteLn('include $(BUILD_%sSTATIC_LIBRARY)' % modifier) + elif self.type == 'shared_library': + self.WriteLn('LOCAL_PRELINK_MODULE := false') + self.WriteLn('include $(BUILD_%sSHARED_LIBRARY)' % modifier) + elif self.type == 'executable': + self.WriteLn('LOCAL_CXX_STL := libc++_static') + # Executables are for build and test purposes only, so they're installed + # to a directory that doesn't get included in the system image. + self.WriteLn('LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)') + self.WriteLn('include $(BUILD_%sEXECUTABLE)' % modifier) + else: + self.WriteLn('LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp') + self.WriteLn('LOCAL_UNINSTALLABLE_MODULE := true') + if self.toolset == 'target': + self.WriteLn('LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)') + else: + self.WriteLn('LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_HOST_VAR_PREFIX)') + self.WriteLn() + self.WriteLn('include $(BUILD_SYSTEM)/base_rules.mk') + self.WriteLn() + self.WriteLn('$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)') + self.WriteLn('\t$(hide) echo "Gyp timestamp: $@"') + self.WriteLn('\t$(hide) mkdir -p $(dir $@)') + self.WriteLn('\t$(hide) touch $@') + self.WriteLn() + self.WriteLn('LOCAL_2ND_ARCH_VAR_PREFIX :=') + + + def WriteList(self, value_list, variable=None, prefix='', + quoter=make.QuoteIfNecessary, local_pathify=False): + """Write a variable definition that is a list of values. + + E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out + foo = blaha blahb + but in a pretty-printed style. + """ + values = '' + if value_list: + value_list = [quoter(prefix + l) for l in value_list] + if local_pathify: + value_list = [self.LocalPathify(l) for l in value_list] + values = ' \\\n\t' + ' \\\n\t'.join(value_list) + self.fp.write('%s :=%s\n\n' % (variable, values)) + + + def WriteLn(self, text=''): + self.fp.write(text + '\n') + + + def LocalPathify(self, path): + """Convert a subdirectory-relative path into a normalized path which starts + with the make variable $(LOCAL_PATH) (i.e. the top of the project tree). + Absolute paths, or paths that contain variables, are just normalized.""" + if '$(' in path or os.path.isabs(path): + # path is not a file in the project tree in this case, but calling + # normpath is still important for trimming trailing slashes. + return os.path.normpath(path) + local_path = os.path.join('$(LOCAL_PATH)', self.path, path) + local_path = os.path.normpath(local_path) + # Check that normalizing the path didn't ../ itself out of $(LOCAL_PATH) + # - i.e. that the resulting path is still inside the project tree. The + # path may legitimately have ended up containing just $(LOCAL_PATH), though, + # so we don't look for a slash. + assert local_path.startswith('$(LOCAL_PATH)'), ( + 'Path %s attempts to escape from gyp path %s !)' % (path, self.path)) + return local_path + + + def ExpandInputRoot(self, template, expansion, dirname): + if '%(INPUT_ROOT)s' not in template and '%(INPUT_DIRNAME)s' not in template: + return template + path = template % { + 'INPUT_ROOT': expansion, + 'INPUT_DIRNAME': dirname, + } + return os.path.normpath(path) + + +def PerformBuild(data, configurations, params): + # The android backend only supports the default configuration. + options = params['options'] + makefile = os.path.abspath(os.path.join(options.toplevel_dir, + 'GypAndroid.mk')) + env = dict(os.environ) + env['ONE_SHOT_MAKEFILE'] = makefile + arguments = ['make', '-C', os.environ['ANDROID_BUILD_TOP'], 'gyp_all_modules'] + print 'Building: %s' % arguments + subprocess.check_call(arguments, env=env) + + +def GenerateOutput(target_list, target_dicts, data, params): + options = params['options'] + generator_flags = params.get('generator_flags', {}) + builddir_name = generator_flags.get('output_dir', 'out') + limit_to_target_all = generator_flags.get('limit_to_target_all', False) + write_alias_targets = generator_flags.get('write_alias_targets', True) + sdk_version = generator_flags.get('aosp_sdk_version', 0) + android_top_dir = os.environ.get('ANDROID_BUILD_TOP') + assert android_top_dir, '$ANDROID_BUILD_TOP not set; you need to run lunch.' + + def CalculateMakefilePath(build_file, base_name): + """Determine where to write a Makefile for a given gyp file.""" + # Paths in gyp files are relative to the .gyp file, but we want + # paths relative to the source root for the master makefile. Grab + # the path of the .gyp file as the base to relativize against. + # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp". + base_path = gyp.common.RelativePath(os.path.dirname(build_file), + options.depth) + # We write the file in the base_path directory. + output_file = os.path.join(options.depth, base_path, base_name) + assert not options.generator_output, ( + 'The Android backend does not support options.generator_output.') + base_path = gyp.common.RelativePath(os.path.dirname(build_file), + options.toplevel_dir) + return base_path, output_file + + # TODO: search for the first non-'Default' target. This can go + # away when we add verification that all targets have the + # necessary configurations. + default_configuration = None + toolsets = set([target_dicts[target]['toolset'] for target in target_list]) + for target in target_list: + spec = target_dicts[target] + if spec['default_configuration'] != 'Default': + default_configuration = spec['default_configuration'] + break + if not default_configuration: + default_configuration = 'Default' + + srcdir = '.' + makefile_name = 'GypAndroid' + options.suffix + '.mk' + makefile_path = os.path.join(options.toplevel_dir, makefile_name) + assert not options.generator_output, ( + 'The Android backend does not support options.generator_output.') + gyp.common.EnsureDirExists(makefile_path) + root_makefile = open(makefile_path, 'w') + + root_makefile.write(header) + + # We set LOCAL_PATH just once, here, to the top of the project tree. This + # allows all the other paths we use to be relative to the Android.mk file, + # as the Android build system expects. + root_makefile.write('\nLOCAL_PATH := $(call my-dir)\n') + + # Find the list of targets that derive from the gyp file(s) being built. + needed_targets = set() + for build_file in params['build_files']: + for target in gyp.common.AllTargets(target_list, target_dicts, build_file): + needed_targets.add(target) + + build_files = set() + include_list = set() + android_modules = {} + for qualified_target in target_list: + build_file, target, toolset = gyp.common.ParseQualifiedTarget( + qualified_target) + relative_build_file = gyp.common.RelativePath(build_file, + options.toplevel_dir) + build_files.add(relative_build_file) + included_files = data[build_file]['included_files'] + for included_file in included_files: + # The included_files entries are relative to the dir of the build file + # that included them, so we have to undo that and then make them relative + # to the root dir. + relative_include_file = gyp.common.RelativePath( + gyp.common.UnrelativePath(included_file, build_file), + options.toplevel_dir) + abs_include_file = os.path.abspath(relative_include_file) + # If the include file is from the ~/.gyp dir, we should use absolute path + # so that relocating the src dir doesn't break the path. + if (params['home_dot_gyp'] and + abs_include_file.startswith(params['home_dot_gyp'])): + build_files.add(abs_include_file) + else: + build_files.add(relative_include_file) + + base_path, output_file = CalculateMakefilePath(build_file, + target + '.' + toolset + options.suffix + '.mk') + + spec = target_dicts[qualified_target] + configs = spec['configurations'] + + part_of_all = qualified_target in needed_targets + if limit_to_target_all and not part_of_all: + continue + + relative_target = gyp.common.QualifiedTarget(relative_build_file, target, + toolset) + writer = AndroidMkWriter(android_top_dir) + android_module = writer.Write(qualified_target, relative_target, base_path, + output_file, spec, configs, + part_of_all=part_of_all, + write_alias_target=write_alias_targets, + sdk_version=sdk_version) + if android_module in android_modules: + print ('ERROR: Android module names must be unique. The following ' + 'targets both generate Android module name %s.\n %s\n %s' % + (android_module, android_modules[android_module], + qualified_target)) + return + android_modules[android_module] = qualified_target + + # Our root_makefile lives at the source root. Compute the relative path + # from there to the output_file for including. + mkfile_rel_path = gyp.common.RelativePath(output_file, + os.path.dirname(makefile_path)) + include_list.add(mkfile_rel_path) + + root_makefile.write('GYP_CONFIGURATION ?= %s\n' % default_configuration) + root_makefile.write('GYP_VAR_PREFIX ?=\n') + root_makefile.write('GYP_HOST_VAR_PREFIX ?=\n') + root_makefile.write('GYP_HOST_MULTILIB ?= first\n') + + # Write out the sorted list of includes. + root_makefile.write('\n') + for include_file in sorted(include_list): + root_makefile.write('include $(LOCAL_PATH)/' + include_file + '\n') + root_makefile.write('\n') + + if write_alias_targets: + root_makefile.write(ALL_MODULES_FOOTER) + + root_makefile.close() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py new file mode 100644 index 0000000000000..17f5e6396c630 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py @@ -0,0 +1,1221 @@ +# 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_CURRENT_LIST_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_CURRENT_LIST_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, variable, property_name, values, sep): + """Given a set of source files, sets the given property on them.""" + output.write('set_source_files_properties(') + WriteVariable(output, variable) + output.write(' PROPERTIES ') + output.write(property_name) + output.write(' "') + for value in values: + output.write(CMakeStringEscape(value)) + output.write(sep) + output.write('")\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(object): + 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: [(, )] to append with generated source files. + extra_deps: [] 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_CURRENT_LIST_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: [(, )] to append with generated source files. + extra_deps: [] 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_CURRENT_LIST_DIR is where the CMakeLists.txt lives. + # The cwd is the current build directory. + output.write(' WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_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: [] 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(object): + 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(NormjoinPathForceCMakeSource(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_CURRENT_LIST_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', '') + target_type = spec.get('type', '') + target_toolset = spec.get('toolset') + + 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 + + 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. + # A full separation is done here because of flag handing (see below). + s_sources = [] + c_sources = [] + cxx_sources = [] + linkable_sources = [] + other_sources = [] + for src in srcs: + _, ext = os.path.splitext(src) + src_type = COMPILABLE_EXTENSIONS.get(ext, None) + src_norm_path = NormjoinPath(path_from_cmakelists_to_gyp, src); + + if src_type == 's': + s_sources.append(src_norm_path) + elif src_type == 'cc': + c_sources.append(src_norm_path) + elif src_type == 'cxx': + cxx_sources.append(src_norm_path) + elif Linkable(ext): + linkable_sources.append(src_norm_path) + else: + other_sources.append(src_norm_path) + + 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(src) + elif src_type == 'cc': + c_sources.append(src) + elif src_type == 'cxx': + cxx_sources.append(src) + elif Linkable(ext): + linkable_sources.append(src) + else: + other_sources.append(src) + + s_sources_name = None + if s_sources: + s_sources_name = cmake_target_name + '__asm_srcs' + SetVariableList(output, s_sources_name, s_sources) + + c_sources_name = None + if c_sources: + c_sources_name = cmake_target_name + '__c_srcs' + SetVariableList(output, c_sources_name, c_sources) + + cxx_sources_name = None + if cxx_sources: + cxx_sources_name = cmake_target_name + '__cxx_srcs' + SetVariableList(output, cxx_sources_name, cxx_sources) + + linkable_sources_name = None + if linkable_sources: + linkable_sources_name = cmake_target_name + '__linkable_srcs' + SetVariableList(output, linkable_sources_name, linkable_sources) + + other_sources_name = None + if other_sources: + other_sources_name = cmake_target_name + '__other_srcs' + SetVariableList(output, other_sources_name, other_sources) + + # CMake gets upset when executable targets provide no sources. + # http://www.cmake.org/pipermail/cmake/2010-July/038461.html + dummy_sources_name = None + has_sources = (s_sources_name or + c_sources_name or + cxx_sources_name or + linkable_sources_name or + other_sources_name) + if target_type == 'executable' and not has_sources: + dummy_sources_name = cmake_target_name + '__dummy_srcs' + SetVariable(output, dummy_sources_name, + "${obj}.${TOOLSET}/${TARGET}/genc/dummy.c") + output.write('if(NOT EXISTS "') + WriteVariable(output, dummy_sources_name) + output.write('")\n') + output.write(' file(WRITE "') + WriteVariable(output, dummy_sources_name) + output.write('" "")\n') + output.write("endif()\n") + + + # 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 s_sources_name: + WriteVariable(output, s_sources_name, ' ') + if c_sources_name: + WriteVariable(output, c_sources_name, ' ') + if cxx_sources_name: + WriteVariable(output, cxx_sources_name, ' ') + if linkable_sources_name: + WriteVariable(output, linkable_sources_name, ' ') + if other_sources_name: + WriteVariable(output, other_sources_name, ' ') + if dummy_sources_name: + WriteVariable(output, dummy_sources_name, ' ') + + output.write(')\n') + + # 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) + + # Output name and location. + if target_type != 'none': + # Link as 'C' if there are no other files + if not c_sources and not cxx_sources: + SetTargetProperty(output, cmake_target_name, 'LINKER_LANGUAGE', ['C']) + + # Mark uncompiled sources as uncompiled. + if other_sources_name: + output.write('set_source_files_properties(') + WriteVariable(output, other_sources_name, '') + output.write(' PROPERTIES HEADER_FILE_ONLY "TRUE")\n') + + # Mark object sources as linkable. + if linkable_sources_name: + output.write('set_source_files_properties(') + WriteVariable(output, other_sources_name, '') + output.write(' PROPERTIES EXTERNAL_OBJECT "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 == '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'], '') + + # 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... + cflags = config.get('cflags', []) + cflags_c = config.get('cflags_c', []) + cflags_cxx = config.get('cflags_cc', []) + if (not cflags_c or not c_sources) and (not cflags_cxx or not cxx_sources): + SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', cflags, ' ') + + elif 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: + # TODO: This is broken, one cannot generally set properties on files, + # as other targets may require different properties on the same files. + if s_sources and cflags: + SetFilesProperty(output, s_sources_name, 'COMPILE_FLAGS', cflags, ' ') + + if c_sources and (cflags or cflags_c): + flags = [] + flags.extend(cflags) + flags.extend(cflags_c) + SetFilesProperty(output, c_sources_name, 'COMPILE_FLAGS', flags, ' ') + + if cxx_sources and (cflags or cflags_cxx): + flags = [] + flags.extend(cflags) + flags.extend(cflags_cxx) + SetFilesProperty(output, cxx_sources_name, 'COMPILE_FLAGS', flags, ' ') + + # 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') + + gyp_file, project_target, _ = gyp.common.ParseQualifiedTarget(target_list[-1]) + output.write('project(') + output.write(project_target) + output.write(')\n') + + SetVariable(output, 'configuration', config_to_use) + + ar = None + cc = None + cxx = None + + make_global_settings = data[gyp_file].get('make_global_settings', []) + build_to_top = gyp.common.InvertRelativePath(build_dir, + options.toplevel_dir) + for key, value in make_global_settings: + if key == 'AR': + ar = os.path.join(build_to_top, value) + if key == 'CC': + cc = os.path.join(build_to_top, value) + if key == 'CXX': + cxx = os.path.join(build_to_top, value) + + ar = gyp.common.GetEnvironFallback(['AR_target', 'AR'], ar) + cc = gyp.common.GetEnvironFallback(['CC_target', 'CC'], cc) + cxx = gyp.common.GetEnvironFallback(['CXX_target', 'CXX'], cxx) + + if ar: + SetVariable(output, 'CMAKE_AR', ar) + if cc: + SetVariable(output, 'CMAKE_C_COMPILER', cc) + if cxx: + SetVariable(output, 'CMAKE_CXX_COMPILER', cxx) + + # 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') + + if cc: + SetVariable(output, 'CMAKE_ASM_COMPILER', cc) + + SetVariable(output, 'builddir', '${CMAKE_CURRENT_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') + + # Force ninja to use rsp files. Otherwise link and ar lines can get too long, + # resulting in 'Argument list too long' errors. + output.write('set(CMAKE_NINJA_FORCE_RESPONSE_FILE 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/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py new file mode 100644 index 0000000000000..160eafe2efeca --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py @@ -0,0 +1,99 @@ +# Copyright (c) 2012 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. + +import collections +import os +import gyp +import gyp.common +import gyp.msvs_emulation +import json +import sys + +generator_supports_multiple_toolsets = True + +generator_wants_static_library_dependencies_adjusted = False + +generator_filelist_paths = { +} + +generator_default_variables = { +} +for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR', + 'LIB_DIR', 'SHARED_LIB_DIR']: + # Some gyp steps fail if these are empty(!). + generator_default_variables[dirname] = 'dir' +for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', + 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', + 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX', + 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX', + 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX', + 'CONFIGURATION_NAME']: + generator_default_variables[unused] = '' + + +def CalculateVariables(default_variables, params): + generator_flags = params.get('generator_flags', {}) + for key, val in generator_flags.items(): + default_variables.setdefault(key, val) + default_variables.setdefault('OS', gyp.common.GetFlavor(params)) + + flavor = gyp.common.GetFlavor(params) + if flavor =='win': + # Copy additional generator configuration data from VS, which is shared + # by the Windows Ninja generator. + import gyp.generator.msvs as msvs_generator + generator_additional_non_configuration_keys = getattr(msvs_generator, + 'generator_additional_non_configuration_keys', []) + generator_additional_path_sections = getattr(msvs_generator, + 'generator_additional_path_sections', []) + + gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) + + +def CalculateGeneratorInputInfo(params): + """Calculate the generator specific info that gets fed to input (called by + gyp).""" + generator_flags = params.get('generator_flags', {}) + if generator_flags.get('adjust_static_libraries', False): + global generator_wants_static_library_dependencies_adjusted + generator_wants_static_library_dependencies_adjusted = True + + toplevel = params['options'].toplevel_dir + generator_dir = os.path.relpath(params['options'].generator_output or '.') + # output_dir: relative path from generator_dir to the build directory. + output_dir = generator_flags.get('output_dir', 'out') + qualified_out_dir = os.path.normpath(os.path.join( + toplevel, generator_dir, output_dir, 'gypfiles')) + global generator_filelist_paths + generator_filelist_paths = { + 'toplevel': toplevel, + 'qualified_out_dir': qualified_out_dir, + } + +def GenerateOutput(target_list, target_dicts, data, params): + # Map of target -> list of targets it depends on. + edges = {} + + # Queue of targets to visit. + targets_to_visit = target_list[:] + + while len(targets_to_visit) > 0: + target = targets_to_visit.pop() + if target in edges: + continue + edges[target] = [] + + for dep in target_dicts[target].get('dependencies', []): + edges[target].append(dep) + targets_to_visit.append(dep) + + try: + filepath = params['generator_flags']['output_dir'] + except KeyError: + filepath = '.' + filename = os.path.join(filepath, 'dump.json') + f = open(filename, 'w') + json.dump(edges, f) + f.close() + print 'Wrote json to %s.' % filename diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py new file mode 100644 index 0000000000000..3544347b3bacd --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py @@ -0,0 +1,425 @@ +# Copyright (c) 2012 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. + +"""GYP backend that generates Eclipse CDT settings files. + +This backend DOES NOT generate Eclipse CDT projects. Instead, it generates XML +files that can be imported into an Eclipse CDT project. The XML file contains a +list of include paths and symbols (i.e. defines). + +Because a full .cproject definition is not created by this generator, it's not +possible to properly define the include dirs and symbols for each file +individually. Instead, one set of includes/symbols is generated for the entire +project. This works fairly well (and is a vast improvement in general), but may +still result in a few indexer issues here and there. + +This generator has no automated tests, so expect it to be broken. +""" + +from xml.sax.saxutils import escape +import os.path +import subprocess +import gyp +import gyp.common +import gyp.msvs_emulation +import shlex +import xml.etree.cElementTree as ET + +generator_wants_static_library_dependencies_adjusted = False + +generator_default_variables = { +} + +for dirname in ['INTERMEDIATE_DIR', 'PRODUCT_DIR', 'LIB_DIR', 'SHARED_LIB_DIR']: + # Some gyp steps fail if these are empty(!), so we convert them to variables + generator_default_variables[dirname] = '$' + dirname + +for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', + 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', + 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX', + 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX', + 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX', + 'CONFIGURATION_NAME']: + generator_default_variables[unused] = '' + +# Include dirs will occasionally use the SHARED_INTERMEDIATE_DIR variable as +# part of the path when dealing with generated headers. This value will be +# replaced dynamically for each configuration. +generator_default_variables['SHARED_INTERMEDIATE_DIR'] = \ + '$SHARED_INTERMEDIATE_DIR' + + +def CalculateVariables(default_variables, params): + generator_flags = params.get('generator_flags', {}) + for key, val in generator_flags.items(): + default_variables.setdefault(key, val) + flavor = gyp.common.GetFlavor(params) + default_variables.setdefault('OS', flavor) + if flavor == 'win': + # Copy additional generator configuration data from VS, which is shared + # by the Eclipse generator. + import gyp.generator.msvs as msvs_generator + generator_additional_non_configuration_keys = getattr(msvs_generator, + 'generator_additional_non_configuration_keys', []) + generator_additional_path_sections = getattr(msvs_generator, + 'generator_additional_path_sections', []) + + gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) + + +def CalculateGeneratorInputInfo(params): + """Calculate the generator specific info that gets fed to input (called by + gyp).""" + generator_flags = params.get('generator_flags', {}) + if generator_flags.get('adjust_static_libraries', False): + global generator_wants_static_library_dependencies_adjusted + generator_wants_static_library_dependencies_adjusted = True + + +def GetAllIncludeDirectories(target_list, target_dicts, + shared_intermediate_dirs, config_name, params, + compiler_path): + """Calculate the set of include directories to be used. + + Returns: + A list including all the include_dir's specified for every target followed + by any include directories that were added as cflag compiler options. + """ + + gyp_includes_set = set() + compiler_includes_list = [] + + # Find compiler's default include dirs. + if compiler_path: + command = shlex.split(compiler_path) + command.extend(['-E', '-xc++', '-v', '-']) + proc = subprocess.Popen(args=command, stdin=subprocess.PIPE, + stdout=subprocess.PIPE, stderr=subprocess.PIPE) + output = proc.communicate()[1] + # Extract the list of include dirs from the output, which has this format: + # ... + # #include "..." search starts here: + # #include <...> search starts here: + # /usr/include/c++/4.6 + # /usr/local/include + # End of search list. + # ... + in_include_list = False + for line in output.splitlines(): + if line.startswith('#include'): + in_include_list = True + continue + if line.startswith('End of search list.'): + break + if in_include_list: + include_dir = line.strip() + if include_dir not in compiler_includes_list: + compiler_includes_list.append(include_dir) + + flavor = gyp.common.GetFlavor(params) + if flavor == 'win': + generator_flags = params.get('generator_flags', {}) + for target_name in target_list: + target = target_dicts[target_name] + if config_name in target['configurations']: + config = target['configurations'][config_name] + + # Look for any include dirs that were explicitly added via cflags. This + # may be done in gyp files to force certain includes to come at the end. + # TODO(jgreenwald): Change the gyp files to not abuse cflags for this, and + # remove this. + if flavor == 'win': + msvs_settings = gyp.msvs_emulation.MsvsSettings(target, generator_flags) + cflags = msvs_settings.GetCflags(config_name) + else: + cflags = config['cflags'] + for cflag in cflags: + if cflag.startswith('-I'): + include_dir = cflag[2:] + if include_dir not in compiler_includes_list: + compiler_includes_list.append(include_dir) + + # Find standard gyp include dirs. + if config.has_key('include_dirs'): + include_dirs = config['include_dirs'] + for shared_intermediate_dir in shared_intermediate_dirs: + for include_dir in include_dirs: + include_dir = include_dir.replace('$SHARED_INTERMEDIATE_DIR', + shared_intermediate_dir) + if not os.path.isabs(include_dir): + base_dir = os.path.dirname(target_name) + + include_dir = base_dir + '/' + include_dir + include_dir = os.path.abspath(include_dir) + + gyp_includes_set.add(include_dir) + + # Generate a list that has all the include dirs. + all_includes_list = list(gyp_includes_set) + all_includes_list.sort() + for compiler_include in compiler_includes_list: + if not compiler_include in gyp_includes_set: + all_includes_list.append(compiler_include) + + # All done. + return all_includes_list + + +def GetCompilerPath(target_list, data, options): + """Determine a command that can be used to invoke the compiler. + + Returns: + If this is a gyp project that has explicit make settings, try to determine + the compiler from that. Otherwise, see if a compiler was specified via the + CC_target environment variable. + """ + # First, see if the compiler is configured in make's settings. + build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) + make_global_settings_dict = data[build_file].get('make_global_settings', {}) + for key, value in make_global_settings_dict: + if key in ['CC', 'CXX']: + return os.path.join(options.toplevel_dir, value) + + # Check to see if the compiler was specified as an environment variable. + for key in ['CC_target', 'CC', 'CXX']: + compiler = os.environ.get(key) + if compiler: + return compiler + + return 'gcc' + + +def GetAllDefines(target_list, target_dicts, data, config_name, params, + compiler_path): + """Calculate the defines for a project. + + Returns: + A dict that includes explict defines declared in gyp files along with all of + the default defines that the compiler uses. + """ + + # Get defines declared in the gyp files. + all_defines = {} + flavor = gyp.common.GetFlavor(params) + if flavor == 'win': + generator_flags = params.get('generator_flags', {}) + for target_name in target_list: + target = target_dicts[target_name] + + if flavor == 'win': + msvs_settings = gyp.msvs_emulation.MsvsSettings(target, generator_flags) + extra_defines = msvs_settings.GetComputedDefines(config_name) + else: + extra_defines = [] + if config_name in target['configurations']: + config = target['configurations'][config_name] + target_defines = config['defines'] + else: + target_defines = [] + for define in target_defines + extra_defines: + split_define = define.split('=', 1) + if len(split_define) == 1: + split_define.append('1') + if split_define[0].strip() in all_defines: + # Already defined + continue + all_defines[split_define[0].strip()] = split_define[1].strip() + # Get default compiler defines (if possible). + if flavor == 'win': + return all_defines # Default defines already processed in the loop above. + if compiler_path: + command = shlex.split(compiler_path) + command.extend(['-E', '-dM', '-']) + cpp_proc = subprocess.Popen(args=command, cwd='.', + stdin=subprocess.PIPE, stdout=subprocess.PIPE) + cpp_output = cpp_proc.communicate()[0] + cpp_lines = cpp_output.split('\n') + for cpp_line in cpp_lines: + if not cpp_line.strip(): + continue + cpp_line_parts = cpp_line.split(' ', 2) + key = cpp_line_parts[1] + if len(cpp_line_parts) >= 3: + val = cpp_line_parts[2] + else: + val = '1' + all_defines[key] = val + + return all_defines + + +def WriteIncludePaths(out, eclipse_langs, include_dirs): + """Write the includes section of a CDT settings export file.""" + + out.write('
    \n') + out.write(' \n') + for lang in eclipse_langs: + out.write(' \n' % lang) + for include_dir in include_dirs: + out.write(' %s\n' % + include_dir) + out.write(' \n') + out.write('
    \n') + + +def WriteMacros(out, eclipse_langs, defines): + """Write the macros section of a CDT settings export file.""" + + out.write('
    \n') + out.write(' \n') + for lang in eclipse_langs: + out.write(' \n' % lang) + for key in sorted(defines.iterkeys()): + out.write(' %s%s\n' % + (escape(key), escape(defines[key]))) + out.write(' \n') + out.write('
    \n') + + +def GenerateOutputForConfig(target_list, target_dicts, data, params, + config_name): + options = params['options'] + generator_flags = params.get('generator_flags', {}) + + # build_dir: relative path from source root to our output files. + # e.g. "out/Debug" + build_dir = os.path.join(generator_flags.get('output_dir', 'out'), + config_name) + + toplevel_build = os.path.join(options.toplevel_dir, build_dir) + # Ninja uses out/Debug/gen while make uses out/Debug/obj/gen as the + # SHARED_INTERMEDIATE_DIR. Include both possible locations. + shared_intermediate_dirs = [os.path.join(toplevel_build, 'obj', 'gen'), + os.path.join(toplevel_build, 'gen')] + + GenerateCdtSettingsFile(target_list, + target_dicts, + data, + params, + config_name, + os.path.join(toplevel_build, + 'eclipse-cdt-settings.xml'), + options, + shared_intermediate_dirs) + GenerateClasspathFile(target_list, + target_dicts, + options.toplevel_dir, + toplevel_build, + os.path.join(toplevel_build, + 'eclipse-classpath.xml')) + + +def GenerateCdtSettingsFile(target_list, target_dicts, data, params, + config_name, out_name, options, + shared_intermediate_dirs): + gyp.common.EnsureDirExists(out_name) + with open(out_name, 'w') as out: + out.write('\n') + out.write('\n') + + eclipse_langs = ['C++ Source File', 'C Source File', 'Assembly Source File', + 'GNU C++', 'GNU C', 'Assembly'] + compiler_path = GetCompilerPath(target_list, data, options) + include_dirs = GetAllIncludeDirectories(target_list, target_dicts, + shared_intermediate_dirs, + config_name, params, compiler_path) + WriteIncludePaths(out, eclipse_langs, include_dirs) + defines = GetAllDefines(target_list, target_dicts, data, config_name, + params, compiler_path) + WriteMacros(out, eclipse_langs, defines) + + out.write('\n') + + +def GenerateClasspathFile(target_list, target_dicts, toplevel_dir, + toplevel_build, out_name): + '''Generates a classpath file suitable for symbol navigation and code + completion of Java code (such as in Android projects) by finding all + .java and .jar files used as action inputs.''' + gyp.common.EnsureDirExists(out_name) + result = ET.Element('classpath') + + def AddElements(kind, paths): + # First, we need to normalize the paths so they are all relative to the + # toplevel dir. + rel_paths = set() + for path in paths: + if os.path.isabs(path): + rel_paths.add(os.path.relpath(path, toplevel_dir)) + else: + rel_paths.add(path) + + for path in sorted(rel_paths): + entry_element = ET.SubElement(result, 'classpathentry') + entry_element.set('kind', kind) + entry_element.set('path', path) + + AddElements('lib', GetJavaJars(target_list, target_dicts, toplevel_dir)) + AddElements('src', GetJavaSourceDirs(target_list, target_dicts, toplevel_dir)) + # Include the standard JRE container and a dummy out folder + AddElements('con', ['org.eclipse.jdt.launching.JRE_CONTAINER']) + # Include a dummy out folder so that Eclipse doesn't use the default /bin + # folder in the root of the project. + AddElements('output', [os.path.join(toplevel_build, '.eclipse-java-build')]) + + ET.ElementTree(result).write(out_name) + + +def GetJavaJars(target_list, target_dicts, toplevel_dir): + '''Generates a sequence of all .jars used as inputs.''' + for target_name in target_list: + target = target_dicts[target_name] + for action in target.get('actions', []): + for input_ in action['inputs']: + if os.path.splitext(input_)[1] == '.jar' and not input_.startswith('$'): + if os.path.isabs(input_): + yield input_ + else: + yield os.path.join(os.path.dirname(target_name), input_) + + +def GetJavaSourceDirs(target_list, target_dicts, toplevel_dir): + '''Generates a sequence of all likely java package root directories.''' + for target_name in target_list: + target = target_dicts[target_name] + for action in target.get('actions', []): + for input_ in action['inputs']: + if (os.path.splitext(input_)[1] == '.java' and + not input_.startswith('$')): + dir_ = os.path.dirname(os.path.join(os.path.dirname(target_name), + input_)) + # If there is a parent 'src' or 'java' folder, navigate up to it - + # these are canonical package root names in Chromium. This will + # break if 'src' or 'java' exists in the package structure. This + # could be further improved by inspecting the java file for the + # package name if this proves to be too fragile in practice. + parent_search = dir_ + while os.path.basename(parent_search) not in ['src', 'java']: + parent_search, _ = os.path.split(parent_search) + if not parent_search or parent_search == toplevel_dir: + # Didn't find a known root, just return the original path + yield dir_ + break + else: + yield parent_search + + +def GenerateOutput(target_list, target_dicts, data, params): + """Generate an XML settings file that can be imported into a CDT project.""" + + if params['options'].generator_output: + raise NotImplementedError("--generator_output not implemented for eclipse") + + 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() + for config_name in config_names: + GenerateOutputForConfig(target_list, target_dicts, data, params, + config_name) + diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py new file mode 100644 index 0000000000000..3efdb9966a69a --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py @@ -0,0 +1,94 @@ +# Copyright (c) 2011 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. + +"""gypd output module + +This module produces gyp input as its output. Output files are given the +.gypd extension to avoid overwriting the .gyp files that they are generated +from. Internal references to .gyp files (such as those found in +"dependencies" sections) are not adjusted to point to .gypd files instead; +unlike other paths, which are relative to the .gyp or .gypd file, such paths +are relative to the directory from which gyp was run to create the .gypd file. + +This generator module is intended to be a sample and a debugging aid, hence +the "d" for "debug" in .gypd. It is useful to inspect the results of the +various merges, expansions, and conditional evaluations performed by gyp +and to see a representation of what would be fed to a generator module. + +It's not advisable to rename .gypd files produced by this module to .gyp, +because they will have all merges, expansions, and evaluations already +performed and the relevant constructs not present in the output; paths to +dependencies may be wrong; and various sections that do not belong in .gyp +files such as such as "included_files" and "*_excluded" will be present. +Output will also be stripped of comments. This is not intended to be a +general-purpose gyp pretty-printer; for that, you probably just want to +run "pprint.pprint(eval(open('source.gyp').read()))", which will still strip +comments but won't do all of the other things done to this module's output. + +The specific formatting of the output generated by this module is subject +to change. +""" + + +import gyp.common +import errno +import os +import pprint + + +# These variables should just be spit back out as variable references. +_generator_identity_variables = [ + 'CONFIGURATION_NAME', + 'EXECUTABLE_PREFIX', + 'EXECUTABLE_SUFFIX', + 'INTERMEDIATE_DIR', + 'LIB_DIR', + 'PRODUCT_DIR', + 'RULE_INPUT_ROOT', + 'RULE_INPUT_DIRNAME', + 'RULE_INPUT_EXT', + 'RULE_INPUT_NAME', + 'RULE_INPUT_PATH', + 'SHARED_INTERMEDIATE_DIR', + 'SHARED_LIB_DIR', + 'SHARED_LIB_PREFIX', + 'SHARED_LIB_SUFFIX', + 'STATIC_LIB_PREFIX', + 'STATIC_LIB_SUFFIX', +] + +# gypd doesn't define a default value for OS like many other generator +# modules. Specify "-D OS=whatever" on the command line to provide a value. +generator_default_variables = { +} + +# gypd supports multiple toolsets +generator_supports_multiple_toolsets = True + +# TODO(mark): This always uses <, which isn't right. The input module should +# notify the generator to tell it which phase it is operating in, and this +# module should use < for the early phase and then switch to > for the late +# phase. Bonus points for carrying @ back into the output too. +for v in _generator_identity_variables: + generator_default_variables[v] = '<(%s)' % v + + +def GenerateOutput(target_list, target_dicts, data, params): + output_files = {} + for qualified_target in target_list: + [input_file, target] = \ + gyp.common.ParseQualifiedTarget(qualified_target)[0:2] + + if input_file[-4:] != '.gyp': + continue + input_file_stem = input_file[:-4] + output_file = input_file_stem + params['options'].suffix + '.gypd' + + if not output_file in output_files: + output_files[output_file] = input_file + + for output_file, input_file in output_files.iteritems(): + output = open(output_file, 'w') + pprint.pprint(data[input_file], output) + output.close() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py new file mode 100644 index 0000000000000..bd405f43a993d --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py @@ -0,0 +1,56 @@ +# Copyright (c) 2011 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. + +"""gypsh output module + +gypsh is a GYP shell. It's not really a generator per se. All it does is +fire up an interactive Python session with a few local variables set to the +variables passed to the generator. Like gypd, it's intended as a debugging +aid, to facilitate the exploration of .gyp structures after being processed +by the input module. + +The expected usage is "gyp -f gypsh -D OS=desired_os". +""" + + +import code +import sys + + +# All of this stuff about generator variables was lovingly ripped from gypd.py. +# That module has a much better description of what's going on and why. +_generator_identity_variables = [ + 'EXECUTABLE_PREFIX', + 'EXECUTABLE_SUFFIX', + 'INTERMEDIATE_DIR', + 'PRODUCT_DIR', + 'RULE_INPUT_ROOT', + 'RULE_INPUT_DIRNAME', + 'RULE_INPUT_EXT', + 'RULE_INPUT_NAME', + 'RULE_INPUT_PATH', + 'SHARED_INTERMEDIATE_DIR', +] + +generator_default_variables = { +} + +for v in _generator_identity_variables: + generator_default_variables[v] = '<(%s)' % v + + +def GenerateOutput(target_list, target_dicts, data, params): + locals = { + 'target_list': target_list, + 'target_dicts': target_dicts, + 'data': data, + } + + # Use a banner that looks like the stock Python one and like what + # code.interact uses by default, but tack on something to indicate what + # locals are available, and identify gypsh. + banner='Python %s on %s\nlocals.keys() = %s\ngypsh' % \ + (sys.version, sys.platform, repr(sorted(locals.keys()))) + + code.interact(banner, local=locals) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py new file mode 100644 index 0000000000000..fe801b77ce3b9 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py @@ -0,0 +1,2263 @@ +# 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. + +# Notes: +# +# This is all roughly based on the Makefile system used by the Linux +# kernel, but is a non-recursive make -- we put the entire dependency +# graph in front of make and let it figure it out. +# +# The code below generates a separate .mk file for each target, but +# all are sourced by the top-level Makefile. This means that all +# variables in .mk-files clobber one another. Be careful to use := +# where appropriate for immediate evaluation, and similarly to watch +# that you're not relying on a variable value to last beween different +# .mk files. +# +# TODOs: +# +# Global settings and utility functions are currently stuffed in the +# toplevel Makefile. It may make sense to generate some .mk files on +# the side to keep the files readable. + +import os +import re +import sys +import subprocess +import gyp +import gyp.common +import gyp.xcode_emulation +from gyp.common import GetEnvironFallback +from gyp.common import GypError + +import hashlib + +generator_default_variables = { + 'EXECUTABLE_PREFIX': '', + 'EXECUTABLE_SUFFIX': '', + 'STATIC_LIB_PREFIX': 'lib', + 'SHARED_LIB_PREFIX': 'lib', + 'STATIC_LIB_SUFFIX': '.a', + 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/$(TARGET)/geni', + 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen', + 'PRODUCT_DIR': '$(builddir)', + 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python. + 'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s', # This gets expanded by Python. + 'RULE_INPUT_PATH': '$(abspath $<)', + 'RULE_INPUT_EXT': '$(suffix $<)', + 'RULE_INPUT_NAME': '$(notdir $<)', + 'CONFIGURATION_NAME': '$(BUILDTYPE)', +} + +# Make supports multiple toolsets +generator_supports_multiple_toolsets = True + +# Request sorted dependencies in the order from dependents to dependencies. +generator_wants_sorted_dependencies = False + +# Placates pylint. +generator_additional_non_configuration_keys = [] +generator_additional_path_sections = [] +generator_extra_sources_for_rules = [] +generator_filelist_paths = None + + +def CalculateVariables(default_variables, params): + """Calculate additional variables for use in the build (called by gyp).""" + flavor = gyp.common.GetFlavor(params) + if flavor == 'mac': + default_variables.setdefault('OS', 'mac') + default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib') + default_variables.setdefault('SHARED_LIB_DIR', + generator_default_variables['PRODUCT_DIR']) + default_variables.setdefault('LIB_DIR', + generator_default_variables['PRODUCT_DIR']) + + # Copy additional generator configuration data from Xcode, which is shared + # by the Mac Make generator. + import gyp.generator.xcode as xcode_generator + global generator_additional_non_configuration_keys + generator_additional_non_configuration_keys = getattr(xcode_generator, + 'generator_additional_non_configuration_keys', []) + global generator_additional_path_sections + generator_additional_path_sections = getattr(xcode_generator, + 'generator_additional_path_sections', []) + global generator_extra_sources_for_rules + generator_extra_sources_for_rules = getattr(xcode_generator, + 'generator_extra_sources_for_rules', []) + COMPILABLE_EXTENSIONS.update({'.m': 'objc', '.mm' : 'objcxx'}) + else: + operating_system = flavor + if flavor == 'android': + operating_system = 'linux' # Keep this legacy behavior for now. + default_variables.setdefault('OS', operating_system) + if flavor == 'aix': + default_variables.setdefault('SHARED_LIB_SUFFIX', '.a') + else: + default_variables.setdefault('SHARED_LIB_SUFFIX', '.so') + default_variables.setdefault('SHARED_LIB_DIR','$(builddir)/lib.$(TOOLSET)') + default_variables.setdefault('LIB_DIR', '$(obj).$(TOOLSET)') + + +def CalculateGeneratorInputInfo(params): + """Calculate the generator specific info that gets fed to input (called by + gyp).""" + generator_flags = params.get('generator_flags', {}) + android_ndk_version = generator_flags.get('android_ndk_version', None) + # Android NDK requires a strict link order. + if android_ndk_version: + 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')) + + 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: +# wildcard, sort, foreach, shell, wordlist +# wildcard can handle spaces, the rest can't. +# Since I could find no way to make foreach work with spaces in filenames +# correctly, the .d files have spaces replaced with another character. The .d +# file for +# Chromium\ Framework.framework/foo +# is for example +# out/Release/.deps/out/Release/Chromium?Framework.framework/foo +# This is the replacement character. +SPACE_REPLACEMENT = '?' + + +LINK_COMMANDS_LINUX = """\ +quiet_cmd_alink = AR($(TOOLSET)) $@ +cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) + +quiet_cmd_alink_thin = AR($(TOOLSET)) $@ +cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) + +# Due to circular dependencies between libraries :(, we wrap the +# special "figure out circular dependencies" flags around the entire +# input list during linking. +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) $(LIBS) -Wl,--end-group + +# We support two kinds of shared objects (.so): +# 1) shared_library, which is just bundling together many dependent libraries +# into a link line. +# 2) loadable_module, which is generating a module intended for dlopen(). +# +# They differ only slightly: +# In the former case, we want to package all dependent code into the .so. +# In the latter case, we want to package just the API exposed by the +# outermost module. +# This means shared_library uses --whole-archive, while loadable_module doesn't. +# (Note that --whole-archive is incompatible with the --start-group used in +# normal linking.) + +# Other shared-object link notes: +# - Set SONAME to the library filename so our binaries don't reference +# the local, absolute paths used on the link command-line. +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) +""" + +LINK_COMMANDS_MAC = """\ +quiet_cmd_alink = LIBTOOL-STATIC $@ +cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^) + +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) + +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -bundle $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) +""" + +LINK_COMMANDS_ANDROID = """\ +quiet_cmd_alink = AR($(TOOLSET)) $@ +cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) + +quiet_cmd_alink_thin = AR($(TOOLSET)) $@ +cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) + +# Due to circular dependencies between libraries :(, we wrap the +# special "figure out circular dependencies" flags around the entire +# input list during linking. +quiet_cmd_link = LINK($(TOOLSET)) $@ +quiet_cmd_link_host = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS) +cmd_link_host = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) + +# Other shared-object link notes: +# - Set SONAME to the library filename so our binaries don't reference +# the local, absolute paths used on the link command-line. +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) +quiet_cmd_solink_module_host = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module_host = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) +""" + + +LINK_COMMANDS_AIX = """\ +quiet_cmd_alink = AR($(TOOLSET)) $@ +cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) -X32_64 crs $@ $(filter %.o,$^) + +quiet_cmd_alink_thin = AR($(TOOLSET)) $@ +cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) -X32_64 crs $@ $(filter %.o,$^) + +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) + +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) +""" + + +LINK_COMMANDS_OS390 = """\ +quiet_cmd_alink = AR($(TOOLSET)) $@ +cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) + +quiet_cmd_alink_thin = AR($(TOOLSET)) $@ +cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) + +quiet_cmd_link = LINK($(TOOLSET)) $@ +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) + +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ +cmd_solink = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) -Wl,DLL + +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ +cmd_solink_module = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) -Wl,DLL + +""" + + +# Header of toplevel Makefile. +# This should go into the build tree, but it's easier to keep it here for now. +SHARED_HEADER = ("""\ +# We borrow heavily from the kernel build setup, though we are simpler since +# we don't have Kconfig tweaking settings on us. + +# The implicit make rules have it looking for RCS files, among other things. +# We instead explicitly write all the rules we care about. +# It's even quicker (saves ~200ms) to pass -r on the command line. +MAKEFLAGS=-r + +# The source directory tree. +srcdir := %(srcdir)s +abs_srcdir := $(abspath $(srcdir)) + +# The name of the builddir. +builddir_name ?= %(builddir)s + +# The V=1 flag on command line makes us verbosely print command lines. +ifdef V + quiet= +else + quiet=quiet_ +endif + +# Specify BUILDTYPE=Release on the command line for a release build. +BUILDTYPE ?= %(default_configuration)s + +# Directory all our build output goes into. +# Note that this must be two directories beneath src/ for unit tests to pass, +# as they reach into the src/ directory for data with relative paths. +builddir ?= $(builddir_name)/$(BUILDTYPE) +abs_builddir := $(abspath $(builddir)) +depsdir := $(builddir)/.deps + +# Object output directory. +obj := $(builddir)/obj +abs_obj := $(abspath $(obj)) + +# We build up a list of every single one of the targets so we can slurp in the +# generated dependency rule Makefiles in one pass. +all_deps := + +%(make_global_settings)s + +CC.target ?= %(CC.target)s +CFLAGS.target ?= $(CPPFLAGS) $(CFLAGS) +CXX.target ?= %(CXX.target)s +CXXFLAGS.target ?= $(CPPFLAGS) $(CXXFLAGS) +LINK.target ?= %(LINK.target)s +LDFLAGS.target ?= $(LDFLAGS) +AR.target ?= $(AR) + +# C++ apps need to be linked with g++. +LINK ?= $(CXX.target) + +# TODO(evan): move all cross-compilation logic to gyp-time so we don't need +# to replicate this environment fallback in make as well. +CC.host ?= %(CC.host)s +CFLAGS.host ?= $(CPPFLAGS_host) $(CFLAGS_host) +CXX.host ?= %(CXX.host)s +CXXFLAGS.host ?= $(CPPFLAGS_host) $(CXXFLAGS_host) +LINK.host ?= %(LINK.host)s +LDFLAGS.host ?= +AR.host ?= %(AR.host)s + +# Define a dir function that can handle spaces. +# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions +# "leading spaces cannot appear in the text of the first argument as written. +# These characters can be put into the argument value by variable substitution." +empty := +space := $(empty) $(empty) + +# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces +replace_spaces = $(subst $(space),""" + SPACE_REPLACEMENT + """,$1) +unreplace_spaces = $(subst """ + SPACE_REPLACEMENT + """,$(space),$1) +dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1))) + +# Flags to make gcc output dependency info. Note that you need to be +# careful here to use the flags that ccache and distcc can understand. +# We write to a dep file on the side first and then rename at the end +# so we can't end up with a broken dep file. +depfile = $(depsdir)/$(call replace_spaces,$@).d +DEPFLAGS = %(makedep_args)s -MF $(depfile).raw + +# We have to fixup the deps output in a few ways. +# (1) the file output should mention the proper .o file. +# ccache or distcc lose the path to the target, so we convert a rule of +# the form: +# foobar.o: DEP1 DEP2 +# into +# path/to/foobar.o: DEP1 DEP2 +# (2) we want missing files not to cause us to fail to build. +# We want to rewrite +# foobar.o: DEP1 DEP2 \\ +# DEP3 +# to +# DEP1: +# DEP2: +# DEP3: +# so if the files are missing, they're just considered phony rules. +# We have to do some pretty insane escaping to get those backslashes +# and dollar signs past make, the shell, and sed at the same time. +# Doesn't work with spaces, but that's fine: .d files have spaces in +# their names replaced with other characters.""" +r""" +define fixup_dep +# The depfile may not exist if the input file didn't have any #includes. +touch $(depfile).raw +# Fixup path as in (1). +sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile) +# Add extra rules as in (2). +# We remove slashes and replace spaces with new lines; +# remove blank lines; +# delete the first line and append a colon to the remaining lines. +sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ + grep -v '^$$' |\ + sed -e 1d -e 's|$$|:|' \ + >> $(depfile) +rm $(depfile).raw +endef +""" +""" +# Command definitions: +# - cmd_foo is the actual command to run; +# - quiet_cmd_foo is the brief-output summary of the command. + +quiet_cmd_cc = CC($(TOOLSET)) $@ +cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< + +quiet_cmd_cxx = CXX($(TOOLSET)) $@ +cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< +%(extra_commands)s +quiet_cmd_touch = TOUCH $@ +cmd_touch = touch $@ + +quiet_cmd_copy = COPY $@ +# send stderr to /dev/null to ignore messages when linking directories. +cmd_copy = rm -rf "$@" && cp %(copy_archive_args)s "$<" "$@" + +%(link_commands)s +""" + +r""" +# Define an escape_quotes function to escape single quotes. +# This allows us to handle quotes properly as long as we always use +# use single quotes and escape_quotes. +escape_quotes = $(subst ','\'',$(1)) +# This comment is here just to include a ' to unconfuse syntax highlighting. +# Define an escape_vars function to escape '$' variable syntax. +# This allows us to read/write command lines with shell variables (e.g. +# $LD_LIBRARY_PATH), without triggering make substitution. +escape_vars = $(subst $$,$$$$,$(1)) +# Helper that expands to a shell command to echo a string exactly as it is in +# make. This uses printf instead of echo because printf's behaviour with respect +# to escape sequences is more portable than echo's across different shells +# (e.g., dash, bash). +exact_echo = printf '%%s\n' '$(call escape_quotes,$(1))' +""" +""" +# Helper to compare the command we're about to run against the command +# we logged the last time we ran the command. Produces an empty +# string (false) when the commands match. +# Tricky point: Make has no string-equality test function. +# The kernel uses the following, but it seems like it would have false +# positives, where one string reordered its arguments. +# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \\ +# $(filter-out $(cmd_$@), $(cmd_$(1)))) +# We instead substitute each for the empty string into the other, and +# say they're equal if both substitutions produce the empty string. +# .d files contain """ + SPACE_REPLACEMENT + \ + """ instead of spaces, take that into account. +command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\\ + $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) + +# Helper that is non-empty when a prerequisite changes. +# Normally make does this implicitly, but we force rules to always run +# so we can check their command lines. +# $? -- new prerequisites +# $| -- order-only dependencies +prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) + +# Helper that executes all postbuilds until one fails. +define do_postbuilds + @E=0;\\ + for p in $(POSTBUILDS); do\\ + eval $$p;\\ + E=$$?;\\ + if [ $$E -ne 0 ]; then\\ + break;\\ + fi;\\ + done;\\ + if [ $$E -ne 0 ]; then\\ + rm -rf "$@";\\ + exit $$E;\\ + fi +endef + +# do_cmd: run a command via the above cmd_foo names, if necessary. +# Should always run for a given target to handle command-line changes. +# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. +# Third argument, if non-zero, makes it do POSTBUILDS processing. +# Note: We intentionally do NOT call dirx for depfile, since it contains """ + \ + SPACE_REPLACEMENT + """ for +# spaces already and dirx strips the """ + SPACE_REPLACEMENT + \ + """ characters. +define do_cmd +$(if $(or $(command_changed),$(prereq_changed)), + @$(call exact_echo, $($(quiet)cmd_$(1))) + @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" + $(if $(findstring flock,$(word %(flock_index)d,$(cmd_$1))), + @$(cmd_$(1)) + @echo " $(quiet_cmd_$(1)): Finished", + @$(cmd_$(1)) + ) + @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) + @$(if $(2),$(fixup_dep)) + $(if $(and $(3), $(POSTBUILDS)), + $(call do_postbuilds) + ) +) +endef + +# Declare the "%(default_target)s" target first so it is the default, +# even though we don't have the deps yet. +.PHONY: %(default_target)s +%(default_target)s: + +# make looks for ways to re-generate included makefiles, but in our case, we +# don't have a direct way. Explicitly telling make that it has nothing to do +# for them makes it go faster. +%%.d: ; + +# Use FORCE_DO_CMD to force a target to run. Should be coupled with +# do_cmd. +.PHONY: FORCE_DO_CMD +FORCE_DO_CMD: + +""") + +SHARED_HEADER_MAC_COMMANDS = """ +quiet_cmd_objc = CXX($(TOOLSET)) $@ +cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< + +quiet_cmd_objcxx = CXX($(TOOLSET)) $@ +cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< + +# Commands for precompiled header files. +quiet_cmd_pch_c = CXX($(TOOLSET)) $@ +cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< +quiet_cmd_pch_cc = CXX($(TOOLSET)) $@ +cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< +quiet_cmd_pch_m = CXX($(TOOLSET)) $@ +cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< +quiet_cmd_pch_mm = CXX($(TOOLSET)) $@ +cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< + +# gyp-mac-tool is written next to the root Makefile by gyp. +# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd +# already. +quiet_cmd_mac_tool = MACTOOL $(4) $< +cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@" + +quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ +cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4) + +quiet_cmd_infoplist = INFOPLIST $@ +cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@" +""" + + +def WriteRootHeaderSuffixRules(writer): + extensions = sorted(COMPILABLE_EXTENSIONS.keys(), key=str.lower) + + writer.write('# Suffix rules, putting all outputs into $(obj).\n') + for ext in extensions: + writer.write('$(obj).$(TOOLSET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD\n' % ext) + writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext]) + + writer.write('\n# Try building from generated source, too.\n') + for ext in extensions: + writer.write( + '$(obj).$(TOOLSET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD\n' % ext) + writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext]) + writer.write('\n') + for ext in extensions: + writer.write('$(obj).$(TOOLSET)/%%.o: $(obj)/%%%s FORCE_DO_CMD\n' % ext) + writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext]) + writer.write('\n') + + +SHARED_HEADER_SUFFIX_RULES_COMMENT1 = ("""\ +# Suffix rules, putting all outputs into $(obj). +""") + + +SHARED_HEADER_SUFFIX_RULES_COMMENT2 = ("""\ +# Try building from generated source, too. +""") + + +SHARED_FOOTER = """\ +# "all" is a concatenation of the "all" targets from all the included +# sub-makefiles. This is just here to clarify. +all: + +# Add in dependency-tracking rules. $(all_deps) is the list of every single +# target in our tree. Only consider the ones with .d (dependency) info: +d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) +ifneq ($(d_files),) + include $(d_files) +endif +""" + +header = """\ +# This file is generated by gyp; do not edit. + +""" + +# Maps every compilable file extension to the do_cmd that compiles it. +COMPILABLE_EXTENSIONS = { + '.c': 'cc', + '.cc': 'cxx', + '.cpp': 'cxx', + '.cxx': 'cxx', + '.s': 'cc', + '.S': 'cc', +} + +def Compilable(filename): + """Return true if the file is compilable (should be in OBJS).""" + for res in (filename.endswith(e) for e in COMPILABLE_EXTENSIONS): + if res: + return True + return False + + +def Linkable(filename): + """Return true if the file is linkable (should be on the link line).""" + return filename.endswith('.o') + + +def Target(filename): + """Translate a compilable filename to its .o target.""" + return os.path.splitext(filename)[0] + '.o' + + +def EscapeShellArgument(s): + """Quotes an argument so that it will be interpreted literally by a POSIX + shell. Taken from + http://stackoverflow.com/questions/35817/whats-the-best-way-to-escape-ossystem-calls-in-python + """ + return "'" + s.replace("'", "'\\''") + "'" + + +def EscapeMakeVariableExpansion(s): + """Make has its own variable expansion syntax using $. We must escape it for + string to be interpreted literally.""" + return s.replace('$', '$$') + + +def EscapeCppDefine(s): + """Escapes a CPP define so that it will reach the compiler unaltered.""" + s = EscapeShellArgument(s) + s = EscapeMakeVariableExpansion(s) + # '#' characters must be escaped even embedded in a string, else Make will + # treat it as the start of a comment. + return s.replace('#', r'\#') + + +def QuoteIfNecessary(string): + """TODO: Should this ideally be replaced with one or more of the above + functions?""" + if '"' in string: + string = '"' + string.replace('"', '\\"') + '"' + return string + + +def StringToMakefileVariable(string): + """Convert a string to a value that is acceptable as a make variable name.""" + return re.sub('[^a-zA-Z0-9_]', '_', string) + + +srcdir_prefix = '' +def Sourceify(path): + """Convert a path to its source directory form.""" + if '$(' in path: + return path + if os.path.isabs(path): + return path + return srcdir_prefix + path + + +def QuoteSpaces(s, quote=r'\ '): + return s.replace(' ', quote) + +def SourceifyAndQuoteSpaces(path): + """Convert a path to its source directory form and quote spaces.""" + return QuoteSpaces(Sourceify(path)) + +# TODO: Avoid code duplication with _ValidateSourcesForMSVSProject in msvs.py. +def _ValidateSourcesForOSX(spec, all_sources): + """Makes sure if duplicate basenames are not specified in the source list. + + Arguments: + spec: The target dictionary containing the properties of the target. + """ + if spec.get('type', None) != 'static_library': + return + + basenames = {} + for source in all_sources: + name, ext = os.path.splitext(source) + is_compiled_file = ext in [ + '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S'] + if not is_compiled_file: + continue + basename = os.path.basename(name) # Don't include extension. + basenames.setdefault(basename, []).append(source) + + error = '' + for basename, files in basenames.iteritems(): + if len(files) > 1: + error += ' %s: %s\n' % (basename, ' '.join(files)) + + if error: + print('static library %s has several files with the same basename:\n' % + spec['target_name'] + error + 'libtool on OS X will generate' + + ' warnings for them.') + raise GypError('Duplicate basenames in sources section, see list above') + + +# Map from qualified target to path to output. +target_outputs = {} +# Map from qualified target to any linkable output. A subset +# of target_outputs. E.g. when mybinary depends on liba, we want to +# include liba in the linker line; when otherbinary depends on +# mybinary, we just want to build mybinary first. +target_link_deps = {} + + +class MakefileWriter(object): + """MakefileWriter packages up the writing of one target-specific foobar.mk. + + Its only real entry point is Write(), and is mostly used for namespacing. + """ + + def __init__(self, generator_flags, flavor): + self.generator_flags = generator_flags + self.flavor = flavor + + self.suffix_rules_srcdir = {} + self.suffix_rules_objdir1 = {} + self.suffix_rules_objdir2 = {} + + # Generate suffix rules for all compilable extensions. + for ext in COMPILABLE_EXTENSIONS.keys(): + # Suffix rules for source folder. + self.suffix_rules_srcdir.update({ext: ("""\ +$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD + @$(call do_cmd,%s,1) +""" % (ext, COMPILABLE_EXTENSIONS[ext]))}) + + # Suffix rules for generated source files. + self.suffix_rules_objdir1.update({ext: ("""\ +$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD + @$(call do_cmd,%s,1) +""" % (ext, COMPILABLE_EXTENSIONS[ext]))}) + self.suffix_rules_objdir2.update({ext: ("""\ +$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD + @$(call do_cmd,%s,1) +""" % (ext, COMPILABLE_EXTENSIONS[ext]))}) + + + def Write(self, qualified_target, base_path, output_filename, spec, configs, + part_of_all): + """The main entry point: writes a .mk file for a single target. + + Arguments: + qualified_target: target we're generating + base_path: path relative to source root we're building in, used to resolve + target-relative paths + output_filename: output .mk file name to write + spec, configs: gyp info + part_of_all: flag indicating this target is part of 'all' + """ + gyp.common.EnsureDirExists(output_filename) + + self.fp = open(output_filename, 'w') + + self.fp.write(header) + + self.qualified_target = qualified_target + self.path = base_path + self.target = spec['target_name'] + self.type = spec['type'] + self.toolset = spec['toolset'] + + self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec) + if self.flavor == 'mac': + self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec) + else: + self.xcode_settings = None + + deps, link_deps = self.ComputeDeps(spec) + + # Some of the generation below can add extra output, sources, or + # link dependencies. All of the out params of the functions that + # follow use names like extra_foo. + extra_outputs = [] + extra_sources = [] + extra_link_deps = [] + extra_mac_bundle_resources = [] + mac_bundle_deps = [] + + if self.is_mac_bundle: + self.output = self.ComputeMacBundleOutput(spec) + self.output_binary = self.ComputeMacBundleBinaryOutput(spec) + else: + self.output = self.output_binary = self.ComputeOutput(spec) + + self.is_standalone_static_library = bool( + spec.get('standalone_static_library', 0)) + self._INSTALLABLE_TARGETS = ('executable', 'loadable_module', + 'shared_library') + if (self.is_standalone_static_library or + self.type in self._INSTALLABLE_TARGETS): + self.alias = os.path.basename(self.output) + install_path = self._InstallableTargetInstallPath() + else: + self.alias = self.output + install_path = self.output + + self.WriteLn("TOOLSET := " + self.toolset) + self.WriteLn("TARGET := " + self.target) + + # Actions must come first, since they can generate more OBJs for use below. + if 'actions' in spec: + self.WriteActions(spec['actions'], extra_sources, extra_outputs, + extra_mac_bundle_resources, part_of_all) + + # Rules must be early like actions. + if 'rules' in spec: + self.WriteRules(spec['rules'], extra_sources, extra_outputs, + extra_mac_bundle_resources, part_of_all) + + if 'copies' in spec: + self.WriteCopies(spec['copies'], extra_outputs, part_of_all) + + # Bundle resources. + if self.is_mac_bundle: + all_mac_bundle_resources = ( + spec.get('mac_bundle_resources', []) + extra_mac_bundle_resources) + self.WriteMacBundleResources(all_mac_bundle_resources, mac_bundle_deps) + self.WriteMacInfoPlist(mac_bundle_deps) + + # Sources. + all_sources = spec.get('sources', []) + extra_sources + if all_sources: + if self.flavor == 'mac': + # libtool on OS X generates warnings for duplicate basenames in the same + # target. + _ValidateSourcesForOSX(spec, all_sources) + self.WriteSources( + configs, deps, all_sources, extra_outputs, + extra_link_deps, part_of_all, + gyp.xcode_emulation.MacPrefixHeader( + self.xcode_settings, lambda p: Sourceify(self.Absolutify(p)), + self.Pchify)) + sources = filter(Compilable, all_sources) + if sources: + self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT1) + extensions = set([os.path.splitext(s)[1] for s in sources]) + for ext in extensions: + if ext in self.suffix_rules_srcdir: + self.WriteLn(self.suffix_rules_srcdir[ext]) + self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT2) + for ext in extensions: + if ext in self.suffix_rules_objdir1: + self.WriteLn(self.suffix_rules_objdir1[ext]) + for ext in extensions: + if ext in self.suffix_rules_objdir2: + self.WriteLn(self.suffix_rules_objdir2[ext]) + self.WriteLn('# End of this set of suffix rules') + + # Add dependency from bundle to bundle binary. + if self.is_mac_bundle: + mac_bundle_deps.append(self.output_binary) + + self.WriteTarget(spec, configs, deps, extra_link_deps + link_deps, + mac_bundle_deps, extra_outputs, part_of_all) + + # Update global list of target outputs, used in dependency tracking. + target_outputs[qualified_target] = install_path + + # Update global list of link dependencies. + if self.type in ('static_library', 'shared_library'): + target_link_deps[qualified_target] = self.output_binary + + # Currently any versions have the same effect, but in future the behavior + # could be different. + if self.generator_flags.get('android_ndk_version', None): + self.WriteAndroidNdkModuleRule(self.target, all_sources, link_deps) + + self.fp.close() + + + def WriteSubMake(self, output_filename, makefile_path, targets, build_dir): + """Write a "sub-project" Makefile. + + This is a small, wrapper Makefile that calls the top-level Makefile to build + the targets from a single gyp file (i.e. a sub-project). + + Arguments: + output_filename: sub-project Makefile name to write + makefile_path: path to the top-level Makefile + targets: list of "all" targets for this sub-project + build_dir: build output directory, relative to the sub-project + """ + 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 + # sub-project dir (see test/subdirectory/gyptest-subdir-all.py). + self.WriteLn('export builddir_name ?= %s' % + os.path.join(os.path.dirname(output_filename), build_dir)) + self.WriteLn('.PHONY: all') + self.WriteLn('all:') + if makefile_path: + makefile_path = ' -C ' + makefile_path + self.WriteLn('\t$(MAKE)%s %s' % (makefile_path, ' '.join(targets))) + self.fp.close() + + + def WriteActions(self, actions, extra_sources, extra_outputs, + extra_mac_bundle_resources, part_of_all): + """Write Makefile code for any 'actions' from the gyp input. + + extra_sources: a list that will be filled in with newly generated source + files, if any + extra_outputs: a list that will be filled in with any outputs of these + actions (used to make other pieces dependent on these + actions) + part_of_all: flag indicating this target is part of 'all' + """ + env = self.GetSortedXcodeEnv() + for action in actions: + name = StringToMakefileVariable('%s_%s' % (self.qualified_target, + action['action_name'])) + self.WriteLn('### Rules for action "%s":' % action['action_name']) + inputs = action['inputs'] + outputs = action['outputs'] + + # Build up a list of outputs. + # Collect the output dirs we'll need. + dirs = set() + for out in outputs: + dir = os.path.split(out)[0] + if dir: + dirs.add(dir) + if int(action.get('process_outputs_as_sources', False)): + extra_sources += outputs + if int(action.get('process_outputs_as_mac_bundle_resources', False)): + extra_mac_bundle_resources += outputs + + # Write the actual command. + action_commands = action['action'] + if self.flavor == 'mac': + action_commands = [gyp.xcode_emulation.ExpandEnvVars(command, env) + for command in action_commands] + command = gyp.common.EncodePOSIXShellList(action_commands) + if 'message' in action: + self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, action['message'])) + else: + self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, name)) + if len(dirs) > 0: + command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command + + cd_action = 'cd %s; ' % Sourceify(self.path or '.') + + # command and cd_action get written to a toplevel variable called + # cmd_foo. Toplevel variables can't handle things that change per + # makefile like $(TARGET), so hardcode the target. + command = command.replace('$(TARGET)', self.target) + cd_action = cd_action.replace('$(TARGET)', self.target) + + # Set LD_LIBRARY_PATH in case the action runs an executable from this + # build which links to shared libs from this build. + # actions run on the host, so they should in theory only use host + # libraries, but until everything is made cross-compile safe, also use + # target libraries. + # TODO(piman): when everything is cross-compile safe, remove lib.target + self.WriteLn('cmd_%s = LD_LIBRARY_PATH=$(builddir)/lib.host:' + '$(builddir)/lib.target:$$LD_LIBRARY_PATH; ' + 'export LD_LIBRARY_PATH; ' + '%s%s' + % (name, cd_action, command)) + self.WriteLn() + outputs = map(self.Absolutify, outputs) + # The makefile rules are all relative to the top dir, but the gyp actions + # are defined relative to their containing dir. This replaces the obj + # variable for the action rule with an absolute version so that the output + # goes in the right place. + # Only write the 'obj' and 'builddir' rules for the "primary" output (:1); + # it's superfluous for the "extra outputs", and this avoids accidentally + # writing duplicate dummy rules for those outputs. + # Same for environment. + self.WriteLn("%s: obj := $(abs_obj)" % QuoteSpaces(outputs[0])) + self.WriteLn("%s: builddir := $(abs_builddir)" % QuoteSpaces(outputs[0])) + self.WriteSortedXcodeEnv(outputs[0], self.GetSortedXcodeEnv()) + + for input in inputs: + assert ' ' not in input, ( + "Spaces in action input filenames not supported (%s)" % input) + for output in outputs: + assert ' ' not in output, ( + "Spaces in action output filenames not supported (%s)" % output) + + # See the comment in WriteCopies about expanding env vars. + outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs] + inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs] + + self.WriteDoCmd(outputs, map(Sourceify, map(self.Absolutify, inputs)), + part_of_all=part_of_all, command=name) + + # Stuff the outputs in a variable so we can refer to them later. + outputs_variable = 'action_%s_outputs' % name + self.WriteLn('%s := %s' % (outputs_variable, ' '.join(outputs))) + extra_outputs.append('$(%s)' % outputs_variable) + self.WriteLn() + + self.WriteLn() + + + def WriteRules(self, rules, extra_sources, extra_outputs, + extra_mac_bundle_resources, part_of_all): + """Write Makefile code for any 'rules' from the gyp input. + + extra_sources: a list that will be filled in with newly generated source + files, if any + extra_outputs: a list that will be filled in with any outputs of these + rules (used to make other pieces dependent on these rules) + part_of_all: flag indicating this target is part of 'all' + """ + env = self.GetSortedXcodeEnv() + for rule in rules: + name = StringToMakefileVariable('%s_%s' % (self.qualified_target, + rule['rule_name'])) + count = 0 + self.WriteLn('### Generated for rule %s:' % name) + + all_outputs = [] + + for rule_source in rule.get('rule_sources', []): + dirs = set() + (rule_source_dirname, rule_source_basename) = os.path.split(rule_source) + (rule_source_root, rule_source_ext) = \ + os.path.splitext(rule_source_basename) + + outputs = [self.ExpandInputRoot(out, rule_source_root, + rule_source_dirname) + for out in rule['outputs']] + + for out in outputs: + dir = os.path.dirname(out) + if dir: + dirs.add(dir) + if int(rule.get('process_outputs_as_sources', False)): + extra_sources += outputs + if int(rule.get('process_outputs_as_mac_bundle_resources', False)): + extra_mac_bundle_resources += outputs + inputs = map(Sourceify, map(self.Absolutify, [rule_source] + + rule.get('inputs', []))) + actions = ['$(call do_cmd,%s_%d)' % (name, count)] + + if name == 'resources_grit': + # HACK: This is ugly. Grit intentionally doesn't touch the + # timestamp of its output file when the file doesn't change, + # which is fine in hash-based dependency systems like scons + # and forge, but not kosher in the make world. After some + # discussion, hacking around it here seems like the least + # amount of pain. + actions += ['@touch --no-create $@'] + + # See the comment in WriteCopies about expanding env vars. + outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs] + inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs] + + outputs = map(self.Absolutify, outputs) + all_outputs += outputs + # Only write the 'obj' and 'builddir' rules for the "primary" output + # (:1); it's superfluous for the "extra outputs", and this avoids + # accidentally writing duplicate dummy rules for those outputs. + self.WriteLn('%s: obj := $(abs_obj)' % outputs[0]) + self.WriteLn('%s: builddir := $(abs_builddir)' % outputs[0]) + self.WriteMakeRule(outputs, inputs, actions, + command="%s_%d" % (name, count)) + # Spaces in rule filenames are not supported, but rule variables have + # spaces in them (e.g. RULE_INPUT_PATH expands to '$(abspath $<)'). + # The spaces within the variables are valid, so remove the variables + # before checking. + variables_with_spaces = re.compile(r'\$\([^ ]* \$<\)') + for output in outputs: + output = re.sub(variables_with_spaces, '', output) + assert ' ' not in output, ( + "Spaces in rule filenames not yet supported (%s)" % output) + self.WriteLn('all_deps += %s' % ' '.join(outputs)) + + action = [self.ExpandInputRoot(ac, rule_source_root, + rule_source_dirname) + for ac in rule['action']] + mkdirs = '' + if len(dirs) > 0: + mkdirs = 'mkdir -p %s; ' % ' '.join(dirs) + cd_action = 'cd %s; ' % Sourceify(self.path or '.') + + # action, cd_action, and mkdirs get written to a toplevel variable + # called cmd_foo. Toplevel variables can't handle things that change + # per makefile like $(TARGET), so hardcode the target. + if self.flavor == 'mac': + action = [gyp.xcode_emulation.ExpandEnvVars(command, env) + for command in action] + action = gyp.common.EncodePOSIXShellList(action) + action = action.replace('$(TARGET)', self.target) + cd_action = cd_action.replace('$(TARGET)', self.target) + mkdirs = mkdirs.replace('$(TARGET)', self.target) + + # Set LD_LIBRARY_PATH in case the rule runs an executable from this + # build which links to shared libs from this build. + # rules run on the host, so they should in theory only use host + # libraries, but until everything is made cross-compile safe, also use + # target libraries. + # TODO(piman): when everything is cross-compile safe, remove lib.target + self.WriteLn( + "cmd_%(name)s_%(count)d = LD_LIBRARY_PATH=" + "$(builddir)/lib.host:$(builddir)/lib.target:$$LD_LIBRARY_PATH; " + "export LD_LIBRARY_PATH; " + "%(cd_action)s%(mkdirs)s%(action)s" % { + 'action': action, + 'cd_action': cd_action, + 'count': count, + 'mkdirs': mkdirs, + 'name': name, + }) + self.WriteLn( + 'quiet_cmd_%(name)s_%(count)d = RULE %(name)s_%(count)d $@' % { + 'count': count, + 'name': name, + }) + self.WriteLn() + count += 1 + + outputs_variable = 'rule_%s_outputs' % name + self.WriteList(all_outputs, outputs_variable) + extra_outputs.append('$(%s)' % outputs_variable) + + self.WriteLn('### Finished generating for rule: %s' % name) + self.WriteLn() + self.WriteLn('### Finished generating for all rules') + self.WriteLn('') + + + def WriteCopies(self, copies, extra_outputs, part_of_all): + """Write Makefile code for any 'copies' from the gyp input. + + extra_outputs: a list that will be filled in with any outputs of this action + (used to make other pieces dependent on this action) + part_of_all: flag indicating this target is part of 'all' + """ + self.WriteLn('### Generated for copy rule.') + + variable = StringToMakefileVariable(self.qualified_target + '_copies') + outputs = [] + for copy in copies: + for path in copy['files']: + # Absolutify() may call normpath, and will strip trailing slashes. + path = Sourceify(self.Absolutify(path)) + filename = os.path.split(path)[1] + output = Sourceify(self.Absolutify(os.path.join(copy['destination'], + filename))) + + # If the output path has variables in it, which happens in practice for + # 'copies', writing the environment as target-local doesn't work, + # because the variables are already needed for the target name. + # Copying the environment variables into global make variables doesn't + # work either, because then the .d files will potentially contain spaces + # after variable expansion, and .d file handling cannot handle spaces. + # As a workaround, manually expand variables at gyp time. Since 'copies' + # can't run scripts, there's no need to write the env then. + # WriteDoCmd() will escape spaces for .d files. + env = self.GetSortedXcodeEnv() + output = gyp.xcode_emulation.ExpandEnvVars(output, env) + path = gyp.xcode_emulation.ExpandEnvVars(path, env) + self.WriteDoCmd([output], [path], 'copy', part_of_all) + outputs.append(output) + self.WriteLn('%s = %s' % (variable, ' '.join(map(QuoteSpaces, outputs)))) + extra_outputs.append('$(%s)' % variable) + self.WriteLn() + + + def WriteMacBundleResources(self, resources, bundle_deps): + """Writes Makefile code for 'mac_bundle_resources'.""" + self.WriteLn('### Generated for mac_bundle_resources') + + for output, res in gyp.xcode_emulation.GetMacBundleResources( + generator_default_variables['PRODUCT_DIR'], self.xcode_settings, + map(Sourceify, map(self.Absolutify, resources))): + _, ext = os.path.splitext(output) + if ext != '.xcassets': + # Make does not supports '.xcassets' emulation. + self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource', + part_of_all=True) + bundle_deps.append(output) + + + def WriteMacInfoPlist(self, bundle_deps): + """Write Makefile code for bundle Info.plist files.""" + info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist( + generator_default_variables['PRODUCT_DIR'], self.xcode_settings, + lambda p: Sourceify(self.Absolutify(p))) + if not info_plist: + return + if defines: + # Create an intermediate file to store preprocessed results. + intermediate_plist = ('$(obj).$(TOOLSET)/$(TARGET)/' + + os.path.basename(info_plist)) + self.WriteList(defines, intermediate_plist + ': INFOPLIST_DEFINES', '-D', + quoter=EscapeCppDefine) + self.WriteMakeRule([intermediate_plist], [info_plist], + ['$(call do_cmd,infoplist)', + # "Convert" the plist so that any weird whitespace changes from the + # preprocessor do not affect the XML parser in mac_tool. + '@plutil -convert xml1 $@ $@']) + info_plist = intermediate_plist + # plists can contain envvars and substitute them into the file. + self.WriteSortedXcodeEnv( + out, self.GetSortedXcodeEnv(additional_settings=extra_env)) + self.WriteDoCmd([out], [info_plist], 'mac_tool,,,copy-info-plist', + part_of_all=True) + bundle_deps.append(out) + + + def WriteSources(self, configs, deps, sources, + extra_outputs, extra_link_deps, + part_of_all, precompiled_header): + """Write Makefile code for any 'sources' from the gyp input. + These are source files necessary to build the current target. + + configs, deps, sources: input from gyp. + extra_outputs: a list of extra outputs this action should be dependent on; + used to serialize action/rules before compilation + extra_link_deps: a list that will be filled in with any outputs of + compilation (to be used in link lines) + part_of_all: flag indicating this target is part of 'all' + """ + + # Write configuration-specific variables for CFLAGS, etc. + for configname in sorted(configs.keys()): + config = configs[configname] + self.WriteList(config.get('defines'), 'DEFS_%s' % configname, prefix='-D', + quoter=EscapeCppDefine) + + if self.flavor == 'mac': + cflags = self.xcode_settings.GetCflags(configname) + cflags_c = self.xcode_settings.GetCflagsC(configname) + cflags_cc = self.xcode_settings.GetCflagsCC(configname) + cflags_objc = self.xcode_settings.GetCflagsObjC(configname) + cflags_objcc = self.xcode_settings.GetCflagsObjCC(configname) + else: + cflags = config.get('cflags') + cflags_c = config.get('cflags_c') + cflags_cc = config.get('cflags_cc') + + self.WriteLn("# Flags passed to all source files."); + self.WriteList(cflags, 'CFLAGS_%s' % configname) + self.WriteLn("# Flags passed to only C files."); + self.WriteList(cflags_c, 'CFLAGS_C_%s' % configname) + self.WriteLn("# Flags passed to only C++ files."); + self.WriteList(cflags_cc, 'CFLAGS_CC_%s' % configname) + if self.flavor == 'mac': + self.WriteLn("# Flags passed to only ObjC files."); + self.WriteList(cflags_objc, 'CFLAGS_OBJC_%s' % configname) + self.WriteLn("# Flags passed to only ObjC++ files."); + self.WriteList(cflags_objcc, 'CFLAGS_OBJCC_%s' % configname) + includes = config.get('include_dirs') + if includes: + includes = map(Sourceify, map(self.Absolutify, includes)) + self.WriteList(includes, 'INCS_%s' % configname, prefix='-I') + + compilable = filter(Compilable, sources) + objs = map(self.Objectify, map(self.Absolutify, map(Target, compilable))) + self.WriteList(objs, 'OBJS') + + for obj in objs: + assert ' ' not in obj, ( + "Spaces in object filenames not supported (%s)" % obj) + self.WriteLn('# Add to the list of files we specially track ' + 'dependencies for.') + self.WriteLn('all_deps += $(OBJS)') + self.WriteLn() + + # Make sure our dependencies are built first. + if deps: + self.WriteMakeRule(['$(OBJS)'], deps, + comment = 'Make sure our dependencies are built ' + 'before any of us.', + order_only = True) + + # Make sure the actions and rules run first. + # If they generate any extra headers etc., the per-.o file dep tracking + # will catch the proper rebuilds, so order only is still ok here. + if extra_outputs: + self.WriteMakeRule(['$(OBJS)'], extra_outputs, + comment = 'Make sure our actions/rules run ' + 'before any of us.', + order_only = True) + + pchdeps = precompiled_header.GetObjDependencies(compilable, objs ) + if pchdeps: + self.WriteLn('# Dependencies from obj files to their precompiled headers') + for source, obj, gch in pchdeps: + self.WriteLn('%s: %s' % (obj, gch)) + self.WriteLn('# End precompiled header dependencies') + + if objs: + extra_link_deps.append('$(OBJS)') + self.WriteLn("""\ +# CFLAGS et al overrides must be target-local. +# See "Target-specific Variable Values" in the GNU Make manual.""") + self.WriteLn("$(OBJS): TOOLSET := $(TOOLSET)") + self.WriteLn("$(OBJS): GYP_CFLAGS := " + "$(DEFS_$(BUILDTYPE)) " + "$(INCS_$(BUILDTYPE)) " + "%s " % precompiled_header.GetInclude('c') + + "$(CFLAGS_$(BUILDTYPE)) " + "$(CFLAGS_C_$(BUILDTYPE))") + self.WriteLn("$(OBJS): GYP_CXXFLAGS := " + "$(DEFS_$(BUILDTYPE)) " + "$(INCS_$(BUILDTYPE)) " + "%s " % precompiled_header.GetInclude('cc') + + "$(CFLAGS_$(BUILDTYPE)) " + "$(CFLAGS_CC_$(BUILDTYPE))") + if self.flavor == 'mac': + self.WriteLn("$(OBJS): GYP_OBJCFLAGS := " + "$(DEFS_$(BUILDTYPE)) " + "$(INCS_$(BUILDTYPE)) " + "%s " % precompiled_header.GetInclude('m') + + "$(CFLAGS_$(BUILDTYPE)) " + "$(CFLAGS_C_$(BUILDTYPE)) " + "$(CFLAGS_OBJC_$(BUILDTYPE))") + self.WriteLn("$(OBJS): GYP_OBJCXXFLAGS := " + "$(DEFS_$(BUILDTYPE)) " + "$(INCS_$(BUILDTYPE)) " + "%s " % precompiled_header.GetInclude('mm') + + "$(CFLAGS_$(BUILDTYPE)) " + "$(CFLAGS_CC_$(BUILDTYPE)) " + "$(CFLAGS_OBJCC_$(BUILDTYPE))") + + self.WritePchTargets(precompiled_header.GetPchBuildCommands()) + + # If there are any object files in our input file list, link them into our + # output. + extra_link_deps += filter(Linkable, sources) + + self.WriteLn() + + def WritePchTargets(self, pch_commands): + """Writes make rules to compile prefix headers.""" + if not pch_commands: + return + + for gch, lang_flag, lang, input in pch_commands: + extra_flags = { + 'c': '$(CFLAGS_C_$(BUILDTYPE))', + 'cc': '$(CFLAGS_CC_$(BUILDTYPE))', + 'm': '$(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))', + 'mm': '$(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))', + }[lang] + var_name = { + 'c': 'GYP_PCH_CFLAGS', + 'cc': 'GYP_PCH_CXXFLAGS', + 'm': 'GYP_PCH_OBJCFLAGS', + 'mm': 'GYP_PCH_OBJCXXFLAGS', + }[lang] + self.WriteLn("%s: %s := %s " % (gch, var_name, lang_flag) + + "$(DEFS_$(BUILDTYPE)) " + "$(INCS_$(BUILDTYPE)) " + "$(CFLAGS_$(BUILDTYPE)) " + + extra_flags) + + self.WriteLn('%s: %s FORCE_DO_CMD' % (gch, input)) + self.WriteLn('\t@$(call do_cmd,pch_%s,1)' % lang) + self.WriteLn('') + assert ' ' not in gch, ( + "Spaces in gch filenames not supported (%s)" % gch) + self.WriteLn('all_deps += %s' % gch) + self.WriteLn('') + + + def ComputeOutputBasename(self, spec): + """Return the 'output basename' of a gyp spec. + + E.g., the loadable module 'foobar' in directory 'baz' will produce + 'libfoobar.so' + """ + assert not self.is_mac_bundle + + if self.flavor == 'mac' and self.type in ( + 'static_library', 'executable', 'shared_library', 'loadable_module'): + return self.xcode_settings.GetExecutablePath() + + target = spec['target_name'] + target_prefix = '' + target_ext = '' + if self.type == 'static_library': + if target[:3] == 'lib': + target = target[3:] + target_prefix = 'lib' + target_ext = '.a' + elif self.type in ('loadable_module', 'shared_library'): + if target[:3] == 'lib': + target = target[3:] + target_prefix = 'lib' + if self.flavor == 'aix': + target_ext = '.a' + else: + target_ext = '.so' + elif self.type == 'none': + target = '%s.stamp' % target + elif self.type != 'executable': + print ("ERROR: What output file should be generated?", + "type", self.type, "target", target) + + target_prefix = spec.get('product_prefix', target_prefix) + target = spec.get('product_name', target) + product_ext = spec.get('product_extension') + if product_ext: + target_ext = '.' + product_ext + + return target_prefix + target + target_ext + + + def _InstallImmediately(self): + return self.toolset == 'target' and self.flavor == 'mac' and self.type in ( + 'static_library', 'executable', 'shared_library', 'loadable_module') + + + def ComputeOutput(self, spec): + """Return the 'output' (full output path) of a gyp spec. + + E.g., the loadable module 'foobar' in directory 'baz' will produce + '$(obj)/baz/libfoobar.so' + """ + assert not self.is_mac_bundle + + path = os.path.join('$(obj).' + self.toolset, self.path) + if self.type == 'executable' or self._InstallImmediately(): + path = '$(builddir)' + path = spec.get('product_dir', path) + return os.path.join(path, self.ComputeOutputBasename(spec)) + + + def ComputeMacBundleOutput(self, spec): + """Return the 'output' (full output path) to a bundle output directory.""" + assert self.is_mac_bundle + path = generator_default_variables['PRODUCT_DIR'] + return os.path.join(path, self.xcode_settings.GetWrapperName()) + + + def ComputeMacBundleBinaryOutput(self, spec): + """Return the 'output' (full output path) to the binary in a bundle.""" + path = generator_default_variables['PRODUCT_DIR'] + return os.path.join(path, self.xcode_settings.GetExecutablePath()) + + + def ComputeDeps(self, spec): + """Compute the dependencies of a gyp spec. + + Returns a tuple (deps, link_deps), where each is a list of + filenames that will need to be put in front of make for either + building (deps) or linking (link_deps). + """ + deps = [] + link_deps = [] + if 'dependencies' in spec: + deps.extend([target_outputs[dep] for dep in spec['dependencies'] + if target_outputs[dep]]) + for dep in spec['dependencies']: + if dep in target_link_deps: + link_deps.append(target_link_deps[dep]) + deps.extend(link_deps) + # TODO: It seems we need to transitively link in libraries (e.g. -lfoo)? + # This hack makes it work: + # link_deps.extend(spec.get('libraries', [])) + return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps)) + + + def WriteDependencyOnExtraOutputs(self, target, extra_outputs): + self.WriteMakeRule([self.output_binary], extra_outputs, + comment = 'Build our special outputs first.', + order_only = True) + + + def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, + extra_outputs, part_of_all): + """Write Makefile code to produce the final target of the gyp spec. + + spec, configs: input from gyp. + deps, link_deps: dependency lists; see ComputeDeps() + extra_outputs: any extra outputs that our target should depend on + part_of_all: flag indicating this target is part of 'all' + """ + + self.WriteLn('### Rules for final target.') + + if extra_outputs: + self.WriteDependencyOnExtraOutputs(self.output_binary, extra_outputs) + self.WriteMakeRule(extra_outputs, deps, + comment=('Preserve order dependency of ' + 'special output on deps.'), + order_only = True) + + target_postbuilds = {} + if self.type != 'none': + for configname in sorted(configs.keys()): + config = configs[configname] + if self.flavor == 'mac': + ldflags = self.xcode_settings.GetLdflags(configname, + generator_default_variables['PRODUCT_DIR'], + lambda p: Sourceify(self.Absolutify(p))) + + # TARGET_POSTBUILDS_$(BUILDTYPE) is added to postbuilds later on. + gyp_to_build = gyp.common.InvertRelativePath(self.path) + target_postbuild = self.xcode_settings.AddImplicitPostbuilds( + configname, + QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build, + self.output))), + QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build, + self.output_binary)))) + if target_postbuild: + target_postbuilds[configname] = target_postbuild + else: + ldflags = config.get('ldflags', []) + # Compute an rpath for this output if needed. + if any(dep.endswith('.so') or '.so.' in dep for dep in deps): + # We want to get the literal string "$ORIGIN" into the link command, + # so we need lots of escaping. + ldflags.append(r'-Wl,-rpath=\$$ORIGIN/lib.%s/' % self.toolset) + ldflags.append(r'-Wl,-rpath-link=\$(builddir)/lib.%s/' % + self.toolset) + library_dirs = config.get('library_dirs', []) + ldflags += [('-L%s' % library_dir) for library_dir in library_dirs] + self.WriteList(ldflags, 'LDFLAGS_%s' % configname) + if self.flavor == 'mac': + self.WriteList(self.xcode_settings.GetLibtoolflags(configname), + 'LIBTOOLFLAGS_%s' % configname) + libraries = spec.get('libraries') + if libraries: + # Remove duplicate entries + libraries = gyp.common.uniquer(libraries) + if self.flavor == 'mac': + libraries = self.xcode_settings.AdjustLibraries(libraries) + self.WriteList(libraries, 'LIBS') + self.WriteLn('%s: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))' % + QuoteSpaces(self.output_binary)) + self.WriteLn('%s: LIBS := $(LIBS)' % QuoteSpaces(self.output_binary)) + + if self.flavor == 'mac': + self.WriteLn('%s: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE))' % + QuoteSpaces(self.output_binary)) + + # Postbuild actions. Like actions, but implicitly depend on the target's + # output. + postbuilds = [] + if self.flavor == 'mac': + if target_postbuilds: + postbuilds.append('$(TARGET_POSTBUILDS_$(BUILDTYPE))') + postbuilds.extend( + gyp.xcode_emulation.GetSpecPostbuildCommands(spec)) + + if postbuilds: + # Envvars may be referenced by TARGET_POSTBUILDS_$(BUILDTYPE), + # so we must output its definition first, since we declare variables + # using ":=". + self.WriteSortedXcodeEnv(self.output, self.GetSortedXcodePostbuildEnv()) + + for configname in target_postbuilds: + self.WriteLn('%s: TARGET_POSTBUILDS_%s := %s' % + (QuoteSpaces(self.output), + configname, + gyp.common.EncodePOSIXShellList(target_postbuilds[configname]))) + + # Postbuilds expect to be run in the gyp file's directory, so insert an + # implicit postbuild to cd to there. + postbuilds.insert(0, gyp.common.EncodePOSIXShellList(['cd', self.path])) + for i in xrange(len(postbuilds)): + if not postbuilds[i].startswith('$'): + postbuilds[i] = EscapeShellArgument(postbuilds[i]) + self.WriteLn('%s: builddir := $(abs_builddir)' % QuoteSpaces(self.output)) + self.WriteLn('%s: POSTBUILDS := %s' % ( + QuoteSpaces(self.output), ' '.join(postbuilds))) + + # A bundle directory depends on its dependencies such as bundle resources + # and bundle binary. When all dependencies have been built, the bundle + # needs to be packaged. + if self.is_mac_bundle: + # If the framework doesn't contain a binary, then nothing depends + # on the actions -- make the framework depend on them directly too. + self.WriteDependencyOnExtraOutputs(self.output, extra_outputs) + + # Bundle dependencies. Note that the code below adds actions to this + # target, so if you move these two lines, move the lines below as well. + self.WriteList(map(QuoteSpaces, bundle_deps), 'BUNDLE_DEPS') + self.WriteLn('%s: $(BUNDLE_DEPS)' % QuoteSpaces(self.output)) + + # After the framework is built, package it. Needs to happen before + # postbuilds, since postbuilds depend on this. + if self.type in ('shared_library', 'loadable_module'): + self.WriteLn('\t@$(call do_cmd,mac_package_framework,,,%s)' % + self.xcode_settings.GetFrameworkVersion()) + + # Bundle postbuilds can depend on the whole bundle, so run them after + # the bundle is packaged, not already after the bundle binary is done. + if postbuilds: + self.WriteLn('\t@$(call do_postbuilds)') + postbuilds = [] # Don't write postbuilds for target's output. + + # Needed by test/mac/gyptest-rebuild.py. + self.WriteLn('\t@true # No-op, used by tests') + + # Since this target depends on binary and resources which are in + # nested subfolders, the framework directory will be older than + # its dependencies usually. To prevent this rule from executing + # on every build (expensive, especially with postbuilds), expliclity + # update the time on the framework directory. + self.WriteLn('\t@touch -c %s' % QuoteSpaces(self.output)) + + if postbuilds: + assert not self.is_mac_bundle, ('Postbuilds for bundles should be done ' + 'on the bundle, not the binary (target \'%s\')' % self.target) + assert 'product_dir' not in spec, ('Postbuilds do not work with ' + 'custom product_dir') + + if self.type == 'executable': + self.WriteLn('%s: LD_INPUTS := %s' % ( + QuoteSpaces(self.output_binary), + ' '.join(map(QuoteSpaces, link_deps)))) + if self.toolset == 'host' and self.flavor == 'android': + self.WriteDoCmd([self.output_binary], link_deps, 'link_host', + part_of_all, postbuilds=postbuilds) + else: + self.WriteDoCmd([self.output_binary], link_deps, 'link', part_of_all, + postbuilds=postbuilds) + + elif self.type == 'static_library': + for link_dep in link_deps: + assert ' ' not in link_dep, ( + "Spaces in alink input filenames not supported (%s)" % link_dep) + if (self.flavor not in ('mac', 'openbsd', 'netbsd', 'win') and not + self.is_standalone_static_library): + self.WriteDoCmd([self.output_binary], link_deps, 'alink_thin', + part_of_all, postbuilds=postbuilds) + else: + self.WriteDoCmd([self.output_binary], link_deps, 'alink', part_of_all, + postbuilds=postbuilds) + elif self.type == 'shared_library': + self.WriteLn('%s: LD_INPUTS := %s' % ( + QuoteSpaces(self.output_binary), + ' '.join(map(QuoteSpaces, link_deps)))) + self.WriteDoCmd([self.output_binary], link_deps, 'solink', part_of_all, + postbuilds=postbuilds) + elif self.type == 'loadable_module': + for link_dep in link_deps: + assert ' ' not in link_dep, ( + "Spaces in module input filenames not supported (%s)" % link_dep) + if self.toolset == 'host' and self.flavor == 'android': + self.WriteDoCmd([self.output_binary], link_deps, 'solink_module_host', + part_of_all, postbuilds=postbuilds) + else: + self.WriteDoCmd( + [self.output_binary], link_deps, 'solink_module', part_of_all, + postbuilds=postbuilds) + elif self.type == 'none': + # Write a stamp line. + self.WriteDoCmd([self.output_binary], deps, 'touch', part_of_all, + postbuilds=postbuilds) + else: + print "WARNING: no output for", self.type, target + + # Add an alias for each target (if there are any outputs). + # Installable target aliases are created below. + if ((self.output and self.output != self.target) and + (self.type not in self._INSTALLABLE_TARGETS)): + self.WriteMakeRule([self.target], [self.output], + comment='Add target alias', phony = True) + if part_of_all: + self.WriteMakeRule(['all'], [self.target], + comment = 'Add target alias to "all" target.', + phony = True) + + # Add special-case rules for our installable targets. + # 1) They need to install to the build dir or "product" dir. + # 2) They get shortcuts for building (e.g. "make chrome"). + # 3) They are part of "make all". + if (self.type in self._INSTALLABLE_TARGETS or + self.is_standalone_static_library): + if self.type == 'shared_library': + file_desc = 'shared library' + elif self.type == 'static_library': + file_desc = 'static library' + else: + file_desc = 'executable' + install_path = self._InstallableTargetInstallPath() + installable_deps = [self.output] + if (self.flavor == 'mac' and not 'product_dir' in spec and + self.toolset == 'target'): + # On mac, products are created in install_path immediately. + assert install_path == self.output, '%s != %s' % ( + install_path, self.output) + + # Point the target alias to the final binary output. + self.WriteMakeRule([self.target], [install_path], + comment='Add target alias', phony = True) + if install_path != self.output: + assert not self.is_mac_bundle # See comment a few lines above. + self.WriteDoCmd([install_path], [self.output], 'copy', + comment = 'Copy this to the %s output path.' % + file_desc, part_of_all=part_of_all) + installable_deps.append(install_path) + if self.output != self.alias and self.alias != self.target: + self.WriteMakeRule([self.alias], installable_deps, + comment = 'Short alias for building this %s.' % + file_desc, phony = True) + if part_of_all: + self.WriteMakeRule(['all'], [install_path], + comment = 'Add %s to "all" target.' % file_desc, + phony = True) + + + def WriteList(self, value_list, variable=None, prefix='', + quoter=QuoteIfNecessary): + """Write a variable definition that is a list of values. + + E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out + foo = blaha blahb + but in a pretty-printed style. + """ + values = '' + if value_list: + value_list = [quoter(prefix + l) for l in value_list] + values = ' \\\n\t' + ' \\\n\t'.join(value_list) + self.fp.write('%s :=%s\n\n' % (variable, values)) + + + def WriteDoCmd(self, outputs, inputs, command, part_of_all, comment=None, + postbuilds=False): + """Write a Makefile rule that uses do_cmd. + + This makes the outputs dependent on the command line that was run, + as well as support the V= make command line flag. + """ + suffix = '' + if postbuilds: + assert ',' not in command + suffix = ',,1' # Tell do_cmd to honor $POSTBUILDS + self.WriteMakeRule(outputs, inputs, + actions = ['$(call do_cmd,%s%s)' % (command, suffix)], + comment = comment, + command = command, + force = True) + # Add our outputs to the list of targets we read depfiles from. + # all_deps is only used for deps file reading, and for deps files we replace + # spaces with ? because escaping doesn't work with make's $(sort) and + # other functions. + outputs = [QuoteSpaces(o, SPACE_REPLACEMENT) for o in outputs] + self.WriteLn('all_deps += %s' % ' '.join(outputs)) + + + def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, + order_only=False, force=False, phony=False, command=None): + """Write a Makefile rule, with some extra tricks. + + outputs: a list of outputs for the rule (note: this is not directly + supported by make; see comments below) + inputs: a list of inputs for the rule + actions: a list of shell commands to run for the rule + comment: a comment to put in the Makefile above the rule (also useful + for making this Python script's code self-documenting) + order_only: if true, makes the dependency order-only + force: if true, include FORCE_DO_CMD as an order-only dep + phony: if true, the rule does not actually generate the named output, the + output is just a name to run the rule + command: (optional) command name to generate unambiguous labels + """ + outputs = map(QuoteSpaces, outputs) + inputs = map(QuoteSpaces, inputs) + + if comment: + self.WriteLn('# ' + comment) + if phony: + self.WriteLn('.PHONY: ' + ' '.join(outputs)) + if actions: + self.WriteLn("%s: TOOLSET := $(TOOLSET)" % outputs[0]) + force_append = ' FORCE_DO_CMD' if force else '' + + if order_only: + # Order only rule: Just write a simple rule. + # TODO(evanm): just make order_only a list of deps instead of this hack. + self.WriteLn('%s: | %s%s' % + (' '.join(outputs), ' '.join(inputs), force_append)) + elif len(outputs) == 1: + # Regular rule, one output: Just write a simple rule. + self.WriteLn('%s: %s%s' % (outputs[0], ' '.join(inputs), force_append)) + else: + # Regular rule, more than one output: Multiple outputs are tricky in + # make. We will write three rules: + # - All outputs depend on an intermediate file. + # - Make .INTERMEDIATE depend on the intermediate. + # - The intermediate file depends on the inputs and executes the + # actual command. + # - The intermediate recipe will 'touch' the intermediate file. + # - The multi-output rule will have an do-nothing recipe. + + # Hash the target name to avoid generating overlong filenames. + cmddigest = hashlib.sha1(command if command else self.target).hexdigest() + intermediate = "%s.intermediate" % cmddigest + self.WriteLn('%s: %s' % (' '.join(outputs), intermediate)) + self.WriteLn('\t%s' % '@:'); + self.WriteLn('%s: %s' % ('.INTERMEDIATE', intermediate)) + self.WriteLn('%s: %s%s' % + (intermediate, ' '.join(inputs), force_append)) + actions.insert(0, '$(call do_cmd,touch)') + + if actions: + for action in actions: + self.WriteLn('\t%s' % action) + self.WriteLn() + + + def WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps): + """Write a set of LOCAL_XXX definitions for Android NDK. + + These variable definitions will be used by Android NDK but do nothing for + non-Android applications. + + Arguments: + module_name: Android NDK module name, which must be unique among all + module names. + all_sources: A list of source files (will be filtered by Compilable). + link_deps: A list of link dependencies, which must be sorted in + the order from dependencies to dependents. + """ + if self.type not in ('executable', 'shared_library', 'static_library'): + return + + self.WriteLn('# Variable definitions for Android applications') + self.WriteLn('include $(CLEAR_VARS)') + self.WriteLn('LOCAL_MODULE := ' + module_name) + self.WriteLn('LOCAL_CFLAGS := $(CFLAGS_$(BUILDTYPE)) ' + '$(DEFS_$(BUILDTYPE)) ' + # LOCAL_CFLAGS is applied to both of C and C++. There is + # no way to specify $(CFLAGS_C_$(BUILDTYPE)) only for C + # sources. + '$(CFLAGS_C_$(BUILDTYPE)) ' + # $(INCS_$(BUILDTYPE)) includes the prefix '-I' while + # LOCAL_C_INCLUDES does not expect it. So put it in + # LOCAL_CFLAGS. + '$(INCS_$(BUILDTYPE))') + # LOCAL_CXXFLAGS is obsolete and LOCAL_CPPFLAGS is preferred. + self.WriteLn('LOCAL_CPPFLAGS := $(CFLAGS_CC_$(BUILDTYPE))') + self.WriteLn('LOCAL_C_INCLUDES :=') + self.WriteLn('LOCAL_LDLIBS := $(LDFLAGS_$(BUILDTYPE)) $(LIBS)') + + # Detect the C++ extension. + cpp_ext = {'.cc': 0, '.cpp': 0, '.cxx': 0} + default_cpp_ext = '.cpp' + for filename in all_sources: + ext = os.path.splitext(filename)[1] + if ext in cpp_ext: + cpp_ext[ext] += 1 + if cpp_ext[ext] > cpp_ext[default_cpp_ext]: + default_cpp_ext = ext + self.WriteLn('LOCAL_CPP_EXTENSION := ' + default_cpp_ext) + + self.WriteList(map(self.Absolutify, filter(Compilable, all_sources)), + 'LOCAL_SRC_FILES') + + # Filter out those which do not match prefix and suffix and produce + # the resulting list without prefix and suffix. + def DepsToModules(deps, prefix, suffix): + modules = [] + for filepath in deps: + filename = os.path.basename(filepath) + if filename.startswith(prefix) and filename.endswith(suffix): + modules.append(filename[len(prefix):-len(suffix)]) + return modules + + # Retrieve the default value of 'SHARED_LIB_SUFFIX' + params = {'flavor': 'linux'} + default_variables = {} + CalculateVariables(default_variables, params) + + self.WriteList( + DepsToModules(link_deps, + generator_default_variables['SHARED_LIB_PREFIX'], + default_variables['SHARED_LIB_SUFFIX']), + 'LOCAL_SHARED_LIBRARIES') + self.WriteList( + DepsToModules(link_deps, + generator_default_variables['STATIC_LIB_PREFIX'], + generator_default_variables['STATIC_LIB_SUFFIX']), + 'LOCAL_STATIC_LIBRARIES') + + if self.type == 'executable': + self.WriteLn('include $(BUILD_EXECUTABLE)') + elif self.type == 'shared_library': + self.WriteLn('include $(BUILD_SHARED_LIBRARY)') + elif self.type == 'static_library': + self.WriteLn('include $(BUILD_STATIC_LIBRARY)') + self.WriteLn() + + + def WriteLn(self, text=''): + self.fp.write(text + '\n') + + + def GetSortedXcodeEnv(self, additional_settings=None): + return gyp.xcode_emulation.GetSortedXcodeEnv( + self.xcode_settings, "$(abs_builddir)", + os.path.join("$(abs_srcdir)", self.path), "$(BUILDTYPE)", + additional_settings) + + + def GetSortedXcodePostbuildEnv(self): + # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack. + # TODO(thakis): It would be nice to have some general mechanism instead. + strip_save_file = self.xcode_settings.GetPerTargetSetting( + 'CHROMIUM_STRIP_SAVE_FILE', '') + # Even if strip_save_file is empty, explicitly write it. Else a postbuild + # might pick up an export from an earlier target. + return self.GetSortedXcodeEnv( + additional_settings={'CHROMIUM_STRIP_SAVE_FILE': strip_save_file}) + + + def WriteSortedXcodeEnv(self, target, env): + for k, v in env: + # For + # foo := a\ b + # the escaped space does the right thing. For + # export foo := a\ b + # it does not -- the backslash is written to the env as literal character. + # So don't escape spaces in |env[k]|. + self.WriteLn('%s: export %s := %s' % (QuoteSpaces(target), k, v)) + + + def Objectify(self, path): + """Convert a path to its output directory form.""" + if '$(' in path: + path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/' % self.toolset) + if not '$(obj)' in path: + path = '$(obj).%s/$(TARGET)/%s' % (self.toolset, path) + return path + + + def Pchify(self, path, lang): + """Convert a prefix header path to its output directory form.""" + path = self.Absolutify(path) + if '$(' in path: + path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/pch-%s' % + (self.toolset, lang)) + return path + return '$(obj).%s/$(TARGET)/pch-%s/%s' % (self.toolset, lang, path) + + + def Absolutify(self, path): + """Convert a subdirectory-relative path into a base-relative path. + Skips over paths that contain variables.""" + if '$(' in path: + # Don't call normpath in this case, as it might collapse the + # path too aggressively if it features '..'. However it's still + # important to strip trailing slashes. + return path.rstrip('/') + return os.path.normpath(os.path.join(self.path, path)) + + + def ExpandInputRoot(self, template, expansion, dirname): + if '%(INPUT_ROOT)s' not in template and '%(INPUT_DIRNAME)s' not in template: + return template + path = template % { + 'INPUT_ROOT': expansion, + 'INPUT_DIRNAME': dirname, + } + return path + + + def _InstallableTargetInstallPath(self): + """Returns the location of the final output for an installable target.""" + # Xcode puts shared_library results into PRODUCT_DIR, and some gyp files + # rely on this. Emulate this behavior for mac. + + # XXX(TooTallNate): disabling this code since we don't want this behavior... + #if (self.type == 'shared_library' and + # (self.flavor != 'mac' or self.toolset != 'target')): + # # Install all shared libs into a common directory (per toolset) for + # # convenient access with LD_LIBRARY_PATH. + # return '$(builddir)/lib.%s/%s' % (self.toolset, self.alias) + return '$(builddir)/' + self.alias + + +def WriteAutoRegenerationRule(params, root_makefile, makefile_name, + build_files): + """Write the target to regenerate the Makefile.""" + options = params['options'] + build_files_args = [gyp.common.RelativePath(filename, options.toplevel_dir) + for filename in params['build_files_arg']] + + gyp_binary = gyp.common.FixIfRelativePath(params['gyp_binary'], + options.toplevel_dir) + if not gyp_binary.startswith(os.sep): + gyp_binary = os.path.join('.', gyp_binary) + + root_makefile.write( + "quiet_cmd_regen_makefile = ACTION Regenerating $@\n" + "cmd_regen_makefile = cd $(srcdir); %(cmd)s\n" + "%(makefile_name)s: %(deps)s\n" + "\t$(call do_cmd,regen_makefile)\n\n" % { + 'makefile_name': makefile_name, + 'deps': ' '.join(map(SourceifyAndQuoteSpaces, build_files)), + 'cmd': gyp.common.EncodePOSIXShellList( + [gyp_binary, '-fmake'] + + gyp.RegenerateFlags(options) + + build_files_args)}) + + +def PerformBuild(data, configurations, params): + options = params['options'] + for config in configurations: + arguments = ['make'] + if options.toplevel_dir and options.toplevel_dir != '.': + arguments += '-C', options.toplevel_dir + arguments.append('BUILDTYPE=' + config) + print 'Building [%s]: %s' % (config, arguments) + subprocess.check_call(arguments) + + +def GenerateOutput(target_list, target_dicts, data, params): + options = params['options'] + flavor = gyp.common.GetFlavor(params) + generator_flags = params.get('generator_flags', {}) + builddir_name = generator_flags.get('output_dir', 'out') + android_ndk_version = generator_flags.get('android_ndk_version', None) + default_target = generator_flags.get('default_target', 'all') + + def CalculateMakefilePath(build_file, base_name): + """Determine where to write a Makefile for a given gyp file.""" + # Paths in gyp files are relative to the .gyp file, but we want + # paths relative to the source root for the master makefile. Grab + # the path of the .gyp file as the base to relativize against. + # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp". + base_path = gyp.common.RelativePath(os.path.dirname(build_file), + options.depth) + # 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.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 + + # TODO: search for the first non-'Default' target. This can go + # away when we add verification that all targets have the + # necessary configurations. + default_configuration = None + toolsets = set([target_dicts[target]['toolset'] for target in target_list]) + for target in target_list: + spec = target_dicts[target] + if spec['default_configuration'] != 'Default': + default_configuration = spec['default_configuration'] + break + if not default_configuration: + default_configuration = 'Default' + + srcdir = '.' + makefile_name = 'Makefile' + options.suffix + makefile_path = os.path.join(options.toplevel_dir, makefile_name) + if options.generator_output: + global srcdir_prefix + makefile_path = os.path.join( + options.toplevel_dir, options.generator_output, makefile_name) + srcdir = gyp.common.RelativePath(srcdir, options.generator_output) + srcdir_prefix = '$(srcdir)/' + + flock_command= 'flock' + copy_archive_arguments = '-af' + makedep_arguments = '-MMD' + header_params = { + 'default_target': default_target, + 'builddir': builddir_name, + 'default_configuration': default_configuration, + 'flock': flock_command, + 'flock_index': 1, + 'link_commands': LINK_COMMANDS_LINUX, + 'extra_commands': '', + 'srcdir': srcdir, + 'copy_archive_args': copy_archive_arguments, + 'makedep_args': makedep_arguments, + } + if flavor == 'mac': + flock_command = './gyp-mac-tool flock' + header_params.update({ + 'flock': flock_command, + 'flock_index': 2, + 'link_commands': LINK_COMMANDS_MAC, + 'extra_commands': SHARED_HEADER_MAC_COMMANDS, + }) + elif flavor == 'android': + header_params.update({ + 'link_commands': LINK_COMMANDS_ANDROID, + }) + elif flavor == 'zos': + copy_archive_arguments = '-fPR' + makedep_arguments = '-qmakedep=gcc' + header_params.update({ + 'copy_archive_args': copy_archive_arguments, + 'makedep_args': makedep_arguments, + 'link_commands': LINK_COMMANDS_OS390, + }) + elif flavor == 'solaris': + header_params.update({ + 'flock': './gyp-flock-tool flock', + 'flock_index': 2, + }) + elif flavor == 'freebsd': + # Note: OpenBSD has sysutils/flock. lockf seems to be FreeBSD specific. + header_params.update({ + 'flock': 'lockf', + }) + elif flavor == 'openbsd': + copy_archive_arguments = '-pPRf' + header_params.update({ + 'copy_archive_args': copy_archive_arguments, + }) + elif flavor == 'aix': + copy_archive_arguments = '-pPRf' + header_params.update({ + 'copy_archive_args': copy_archive_arguments, + 'link_commands': LINK_COMMANDS_AIX, + 'flock': './gyp-flock-tool flock', + 'flock_index': 2, + }) + + header_params.update({ + 'CC.target': GetEnvironFallback(('CC_target', 'CC'), '$(CC)'), + 'AR.target': GetEnvironFallback(('AR_target', 'AR'), '$(AR)'), + 'CXX.target': GetEnvironFallback(('CXX_target', 'CXX'), '$(CXX)'), + 'LINK.target': GetEnvironFallback(('LINK_target', 'LINK'), '$(LINK)'), + 'CC.host': GetEnvironFallback(('CC_host', 'CC'), 'gcc'), + 'AR.host': GetEnvironFallback(('AR_host', 'AR'), 'ar'), + 'CXX.host': GetEnvironFallback(('CXX_host', 'CXX'), 'g++'), + 'LINK.host': GetEnvironFallback(('LINK_host', 'LINK'), '$(CXX.host)'), + }) + + build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) + make_global_settings_array = data[build_file].get('make_global_settings', []) + wrappers = {} + for key, value in make_global_settings_array: + if key.endswith('_wrapper'): + wrappers[key[:-len('_wrapper')]] = '$(abspath %s)' % value + make_global_settings = '' + for key, value in make_global_settings_array: + if re.match('.*_wrapper', key): + continue + if value[0] != '$': + value = '$(abspath %s)' % value + wrapper = wrappers.get(key) + if wrapper: + value = '%s %s' % (wrapper, value) + del wrappers[key] + if key in ('CC', 'CC.host', 'CXX', 'CXX.host'): + make_global_settings += ( + 'ifneq (,$(filter $(origin %s), undefined default))\n' % key) + # Let gyp-time envvars win over global settings. + 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: + make_global_settings += '%s ?= %s\n' % (key, value) + # TODO(ukai): define cmd when only wrapper is specified in + # make_global_settings. + + header_params['make_global_settings'] = make_global_settings + + 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 + # could be different. + if android_ndk_version: + root_makefile.write( + '# Define LOCAL_PATH for build of Android applications.\n' + 'LOCAL_PATH := $(call my-dir)\n' + '\n') + for toolset in toolsets: + root_makefile.write('TOOLSET := %s\n' % toolset) + WriteRootHeaderSuffixRules(root_makefile) + + # Put build-time support tools next to the root Makefile. + dest_path = os.path.dirname(makefile_path) + gyp.common.CopyTool(flavor, dest_path) + + # Find the list of targets that derive from the gyp file(s) being built. + needed_targets = set() + for build_file in params['build_files']: + for target in gyp.common.AllTargets(target_list, target_dicts, build_file): + needed_targets.add(target) + + build_files = set() + include_list = set() + for qualified_target in target_list: + build_file, target, toolset = gyp.common.ParseQualifiedTarget( + qualified_target) + + 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. %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'] + for included_file in included_files: + # The included_files entries are relative to the dir of the build file + # that included them, so we have to undo that and then make them relative + # to the root dir. + relative_include_file = gyp.common.RelativePath( + gyp.common.UnrelativePath(included_file, build_file), + options.toplevel_dir) + abs_include_file = os.path.abspath(relative_include_file) + # If the include file is from the ~/.gyp dir, we should use absolute path + # so that relocating the src dir doesn't break the path. + if (params['home_dot_gyp'] and + abs_include_file.startswith(params['home_dot_gyp'])): + build_files.add(abs_include_file) + else: + build_files.add(relative_include_file) + + base_path, output_file = CalculateMakefilePath(build_file, + target + '.' + toolset + options.suffix + '.mk') + + spec = target_dicts[qualified_target] + configs = spec['configurations'] + + if flavor == 'mac': + gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec) + + writer = MakefileWriter(generator_flags, flavor) + writer.Write(qualified_target, base_path, output_file, spec, configs, + part_of_all=qualified_target in needed_targets) + + # Our root_makefile lives at the source root. Compute the relative path + # from there to the output_file for including. + mkfile_rel_path = gyp.common.RelativePath(output_file, + os.path.dirname(makefile_path)) + include_list.add(mkfile_rel_path) + + # Write out per-gyp (sub-project) Makefiles. + depth_rel_path = gyp.common.RelativePath(options.depth, os.getcwd()) + for build_file in build_files: + # The paths in build_files were relativized above, so undo that before + # testing against the non-relativized items in target_list and before + # calculating the Makefile path. + build_file = os.path.join(depth_rel_path, build_file) + gyp_targets = [target_dicts[target]['target_name'] for target in target_list + if target.startswith(build_file) and + target in needed_targets] + # Only generate Makefiles for gyp files with targets. + if not gyp_targets: + continue + base_path, output_file = CalculateMakefilePath(build_file, + os.path.splitext(os.path.basename(build_file))[0] + '.Makefile') + makefile_rel_path = gyp.common.RelativePath(os.path.dirname(makefile_path), + os.path.dirname(output_file)) + writer.WriteSubMake(output_file, makefile_rel_path, gyp_targets, + builddir_name) + + + # Write out the sorted list of includes. + root_makefile.write('\n') + for include_file in sorted(include_list): + # We wrap each .mk include in an if statement so users can tell make to + # not load a file by setting NO_LOAD. The below make code says, only + # load the .mk file if the .mk filename doesn't start with a token in + # NO_LOAD. + root_makefile.write( + "ifeq ($(strip $(foreach prefix,$(NO_LOAD),\\\n" + " $(findstring $(join ^,$(prefix)),\\\n" + " $(join ^," + include_file + ")))),)\n") + root_makefile.write(" include " + include_file + "\n") + root_makefile.write("endif\n") + root_makefile.write('\n') + + if (not generator_flags.get('standalone') + and generator_flags.get('auto_regeneration', True)): + WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files) + + root_makefile.write(SHARED_FOOTER) + + root_makefile.close() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py new file mode 100644 index 0000000000000..3901ba94161e6 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py @@ -0,0 +1,3494 @@ +# Copyright (c) 2012 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. + +import copy +import ntpath +import os +import posixpath +import re +import subprocess +import sys + +import gyp.common +import gyp.easy_xml as easy_xml +import gyp.generator.ninja as ninja_generator +import gyp.MSVSNew as MSVSNew +import gyp.MSVSProject as MSVSProject +import gyp.MSVSSettings as MSVSSettings +import gyp.MSVSToolFile as MSVSToolFile +import gyp.MSVSUserFile as MSVSUserFile +import gyp.MSVSUtil as MSVSUtil +import gyp.MSVSVersion as MSVSVersion +from gyp.common import GypError +from gyp.common import OrderedSet + +# 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, +# IncrediBuild BuildConsole will parse the solution file, but then +# silently skip building the target causing hard to track down errors. +# Note that this only happens with the BuildConsole, and does not occur +# if IncrediBuild is executed from inside Visual Studio. This regex +# validates that the string looks like a GUID with all uppercase hex +# letters. +VALID_MSVS_GUID_CHARS = re.compile(r'^[A-F0-9\-]+$') + + +generator_default_variables = { + 'EXECUTABLE_PREFIX': '', + 'EXECUTABLE_SUFFIX': '.exe', + 'STATIC_LIB_PREFIX': '', + 'SHARED_LIB_PREFIX': '', + 'STATIC_LIB_SUFFIX': '.lib', + 'SHARED_LIB_SUFFIX': '.dll', + 'INTERMEDIATE_DIR': '$(IntDir)', + 'SHARED_INTERMEDIATE_DIR': '$(OutDir)obj/global_intermediate', + 'OS': 'win', + 'PRODUCT_DIR': '$(OutDir)', + 'LIB_DIR': '$(OutDir)lib', + 'RULE_INPUT_ROOT': '$(InputName)', + 'RULE_INPUT_DIRNAME': '$(InputDir)', + 'RULE_INPUT_EXT': '$(InputExt)', + 'RULE_INPUT_NAME': '$(InputFileName)', + 'RULE_INPUT_PATH': '$(InputPath)', + 'CONFIGURATION_NAME': '$(ConfigurationName)', +} + + +# The msvs specific sections that hold paths +generator_additional_path_sections = [ + 'msvs_cygwin_dirs', + 'msvs_props', +] + + +generator_additional_non_configuration_keys = [ + 'msvs_cygwin_dirs', + 'msvs_cygwin_shell', + 'msvs_large_pdb', + 'msvs_shard', + 'msvs_external_builder', + 'msvs_external_builder_out_dir', + 'msvs_external_builder_build_cmd', + 'msvs_external_builder_clean_cmd', + 'msvs_external_builder_clcompile_cmd', + 'msvs_enable_winrt', + 'msvs_requires_importlibrary', + 'msvs_enable_winphone', + 'msvs_application_type_revision', + 'msvs_target_platform_version', + 'msvs_target_platform_minversion', +] + + +# List of precompiled header related keys. +precomp_keys = [ + 'msvs_precompiled_header', + 'msvs_precompiled_source', +] + + +cached_username = None + + +cached_domain = None + + +# 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 +# 64-bit. +def _GetDomainAndUserName(): + if sys.platform not in ('win32', 'cygwin'): + return ('DOMAIN', 'USERNAME') + global cached_username + global cached_domain + if not cached_domain or not cached_username: + domain = os.environ.get('USERDOMAIN') + username = os.environ.get('USERNAME') + if not domain or not username: + call = subprocess.Popen(['net', 'config', 'Workstation'], + stdout=subprocess.PIPE) + config = call.communicate()[0] + username_re = re.compile(r'^User name\s+(\S+)', re.MULTILINE) + username_match = username_re.search(config) + if username_match: + username = username_match.group(1) + domain_re = re.compile(r'^Logon domain\s+(\S+)', re.MULTILINE) + domain_match = domain_re.search(config) + if domain_match: + domain = domain_match.group(1) + cached_domain = domain + cached_username = username + return (cached_domain, cached_username) + +fixpath_prefix = None + + +def _NormalizedSource(source): + """Normalize the path. + + But not if that gets rid of a variable, as this may expand to something + larger than one directory. + + Arguments: + source: The path to be normalize.d + + Returns: + The normalized path. + """ + normalized = os.path.normpath(source) + if source.count('$') == normalized.count('$'): + source = normalized + return source + + +def _FixPath(path): + """Convert paths to a form that will make sense in a vcproj file. + + Arguments: + path: The path to convert, may contain / etc. + Returns: + The path with all slashes made into backslashes. + """ + if fixpath_prefix and path and not os.path.isabs(path) and not path[0] == '$': + path = os.path.join(fixpath_prefix, path) + path = path.replace('/', '\\') + path = _NormalizedSource(path) + if path and path[-1] == '\\': + path = path[:-1] + return path + + +def _FixPaths(paths): + """Fix each of the paths of the list.""" + return [_FixPath(i) for i in paths] + + +def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None, + 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 + layout of the source tree. + For example: + _ConvertSourcesToFilterHierarchy([['a', 'bob1.c'], ['b', 'bob2.c']], + prefix=['joe']) + --> + [MSVSProject.Filter('a', contents=['joe\\a\\bob1.c']), + MSVSProject.Filter('b', contents=['joe\\b\\bob2.c'])] + """ + if not prefix: prefix = [] + result = [] + excluded_result = [] + folders = OrderedDict() + # Gather files into the final result, excluded, or folders. + for s in sources: + if len(s) == 1: + filename = _NormalizedSource('\\'.join(prefix + s)) + if filename in excluded: + excluded_result.append(filename) + else: + result.append(filename) + 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], + excluded=excluded, + list_excluded=list_excluded, + msvs_version=msvs_version) + contents = MSVSProject.Filter(f, contents=contents) + result.append(contents) + return result + + +def _ToolAppend(tools, tool_name, setting, value, only_if_unset=False): + if not value: return + _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset) + + +def _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset=False): + # TODO(bradnelson): ugly hack, fix this more generally!!! + if 'Directories' in setting or 'Dependencies' in setting: + if type(value) == str: + value = value.replace('/', '\\') + else: + value = [i.replace('/', '\\') for i in value] + if not tools.get(tool_name): + tools[tool_name] = dict() + tool = tools[tool_name] + if tool.get(setting): + if only_if_unset: return + if type(tool[setting]) == list and type(value) == list: + tool[setting] += value + else: + raise TypeError( + 'Appending "%s" to a non-list setting "%s" for tool "%s" is ' + 'not allowed, previous value: %s' % ( + value, setting, tool_name, str(tool[setting]))) + else: + tool[setting] = value + + +def _ConfigPlatform(config_data): + return config_data.get('msvs_configuration_platform', 'Win32') + + +def _ConfigBaseName(config_name, platform_name): + if config_name.endswith('_' + platform_name): + return config_name[0:-len(platform_name) - 1] + else: + return config_name + + +def _ConfigFullName(config_name, config_data): + platform_name = _ConfigPlatform(config_data) + return '%s|%s' % (_ConfigBaseName(config_name, platform_name), platform_name) + + +def _ConfigWindowsTargetPlatformVersion(config_data): + ver = config_data.get('msvs_windows_target_platform_version') + if not ver or re.match(r'^\d+', ver): + return ver + for key in [r'HKLM\Software\Microsoft\Microsoft SDKs\Windows\%s', + r'HKLM\Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows\%s']: + sdkdir = MSVSVersion._RegistryGetValue(key % ver, 'InstallationFolder') + if not sdkdir: + continue + version = MSVSVersion._RegistryGetValue(key % ver, 'ProductVersion') or '' + # find a matching entry in sdkdir\include + names = sorted([x for x in os.listdir(r'%s\include' % sdkdir) \ + if x.startswith(version)], reverse = True) + return names[0] + + +def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, + quote_cmd, do_setup_env): + + if [x for x in cmd if '$(InputDir)' in x]: + input_dir_preamble = ( + 'set INPUTDIR=$(InputDir)\n' + 'if NOT DEFINED INPUTDIR set INPUTDIR=.\\\n' + 'set INPUTDIR=%INPUTDIR:~0,-1%\n' + ) + else: + input_dir_preamble = '' + + if cygwin_shell: + # Find path to cygwin. + cygwin_dir = _FixPath(spec.get('msvs_cygwin_dirs', ['.'])[0]) + # Prepare command. + direct_cmd = cmd + direct_cmd = [i.replace('$(IntDir)', + '`cygpath -m "${INTDIR}"`') for i in direct_cmd] + direct_cmd = [i.replace('$(OutDir)', + '`cygpath -m "${OUTDIR}"`') for i in direct_cmd] + direct_cmd = [i.replace('$(InputDir)', + '`cygpath -m "${INPUTDIR}"`') for i in direct_cmd] + if has_input_path: + direct_cmd = [i.replace('$(InputPath)', + '`cygpath -m "${INPUTPATH}"`') + for i in direct_cmd] + direct_cmd = ['\\"%s\\"' % i.replace('"', '\\\\\\"') for i in direct_cmd] + # direct_cmd = gyp.common.EncodePOSIXShellList(direct_cmd) + direct_cmd = ' '.join(direct_cmd) + # TODO(quote): regularize quoting path names throughout the module + cmd = '' + if do_setup_env: + cmd += 'call "$(ProjectDir)%(cygwin_dir)s\\setup_env.bat" && ' + cmd += 'set CYGWIN=nontsec&& ' + if direct_cmd.find('NUMBER_OF_PROCESSORS') >= 0: + cmd += 'set /a NUMBER_OF_PROCESSORS_PLUS_1=%%NUMBER_OF_PROCESSORS%%+1&& ' + if direct_cmd.find('INTDIR') >= 0: + cmd += 'set INTDIR=$(IntDir)&& ' + if direct_cmd.find('OUTDIR') >= 0: + cmd += 'set OUTDIR=$(OutDir)&& ' + if has_input_path and direct_cmd.find('INPUTPATH') >= 0: + cmd += 'set INPUTPATH=$(InputPath) && ' + cmd += 'bash -c "%(cmd)s"' + cmd = cmd % {'cygwin_dir': cygwin_dir, + 'cmd': direct_cmd} + return input_dir_preamble + cmd + else: + # Convert cat --> type to mimic unix. + if cmd[0] == 'cat': + command = ['type'] + else: + command = [cmd[0].replace('/', '\\')] + # Add call before command to ensure that commands can be tied together one + # after the other without aborting in Incredibuild, since IB makes a bat + # file out of the raw command string, and some commands (like python) are + # actually batch files themselves. + command.insert(0, 'call') + # Fix the paths + # TODO(quote): This is a really ugly heuristic, and will miss path fixing + # for arguments like "--arg=path" or "/opt:path". + # If the argument starts with a slash or dash, it's probably a command line + # switch + arguments = [i if (i[:1] in "/-") else _FixPath(i) for i in cmd[1:]] + arguments = [i.replace('$(InputDir)', '%INPUTDIR%') for i in arguments] + arguments = [MSVSSettings.FixVCMacroSlashes(i) for i in arguments] + if quote_cmd: + # Support a mode for using cmd directly. + # Convert any paths to native form (first element is used directly). + # TODO(quote): regularize quoting path names throughout the module + arguments = ['"%s"' % i for i in arguments] + # Collapse into a single command. + return input_dir_preamble + ' '.join(command + arguments) + + +def _BuildCommandLineForRule(spec, rule, has_input_path, do_setup_env): + # Currently this weird argument munging is used to duplicate the way a + # python script would need to be run as part of the chrome tree. + # Eventually we should add some sort of rule_default option to set this + # per project. For now the behavior chrome needs is the default. + mcs = rule.get('msvs_cygwin_shell') + if mcs is None: + mcs = int(spec.get('msvs_cygwin_shell', 1)) + elif isinstance(mcs, str): + mcs = int(mcs) + quote_cmd = int(rule.get('msvs_quote_cmd', 1)) + return _BuildCommandLineForRuleRaw(spec, rule['action'], mcs, has_input_path, + quote_cmd, do_setup_env=do_setup_env) + + +def _AddActionStep(actions_dict, inputs, outputs, description, command): + """Merge action into an existing list of actions. + + Care must be taken so that actions which have overlapping inputs either don't + get assigned to the same input, or get collapsed into one. + + Arguments: + actions_dict: dictionary keyed on input name, which maps to a list of + dicts describing the actions attached to that input file. + inputs: list of inputs + outputs: list of outputs + description: description of the action + command: command line to execute + """ + # Require there to be at least one input (call sites will ensure this). + assert inputs + + action = { + 'inputs': inputs, + 'outputs': outputs, + 'description': description, + 'command': command, + } + + # Pick where to stick this action. + # While less than optimal in terms of build time, attach them to the first + # input for now. + chosen_input = inputs[0] + + # Add it there. + if chosen_input not in actions_dict: + actions_dict[chosen_input] = [] + actions_dict[chosen_input].append(action) + + +def _AddCustomBuildToolForMSVS(p, spec, primary_input, + inputs, outputs, description, cmd): + """Add a custom build tool to execute something. + + Arguments: + p: the target project + spec: the target project dict + primary_input: input file to attach the build tool to + inputs: list of inputs + outputs: list of outputs + description: description of the action + cmd: command line to execute + """ + inputs = _FixPaths(inputs) + outputs = _FixPaths(outputs) + tool = MSVSProject.Tool( + 'VCCustomBuildTool', + {'Description': description, + 'AdditionalDependencies': ';'.join(inputs), + 'Outputs': ';'.join(outputs), + 'CommandLine': cmd, + }) + # Add to the properties of primary input for each config. + for config_name, c_data in spec['configurations'].iteritems(): + p.AddFileConfig(_FixPath(primary_input), + _ConfigFullName(config_name, c_data), tools=[tool]) + + +def _AddAccumulatedActionsToMSVS(p, spec, actions_dict): + """Add actions accumulated into an actions_dict, merging as needed. + + Arguments: + p: the target project + spec: the target project dict + actions_dict: dictionary keyed on input name, which maps to a list of + dicts describing the actions attached to that input file. + """ + for primary_input in actions_dict: + inputs = OrderedSet() + outputs = OrderedSet() + descriptions = [] + commands = [] + for action in actions_dict[primary_input]: + 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. + description = ', and also '.join(descriptions) + command = '\r\n'.join(commands) + _AddCustomBuildToolForMSVS(p, spec, + primary_input=primary_input, + inputs=inputs, + outputs=outputs, + description=description, + cmd=command) + + +def _RuleExpandPath(path, input_file): + """Given the input file to which a rule applied, string substitute a path. + + Arguments: + path: a path to string expand + input_file: the file to which the rule applied. + Returns: + The string substituted path. + """ + path = path.replace('$(InputName)', + os.path.splitext(os.path.split(input_file)[1])[0]) + path = path.replace('$(InputDir)', os.path.dirname(input_file)) + path = path.replace('$(InputExt)', + os.path.splitext(os.path.split(input_file)[1])[1]) + path = path.replace('$(InputFileName)', os.path.split(input_file)[1]) + path = path.replace('$(InputPath)', input_file) + return path + + +def _FindRuleTriggerFiles(rule, sources): + """Find the list of files which a particular rule applies to. + + Arguments: + rule: the rule in question + sources: the set of all known source files for this project + Returns: + The list of sources that trigger a particular rule. + """ + return rule.get('rule_sources', []) + + +def _RuleInputsAndOutputs(rule, trigger_file): + """Find the inputs and outputs generated by a rule. + + Arguments: + rule: the rule in question. + trigger_file: the main trigger for this rule. + Returns: + The pair of (inputs, outputs) involved in this rule. + """ + raw_inputs = _FixPaths(rule.get('inputs', [])) + raw_outputs = _FixPaths(rule.get('outputs', [])) + inputs = OrderedSet() + outputs = OrderedSet() + inputs.add(trigger_file) + for i in raw_inputs: + inputs.add(_RuleExpandPath(i, trigger_file)) + for o in raw_outputs: + outputs.add(_RuleExpandPath(o, trigger_file)) + return (inputs, outputs) + + +def _GenerateNativeRulesForMSVS(p, rules, output_dir, spec, options): + """Generate a native rules file. + + Arguments: + p: the target project + rules: the set of rules to include + output_dir: the directory in which the project/gyp resides + spec: the project dict + options: global generator options + """ + rules_filename = '%s%s.rules' % (spec['target_name'], + options.suffix) + rules_file = MSVSToolFile.Writer(os.path.join(output_dir, rules_filename), + spec['target_name']) + # Add each rule. + for r in rules: + rule_name = r['rule_name'] + rule_ext = r['extension'] + inputs = _FixPaths(r.get('inputs', [])) + outputs = _FixPaths(r.get('outputs', [])) + # Skip a rule with no action and no inputs. + if 'action' not in r and not r.get('rule_sources', []): + continue + cmd = _BuildCommandLineForRule(spec, r, has_input_path=True, + do_setup_env=True) + rules_file.AddCustomBuildRule(name=rule_name, + description=r.get('message', rule_name), + extensions=[rule_ext], + additional_dependencies=inputs, + outputs=outputs, + cmd=cmd) + # Write out rules file. + rules_file.WriteIfChanged() + + # Add rules file to project. + p.AddToolFile(rules_filename) + + +def _Cygwinify(path): + path = path.replace('$(OutDir)', '$(OutDirCygwin)') + path = path.replace('$(IntDir)', '$(IntDirCygwin)') + return path + + +def _GenerateExternalRules(rules, output_dir, spec, + sources, options, actions_to_add): + """Generate an external makefile to do a set of rules. + + Arguments: + rules: the list of rules to include + output_dir: path containing project and gyp files + spec: project specification data + sources: set of sources known + options: global generator options + actions_to_add: The list of actions we will add to. + """ + filename = '%s_rules%s.mk' % (spec['target_name'], options.suffix) + mk_file = gyp.common.WriteOnDiff(os.path.join(output_dir, filename)) + # Find cygwin style versions of some paths. + 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 = 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(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]) + # Get the unique output directories for this rule. + output_dirs = [os.path.split(i)[0] for i in outputs] + for od in output_dirs: + all_output_dirs.add(od) + first_outputs_cyg = [_Cygwinify(i) for i in first_outputs] + # Write out all: target, including mkdir for each output directory. + mk_file.write('all: %s\n' % ' '.join(first_outputs_cyg)) + for od in all_output_dirs: + if od: + mk_file.write('\tmkdir -p `cygpath -u "%s"`\n' % od) + mk_file.write('\n') + # Define how each output is generated. + for rule in rules: + trigger_files = _FindRuleTriggerFiles(rule, sources) + for tf in trigger_files: + # Get all the inputs and outputs for this rule for this trigger file. + inputs, outputs = _RuleInputsAndOutputs(rule, tf) + inputs = [_Cygwinify(i) for i in inputs] + outputs = [_Cygwinify(i) for i in outputs] + # Prepare the command line for this rule. + cmd = [_RuleExpandPath(c, tf) for c in rule['action']] + cmd = ['"%s"' % i for i in cmd] + cmd = ' '.join(cmd) + # Add it to the makefile. + mk_file.write('%s: %s\n' % (' '.join(outputs), ' '.join(inputs))) + mk_file.write('\t%s\n\n' % cmd) + # Close up the file. + mk_file.close() + + # Add makefile to list of sources. + sources.add(filename) + # Add a build action to call makefile. + cmd = ['make', + 'OutDir=$(OutDir)', + 'IntDir=$(IntDir)', + '-j', '${NUMBER_OF_PROCESSORS_PLUS_1}', + '-f', filename] + cmd = _BuildCommandLineForRuleRaw(spec, cmd, True, False, True, True) + # Insert makefile as 0'th input, so it gets the action attached there, + # as this is easier to understand from in the IDE. + all_inputs = list(all_inputs) + all_inputs.insert(0, filename) + _AddActionStep(actions_to_add, + inputs=_FixPaths(all_inputs), + outputs=_FixPaths(all_outputs), + description='Running external rules for %s' % + spec['target_name'], + command=cmd) + + +def _EscapeEnvironmentVariableExpansion(s): + """Escapes % characters. + + Escapes any % characters so that Windows-style environment variable + expansions will leave them alone. + See http://connect.microsoft.com/VisualStudio/feedback/details/106127/cl-d-name-text-containing-percentage-characters-doesnt-compile + to understand why we have to do this. + + Args: + s: The string to be escaped. + + Returns: + The escaped string. + """ + s = s.replace('%', '%%') + return s + + +quote_replacer_regex = re.compile(r'(\\*)"') + + +def _EscapeCommandLineArgumentForMSVS(s): + """Escapes a Windows command-line argument. + + So that the Win32 CommandLineToArgv function will turn the escaped result back + into the original string. + See http://msdn.microsoft.com/en-us/library/17w5ykft.aspx + ("Parsing C++ Command-Line Arguments") to understand why we have to do + this. + + Args: + s: the string to be escaped. + Returns: + the escaped string. + """ + + def _Replace(match): + # For a literal quote, CommandLineToArgv requires an odd number of + # backslashes preceding it, and it produces half as many literal backslashes + # (rounded down). So we need to produce 2n+1 backslashes. + return 2 * match.group(1) + '\\"' + + # Escape all quotes so that they are interpreted literally. + s = quote_replacer_regex.sub(_Replace, s) + # Now add unescaped quotes so that any whitespace is interpreted literally. + s = '"' + s + '"' + return s + + +delimiters_replacer_regex = re.compile(r'(\\*)([,;]+)') + + +def _EscapeVCProjCommandLineArgListItem(s): + """Escapes command line arguments for MSVS. + + The VCProj format stores string lists in a single string using commas and + semi-colons as separators, which must be quoted if they are to be + interpreted literally. However, command-line arguments may already have + quotes, and the VCProj parser is ignorant of the backslash escaping + convention used by CommandLineToArgv, so the command-line quotes and the + VCProj quotes may not be the same quotes. So to store a general + command-line argument in a VCProj list, we need to parse the existing + quoting according to VCProj's convention and quote any delimiters that are + not already quoted by that convention. The quotes that we add will also be + seen by CommandLineToArgv, so if backslashes precede them then we also have + to escape those backslashes according to the CommandLineToArgv + convention. + + Args: + s: the string to be escaped. + Returns: + the escaped string. + """ + + def _Replace(match): + # For a non-literal quote, CommandLineToArgv requires an even number of + # backslashes preceding it, and it produces half as many literal + # backslashes. So we need to produce 2n backslashes. + return 2 * match.group(1) + '"' + match.group(2) + '"' + + segments = s.split('"') + # The unquoted segments are at the even-numbered indices. + for i in range(0, len(segments), 2): + segments[i] = delimiters_replacer_regex.sub(_Replace, segments[i]) + # Concatenate back into a single string + s = '"'.join(segments) + if len(segments) % 2 == 0: + # String ends while still quoted according to VCProj's convention. This + # means the delimiter and the next list item that follow this one in the + # .vcproj file will be misinterpreted as part of this item. There is nothing + # we can do about this. Adding an extra quote would correct the problem in + # the VCProj but cause the same problem on the final command-line. Moving + # the item to the end of the list does works, but that's only possible if + # there's only one such item. Let's just warn the user. + print >> sys.stderr, ('Warning: MSVS may misinterpret the odd number of ' + + 'quotes in ' + s) + return s + + +def _EscapeCppDefineForMSVS(s): + """Escapes a CPP define so that it will reach the compiler unaltered.""" + s = _EscapeEnvironmentVariableExpansion(s) + s = _EscapeCommandLineArgumentForMSVS(s) + s = _EscapeVCProjCommandLineArgListItem(s) + # cl.exe replaces literal # characters with = in preprocesor definitions for + # some reason. Octal-encode to work around that. + s = s.replace('#', '\\%03o' % ord('#')) + return s + + +quote_replacer_regex2 = re.compile(r'(\\+)"') + + +def _EscapeCommandLineArgumentForMSBuild(s): + """Escapes a Windows command-line argument for use by MSBuild.""" + + def _Replace(match): + return (len(match.group(1)) / 2 * 4) * '\\' + '\\"' + + # Escape all quotes so that they are interpreted literally. + s = quote_replacer_regex2.sub(_Replace, s) + return s + + +def _EscapeMSBuildSpecialCharacters(s): + escape_dictionary = { + '%': '%25', + '$': '%24', + '@': '%40', + "'": '%27', + ';': '%3B', + '?': '%3F', + '*': '%2A' + } + result = ''.join([escape_dictionary.get(c, c) for c in s]) + return result + + +def _EscapeCppDefineForMSBuild(s): + """Escapes a CPP define so that it will reach the compiler unaltered.""" + s = _EscapeEnvironmentVariableExpansion(s) + s = _EscapeCommandLineArgumentForMSBuild(s) + s = _EscapeMSBuildSpecialCharacters(s) + # cl.exe replaces literal # characters with = in preprocesor definitions for + # some reason. Octal-encode to work around that. + s = s.replace('#', '\\%03o' % ord('#')) + return s + + +def _GenerateRulesForMSVS(p, output_dir, options, spec, + sources, excluded_sources, + actions_to_add): + """Generate all the rules for a particular project. + + Arguments: + p: the project + output_dir: directory to emit rules to + options: global options passed to the generator + spec: the specification for this project + sources: the set of all known source files in this project + excluded_sources: the set of sources excluded from normal processing + actions_to_add: deferred list of actions to add in + """ + rules = spec.get('rules', []) + rules_native = [r for r in rules if not int(r.get('msvs_external_rule', 0))] + rules_external = [r for r in rules if int(r.get('msvs_external_rule', 0))] + + # Handle rules that use a native rules file. + if rules_native: + _GenerateNativeRulesForMSVS(p, rules_native, output_dir, spec, options) + + # Handle external rules (non-native rules). + if rules_external: + _GenerateExternalRules(rules_external, output_dir, spec, + sources, options, actions_to_add) + _AdjustSourcesForRules(rules, sources, excluded_sources, False) + + +def _AdjustSourcesForRules(rules, sources, excluded_sources, is_msbuild): + # Add outputs generated by each rule (if applicable). + for rule in rules: + # Add in the outputs from this rule. + trigger_files = _FindRuleTriggerFiles(rule, sources) + for trigger_file in trigger_files: + # Remove trigger_file from excluded_sources to let the rule be triggered + # (e.g. rule trigger ax_enums.idl is added to excluded_sources + # because it's also in an action's inputs in the same project) + excluded_sources.discard(_FixPath(trigger_file)) + # Done if not processing outputs as sources. + if int(rule.get('process_outputs_as_sources', False)): + inputs, outputs = _RuleInputsAndOutputs(rule, trigger_file) + inputs = OrderedSet(_FixPaths(inputs)) + outputs = OrderedSet(_FixPaths(outputs)) + inputs.remove(_FixPath(trigger_file)) + sources.update(inputs) + if not is_msbuild: + excluded_sources.update(inputs) + sources.update(outputs) + + +def _FilterActionsFromExcluded(excluded_sources, actions_to_add): + """Take inputs with actions attached out of the list of exclusions. + + Arguments: + excluded_sources: list of source files not to be built. + actions_to_add: dict of actions keyed on source file they're attached to. + Returns: + excluded_sources with files that have actions attached removed. + """ + must_keep = OrderedSet(_FixPaths(actions_to_add.keys())) + return [s for s in excluded_sources if s not in must_keep] + + +def _GetDefaultConfiguration(spec): + return spec['configurations'][spec['default_configuration']] + + +def _GetGuidOfProject(proj_path, spec): + """Get the guid for the project. + + Arguments: + proj_path: Path of the vcproj or vcxproj file to generate. + spec: The target dictionary containing the properties of the target. + Returns: + the guid. + Raises: + ValueError: if the specified GUID is invalid. + """ + # Pluck out the default configuration. + default_config = _GetDefaultConfiguration(spec) + # Decide the guid of the project. + guid = default_config.get('msvs_guid') + if guid: + if VALID_MSVS_GUID_CHARS.match(guid) is None: + raise ValueError('Invalid MSVS guid: "%s". Must match regex: "%s".' % + (guid, VALID_MSVS_GUID_CHARS.pattern)) + guid = '{%s}' % guid + guid = guid or MSVSNew.MakeGuid(proj_path) + return guid + + +def _GetMsbuildToolsetOfProject(proj_path, spec, version): + """Get the platform toolset for the project. + + Arguments: + proj_path: Path of the vcproj or vcxproj file to generate. + spec: The target dictionary containing the properties of the target. + version: The MSVSVersion object. + Returns: + the platform toolset string or None. + """ + # Pluck out the default configuration. + default_config = _GetDefaultConfiguration(spec) + toolset = default_config.get('msbuild_toolset') + if not toolset and version.DefaultToolset(): + toolset = version.DefaultToolset() + return toolset + + +def _GenerateProject(project, options, version, generator_flags): + """Generates a vcproj file. + + Arguments: + project: the MSVSProject object. + options: global generator options. + version: the MSVSVersion object. + generator_flags: dict of generator-specific flags. + Returns: + A list of source files that cannot be found on disk. + """ + default_config = _GetDefaultConfiguration(project.spec) + + # Skip emitting anything if told to with msvs_existing_vcproj option. + if default_config.get('msvs_existing_vcproj'): + return [] + + if version.UsesVcxproj(): + return _GenerateMSBuildProject(project, options, version, generator_flags) + else: + return _GenerateMSVSProject(project, options, version, generator_flags) + + +# TODO: Avoid code duplication with _ValidateSourcesForOSX in make.py. +def _ValidateSourcesForMSVSProject(spec, version): + """Makes sure if duplicate basenames are not specified in the source list. + + Arguments: + spec: The target dictionary containing the properties of the target. + version: The VisualStudioVersion object. + """ + # This validation should not be applied to MSVC2010 and later. + assert not version.UsesVcxproj() + + # TODO: Check if MSVC allows this for loadable_module targets. + if spec.get('type', None) not in ('static_library', 'shared_library'): + return + sources = spec.get('sources', []) + basenames = {} + for source in sources: + name, ext = os.path.splitext(source) + is_compiled_file = ext in [ + '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S'] + if not is_compiled_file: + continue + basename = os.path.basename(name) # Don't include extension. + basenames.setdefault(basename, []).append(source) + + error = '' + for basename, files in basenames.iteritems(): + if len(files) > 1: + error += ' %s: %s\n' % (basename, ' '.join(files)) + + if error: + print('static library %s has several files with the same basename:\n' % + spec['target_name'] + error + 'MSVC08 cannot handle that.') + raise GypError('Duplicate basenames in sources section, see list above') + + +def _GenerateMSVSProject(project, options, version, generator_flags): + """Generates a .vcproj file. It may create .rules and .user files too. + + Arguments: + project: The project object we will generate the file for. + options: Global options passed to the generator. + version: The VisualStudioVersion object. + generator_flags: dict of generator-specific flags. + """ + spec = project.spec + gyp.common.EnsureDirExists(project.path) + + platforms = _GetUniquePlatforms(spec) + p = MSVSProject.Writer(project.path, version, spec['target_name'], + project.guid, platforms) + + # Get directory project file is in. + project_dir = os.path.split(project.path)[0] + gyp_path = _NormalizedSource(project.build_file) + relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, project_dir) + + config_type = _GetMSVSConfigurationType(spec, project.build_file) + for config_name, config in spec['configurations'].iteritems(): + _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config) + + # MSVC08 and prior version cannot handle duplicate basenames in the same + # target. + # TODO: Take excluded sources into consideration if possible. + _ValidateSourcesForMSVSProject(spec, version) + + # Prepare list of sources and excluded sources. + gyp_file = os.path.split(project.build_file)[1] + sources, excluded_sources = _PrepareListOfSources(spec, generator_flags, + gyp_file) + + # Add rules. + actions_to_add = {} + _GenerateRulesForMSVS(p, project_dir, options, spec, + sources, excluded_sources, + 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, version)) + + # Add in files. + missing_sources = _VerifySourcesExist(sources, project_dir) + p.AddFiles(sources) + + _AddToolFilesToMSVS(p, spec) + _HandlePreCompiledHeaders(p, sources, spec) + _AddActions(actions_to_add, spec, relative_path_of_gyp_file) + _AddCopies(actions_to_add, spec) + _WriteMSVSUserFile(project.path, version, spec) + + # NOTE: this stanza must appear after all actions have been decided. + # Don't excluded sources with actions attached, or they won't run. + excluded_sources = _FilterActionsFromExcluded( + excluded_sources, actions_to_add) + _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl, + list_excluded) + _AddAccumulatedActionsToMSVS(p, spec, actions_to_add) + + # Write it out. + p.WriteIfChanged() + + return missing_sources + + +def _GetUniquePlatforms(spec): + """Returns the list of unique platforms for this spec, e.g ['win32', ...]. + + Arguments: + spec: The target dictionary containing the properties of the target. + Returns: + The MSVSUserFile object created. + """ + # Gather list of unique platforms. + platforms = OrderedSet() + for configuration in spec['configurations']: + platforms.add(_ConfigPlatform(spec['configurations'][configuration])) + platforms = list(platforms) + return platforms + + +def _CreateMSVSUserFile(proj_path, version, spec): + """Generates a .user file for the user running this Gyp program. + + Arguments: + proj_path: The path of the project file being created. The .user file + shares the same path (with an appropriate suffix). + version: The VisualStudioVersion object. + spec: The target dictionary containing the properties of the target. + Returns: + The MSVSUserFile object created. + """ + (domain, username) = _GetDomainAndUserName() + vcuser_filename = '.'.join([proj_path, domain, username, 'user']) + user_file = MSVSUserFile.Writer(vcuser_filename, version, + spec['target_name']) + return user_file + + +def _GetMSVSConfigurationType(spec, build_file): + """Returns the configuration type for this project. + + It's a number defined by Microsoft. May raise an exception. + + Args: + spec: The target dictionary containing the properties of the target. + build_file: The path of the gyp file. + Returns: + An integer, the configuration type. + """ + try: + config_type = { + 'executable': '1', # .exe + 'shared_library': '2', # .dll + 'loadable_module': '2', # .dll + 'static_library': '4', # .lib + 'none': '10', # Utility type + }[spec['type']] + except KeyError: + if spec.get('type'): + raise GypError('Target type %s is not a valid target type for ' + 'target %s in %s.' % + (spec['type'], spec['target_name'], build_file)) + else: + raise GypError('Missing type field for target %s in %s.' % + (spec['target_name'], build_file)) + return config_type + + +def _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config): + """Adds a configuration to the MSVS project. + + Many settings in a vcproj file are specific to a configuration. This + function the main part of the vcproj file that's configuration specific. + + Arguments: + p: The target project being generated. + spec: The target dictionary containing the properties of the target. + config_type: The configuration type, a number as defined by Microsoft. + config_name: The name of the configuration. + config: The dictionary that defines the special processing to be done + for this configuration. + """ + # Get the information for this configuration + include_dirs, midl_include_dirs, resource_include_dirs = \ + _GetIncludeDirs(config) + libraries = _GetLibraries(spec) + library_dirs = _GetLibraryDirs(config) + out_file, vc_tool, _ = _GetOutputFilePathAndTool(spec, msbuild=False) + defines = _GetDefines(config) + defines = [_EscapeCppDefineForMSVS(d) for d in defines] + disabled_warnings = _GetDisabledWarnings(config) + prebuild = config.get('msvs_prebuild') + postbuild = config.get('msvs_postbuild') + def_file = _GetModuleDefinition(spec) + precompiled_header = config.get('msvs_precompiled_header') + + # Prepare the list of tools as a dictionary. + tools = dict() + # Add in user specified msvs_settings. + msvs_settings = config.get('msvs_settings', {}) + MSVSSettings.ValidateMSVSSettings(msvs_settings) + + # Prevent default library inheritance from the environment. + _ToolAppend(tools, 'VCLinkerTool', 'AdditionalDependencies', ['$(NOINHERIT)']) + + for tool in msvs_settings: + settings = config['msvs_settings'][tool] + for setting in settings: + _ToolAppend(tools, tool, setting, settings[setting]) + # Add the information to the appropriate tool + _ToolAppend(tools, 'VCCLCompilerTool', + 'AdditionalIncludeDirectories', include_dirs) + _ToolAppend(tools, 'VCMIDLTool', + 'AdditionalIncludeDirectories', midl_include_dirs) + _ToolAppend(tools, 'VCResourceCompilerTool', + 'AdditionalIncludeDirectories', resource_include_dirs) + # Add in libraries. + _ToolAppend(tools, 'VCLinkerTool', 'AdditionalDependencies', libraries) + _ToolAppend(tools, 'VCLinkerTool', 'AdditionalLibraryDirectories', + library_dirs) + if out_file: + _ToolAppend(tools, vc_tool, 'OutputFile', out_file, only_if_unset=True) + # Add defines. + _ToolAppend(tools, 'VCCLCompilerTool', 'PreprocessorDefinitions', defines) + _ToolAppend(tools, 'VCResourceCompilerTool', 'PreprocessorDefinitions', + defines) + # Change program database directory to prevent collisions. + _ToolAppend(tools, 'VCCLCompilerTool', 'ProgramDataBaseFileName', + '$(IntDir)$(ProjectName)\\vc80.pdb', only_if_unset=True) + # Add disabled warnings. + _ToolAppend(tools, 'VCCLCompilerTool', + 'DisableSpecificWarnings', disabled_warnings) + # Add Pre-build. + _ToolAppend(tools, 'VCPreBuildEventTool', 'CommandLine', prebuild) + # Add Post-build. + _ToolAppend(tools, 'VCPostBuildEventTool', 'CommandLine', postbuild) + # Turn on precompiled headers if appropriate. + if precompiled_header: + precompiled_header = os.path.split(precompiled_header)[1] + _ToolAppend(tools, 'VCCLCompilerTool', 'UsePrecompiledHeader', '2') + _ToolAppend(tools, 'VCCLCompilerTool', + 'PrecompiledHeaderThrough', precompiled_header) + _ToolAppend(tools, 'VCCLCompilerTool', + 'ForcedIncludeFiles', precompiled_header) + # Loadable modules don't generate import libraries; + # tell dependent projects to not expect one. + if spec['type'] == 'loadable_module': + _ToolAppend(tools, 'VCLinkerTool', 'IgnoreImportLibrary', 'true') + # Set the module definition file if any. + if def_file: + _ToolAppend(tools, 'VCLinkerTool', 'ModuleDefinitionFile', def_file) + + _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name) + + +def _GetIncludeDirs(config): + """Returns the list of directories to be used for #include directives. + + Arguments: + config: The dictionary that defines the special processing to be done + for this configuration. + Returns: + The list of directory paths. + """ + # TODO(bradnelson): include_dirs should really be flexible enough not to + # require this sort of thing. + include_dirs = ( + config.get('include_dirs', []) + + config.get('msvs_system_include_dirs', [])) + midl_include_dirs = ( + config.get('midl_include_dirs', []) + + config.get('msvs_system_include_dirs', [])) + resource_include_dirs = config.get('resource_include_dirs', include_dirs) + include_dirs = _FixPaths(include_dirs) + midl_include_dirs = _FixPaths(midl_include_dirs) + resource_include_dirs = _FixPaths(resource_include_dirs) + return include_dirs, midl_include_dirs, resource_include_dirs + + +def _GetLibraryDirs(config): + """Returns the list of directories to be used for library search paths. + + Arguments: + config: The dictionary that defines the special processing to be done + for this configuration. + Returns: + The list of directory paths. + """ + + library_dirs = config.get('library_dirs', []) + library_dirs = _FixPaths(library_dirs) + return library_dirs + + +def _GetLibraries(spec): + """Returns the list of libraries for this configuration. + + Arguments: + spec: The target dictionary containing the properties of the target. + Returns: + The list of directory paths. + """ + libraries = spec.get('libraries', []) + # Strip out -l, as it is not used on windows (but is needed so we can pass + # 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 = OrderedSet() + unique_libraries_list = [] + for entry in reversed(libraries): + library = re.sub(r'^\-l', '', entry) + if not os.path.splitext(library)[1]: + library += '.lib' + if library not in found: + found.add(library) + unique_libraries_list.append(library) + unique_libraries_list.reverse() + return unique_libraries_list + + +def _GetOutputFilePathAndTool(spec, msbuild): + """Returns the path and tool to use for this target. + + Figures out the path of the file this spec will create and the name of + the VC tool that will create it. + + Arguments: + spec: The target dictionary containing the properties of the target. + Returns: + A triple of (file path, name of the vc tool, name of the msbuild tool) + """ + # Select a name for the output file. + out_file = '' + vc_tool = '' + msbuild_tool = '' + output_file_map = { + 'executable': ('VCLinkerTool', 'Link', '$(OutDir)', '.exe'), + 'shared_library': ('VCLinkerTool', 'Link', '$(OutDir)', '.dll'), + 'loadable_module': ('VCLinkerTool', 'Link', '$(OutDir)', '.dll'), + 'static_library': ('VCLibrarianTool', 'Lib', '$(OutDir)lib\\', '.lib'), + } + output_file_props = output_file_map.get(spec['type']) + if output_file_props and int(spec.get('msvs_auto_output_file', 1)): + vc_tool, msbuild_tool, out_dir, suffix = output_file_props + if spec.get('standalone_static_library', 0): + out_dir = '$(OutDir)' + out_dir = spec.get('product_dir', out_dir) + product_extension = spec.get('product_extension') + if product_extension: + suffix = '.' + product_extension + elif msbuild: + suffix = '$(TargetExt)' + prefix = spec.get('product_prefix', '') + product_name = spec.get('product_name', '$(ProjectName)') + out_file = ntpath.join(out_dir, prefix + product_name + suffix) + return out_file, vc_tool, msbuild_tool + + +def _GetOutputTargetExt(spec): + """Returns the extension for this target, including the dot + + If product_extension is specified, set target_extension to this to avoid + MSB8012, returns None otherwise. Ignores any target_extension settings in + the input files. + + Arguments: + spec: The target dictionary containing the properties of the target. + Returns: + A string with the extension, or None + """ + target_extension = spec.get('product_extension') + if target_extension: + return '.' + target_extension + return None + + +def _GetDefines(config): + """Returns the list of preprocessor definitions for this configuation. + + Arguments: + config: The dictionary that defines the special processing to be done + for this configuration. + Returns: + The list of preprocessor definitions. + """ + defines = [] + for d in config.get('defines', []): + if type(d) == list: + fd = '='.join([str(dpart) for dpart in d]) + else: + fd = str(d) + defines.append(fd) + return defines + + +def _GetDisabledWarnings(config): + return [str(i) for i in config.get('msvs_disabled_warnings', [])] + + +def _GetModuleDefinition(spec): + def_file = '' + if spec['type'] in ['shared_library', 'loadable_module', 'executable']: + def_files = [s for s in spec.get('sources', []) if s.endswith('.def')] + if len(def_files) == 1: + def_file = _FixPath(def_files[0]) + elif def_files: + raise ValueError( + 'Multiple module definition files in one target, target %s lists ' + 'multiple .def files: %s' % ( + spec['target_name'], ' '.join(def_files))) + return def_file + + +def _ConvertToolsToExpectedForm(tools): + """Convert tools to a form expected by Visual Studio. + + Arguments: + tools: A dictionary of settings; the tool name is the key. + Returns: + A list of Tool objects. + """ + tool_list = [] + for tool, settings in tools.iteritems(): + # Collapse settings with lists. + settings_fixed = {} + for setting, value in settings.iteritems(): + if type(value) == list: + if ((tool == 'VCLinkerTool' and + setting == 'AdditionalDependencies') or + setting == 'AdditionalOptions'): + settings_fixed[setting] = ' '.join(value) + else: + settings_fixed[setting] = ';'.join(value) + else: + settings_fixed[setting] = value + # Add in this tool. + tool_list.append(MSVSProject.Tool(tool, settings_fixed)) + return tool_list + + +def _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name): + """Add to the project file the configuration specified by config. + + Arguments: + p: The target project being generated. + spec: the target project dict. + tools: A dictionary of settings; the tool name is the key. + config: The dictionary that defines the special processing to be done + for this configuration. + config_type: The configuration type, a number as defined by Microsoft. + config_name: The name of the configuration. + """ + attributes = _GetMSVSAttributes(spec, config, config_type) + # Add in this configuration. + tool_list = _ConvertToolsToExpectedForm(tools) + p.AddConfig(_ConfigFullName(config_name, config), + attrs=attributes, tools=tool_list) + + +def _GetMSVSAttributes(spec, config, config_type): + # Prepare configuration attributes. + prepared_attrs = {} + source_attrs = config.get('msvs_configuration_attributes', {}) + for a in source_attrs: + prepared_attrs[a] = source_attrs[a] + # Add props files. + vsprops_dirs = config.get('msvs_props', []) + vsprops_dirs = _FixPaths(vsprops_dirs) + if vsprops_dirs: + prepared_attrs['InheritedPropertySheets'] = ';'.join(vsprops_dirs) + # Set configuration type. + prepared_attrs['ConfigurationType'] = config_type + output_dir = prepared_attrs.get('OutputDirectory', + '$(SolutionDir)$(ConfigurationName)') + prepared_attrs['OutputDirectory'] = _FixPath(output_dir) + '\\' + if 'IntermediateDirectory' not in prepared_attrs: + intermediate = '$(ConfigurationName)\\obj\\$(ProjectName)' + prepared_attrs['IntermediateDirectory'] = _FixPath(intermediate) + '\\' + else: + intermediate = _FixPath(prepared_attrs['IntermediateDirectory']) + '\\' + intermediate = MSVSSettings.FixVCMacroSlashes(intermediate) + prepared_attrs['IntermediateDirectory'] = intermediate + return prepared_attrs + + +def _AddNormalizedSources(sources_set, sources_array): + sources_set.update(_NormalizedSource(s) for s in sources_array) + + +def _PrepareListOfSources(spec, generator_flags, gyp_file): + """Prepare list of sources and excluded sources. + + Besides the sources specified directly in the spec, adds the gyp file so + that a change to it will cause a re-compile. Also adds appropriate sources + for actions and copies. Assumes later stage will un-exclude files which + have custom build steps attached. + + Arguments: + spec: The target dictionary containing the properties of the target. + gyp_file: The name of the gyp file. + Returns: + A pair of (list of sources, list of excluded sources). + The sources will be relative to the gyp file. + """ + sources = OrderedSet() + _AddNormalizedSources(sources, spec.get('sources', [])) + excluded_sources = OrderedSet() + # Add in the gyp file. + if not generator_flags.get('standalone'): + sources.add(gyp_file) + + # Add in 'action' inputs and outputs. + for a in spec.get('actions', []): + inputs = a['inputs'] + inputs = [_NormalizedSource(i) for i in inputs] + # Add all inputs to sources and excluded sources. + inputs = OrderedSet(inputs) + sources.update(inputs) + if not spec.get('msvs_external_builder'): + excluded_sources.update(inputs) + if int(a.get('process_outputs_as_sources', False)): + _AddNormalizedSources(sources, a.get('outputs', [])) + # Add in 'copies' inputs and outputs. + for cpy in spec.get('copies', []): + _AddNormalizedSources(sources, cpy.get('files', [])) + return (sources, excluded_sources) + + +def _AdjustSourcesAndConvertToFilterHierarchy( + spec, options, gyp_dir, sources, excluded_sources, list_excluded, version): + """Adjusts the list of sources and excluded sources. + + Also converts the sets to lists. + + Arguments: + spec: The target dictionary containing the properties of the target. + options: Global generator options. + 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(OrderedSet(spec.get('sources_excluded', []))) + # Add excluded sources into sources for good measure. + sources.update(excluded_sources) + # Convert to proper windows form. + # NOTE: sources goes from being a set to a list here. + # NOTE: excluded_sources goes from being a set to a list here. + sources = _FixPaths(sources) + # Convert to proper windows form. + excluded_sources = _FixPaths(excluded_sources) + + excluded_idl = _IdlFilesHandledNonNatively(spec, sources) + + precompiled_related = _GetPrecompileRelatedFiles(spec) + # Find the excluded ones, minus the precompiled header related ones. + fully_excluded = [i for i in excluded_sources if i not in precompiled_related] + + # Convert to folders and the right slashes. + sources = [i.split('\\') for i in sources] + sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_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. + if version.UsesVcxproj(): + while all([isinstance(s, MSVSProject.Filter) for s in sources]) \ + and len(set([s.name for s in sources])) == 1: + assert all([len(s.contents) == 1 for s in sources]) + sources = [s.contents[0] for s in sources] + else: + while len(sources) == 1 and isinstance(sources[0], MSVSProject.Filter): + sources = sources[0].contents + + return sources, excluded_sources, excluded_idl + + +def _IdlFilesHandledNonNatively(spec, sources): + # If any non-native rules use 'idl' as an extension exclude idl files. + # Gather a list here to use later. + using_idl = False + for rule in spec.get('rules', []): + if rule['extension'] == 'idl' and int(rule.get('msvs_external_rule', 0)): + using_idl = True + break + if using_idl: + excluded_idl = [i for i in sources if i.endswith('.idl')] + else: + excluded_idl = [] + return excluded_idl + + +def _GetPrecompileRelatedFiles(spec): + # Gather a list of precompiled header related sources. + precompiled_related = [] + for _, config in spec['configurations'].iteritems(): + for k in precomp_keys: + f = config.get(k) + if f: + precompiled_related.append(_FixPath(f)) + return precompiled_related + + +def _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl, + list_excluded): + exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl) + for file_name, excluded_configs in exclusions.iteritems(): + if (not list_excluded and + len(excluded_configs) == len(spec['configurations'])): + # If we're not listing excluded files, then they won't appear in the + # project, so don't try to configure them to be excluded. + pass + else: + for config_name, config in excluded_configs: + p.AddFileConfig(file_name, _ConfigFullName(config_name, config), + {'ExcludedFromBuild': 'true'}) + + +def _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl): + exclusions = {} + # Exclude excluded sources from being built. + for f in excluded_sources: + excluded_configs = [] + for config_name, config in spec['configurations'].iteritems(): + precomped = [_FixPath(config.get(i, '')) for i in precomp_keys] + # Don't do this for ones that are precompiled header related. + if f not in precomped: + excluded_configs.append((config_name, config)) + exclusions[f] = excluded_configs + # If any non-native rules use 'idl' as an extension exclude idl files. + # Exclude them now. + for f in excluded_idl: + excluded_configs = [] + for config_name, config in spec['configurations'].iteritems(): + excluded_configs.append((config_name, config)) + exclusions[f] = excluded_configs + return exclusions + + +def _AddToolFilesToMSVS(p, spec): + # Add in tool files (rules). + tool_files = OrderedSet() + for _, config in spec['configurations'].iteritems(): + for f in config.get('msvs_tool_files', []): + tool_files.add(f) + for f in tool_files: + p.AddToolFile(f) + + +def _HandlePreCompiledHeaders(p, sources, spec): + # Pre-compiled header source stubs need a different compiler flag + # (generate precompiled header) and any source file not of the same + # kind (i.e. C vs. C++) as the precompiled header source stub needs + # to have use of precompiled headers disabled. + extensions_excluded_from_precompile = [] + for config_name, config in spec['configurations'].iteritems(): + source = config.get('msvs_precompiled_source') + if source: + source = _FixPath(source) + # UsePrecompiledHeader=1 for if using precompiled headers. + tool = MSVSProject.Tool('VCCLCompilerTool', + {'UsePrecompiledHeader': '1'}) + p.AddFileConfig(source, _ConfigFullName(config_name, config), + {}, tools=[tool]) + basename, extension = os.path.splitext(source) + if extension == '.c': + extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx'] + else: + extensions_excluded_from_precompile = ['.c'] + def DisableForSourceTree(source_tree): + for source in source_tree: + if isinstance(source, MSVSProject.Filter): + DisableForSourceTree(source.contents) + else: + basename, extension = os.path.splitext(source) + if extension in extensions_excluded_from_precompile: + for config_name, config in spec['configurations'].iteritems(): + tool = MSVSProject.Tool('VCCLCompilerTool', + {'UsePrecompiledHeader': '0', + 'ForcedIncludeFiles': '$(NOINHERIT)'}) + p.AddFileConfig(_FixPath(source), + _ConfigFullName(config_name, config), + {}, tools=[tool]) + # Do nothing if there was no precompiled source. + if extensions_excluded_from_precompile: + DisableForSourceTree(sources) + + +def _AddActions(actions_to_add, spec, relative_path_of_gyp_file): + # Add actions. + actions = spec.get('actions', []) + # Don't setup_env every time. When all the actions are run together in one + # batch file in VS, the PATH will grow too long. + # Membership in this set means that the cygwin environment has been set up, + # and does not need to be set up again. + have_setup_env = set() + for a in actions: + # Attach actions to the gyp file if nothing else is there. + inputs = a.get('inputs') or [relative_path_of_gyp_file] + attached_to = inputs[0] + need_setup_env = attached_to not in have_setup_env + cmd = _BuildCommandLineForRule(spec, a, has_input_path=False, + do_setup_env=need_setup_env) + have_setup_env.add(attached_to) + # Add the action. + _AddActionStep(actions_to_add, + inputs=inputs, + outputs=a.get('outputs', []), + description=a.get('message', a['action_name']), + command=cmd) + + +def _WriteMSVSUserFile(project_path, version, spec): + # Add run_as and test targets. + if 'run_as' in spec: + run_as = spec['run_as'] + action = run_as.get('action', []) + environment = run_as.get('environment', []) + working_directory = run_as.get('working_directory', '.') + elif int(spec.get('test', 0)): + action = ['$(TargetPath)', '--gtest_print_time'] + environment = [] + working_directory = '.' + else: + return # Nothing to add + # Write out the user file. + user_file = _CreateMSVSUserFile(project_path, version, spec) + for config_name, c_data in spec['configurations'].iteritems(): + user_file.AddDebugSettings(_ConfigFullName(config_name, c_data), + action, environment, working_directory) + user_file.WriteIfChanged() + + +def _AddCopies(actions_to_add, spec): + copies = _GetCopies(spec) + for inputs, outputs, cmd, description in copies: + _AddActionStep(actions_to_add, inputs=inputs, outputs=outputs, + description=description, command=cmd) + + +def _GetCopies(spec): + copies = [] + # Add copies. + for cpy in spec.get('copies', []): + for src in cpy.get('files', []): + dst = os.path.join(cpy['destination'], os.path.basename(src)) + # _AddCustomBuildToolForMSVS() will call _FixPath() on the inputs and + # outputs, so do the same for our generated command line. + if src.endswith('/'): + src_bare = src[:-1] + base_dir = posixpath.split(src_bare)[0] + outer_dir = posixpath.split(src_bare)[1] + cmd = 'cd "%s" && xcopy /e /f /y "%s" "%s\\%s\\"' % ( + _FixPath(base_dir), outer_dir, _FixPath(dst), outer_dir) + copies.append(([src], ['dummy_copies', dst], cmd, + 'Copying %s to %s' % (src, dst))) + else: + cmd = 'mkdir "%s" 2>nul & set ERRORLEVEL=0 & copy /Y "%s" "%s"' % ( + _FixPath(cpy['destination']), _FixPath(src), _FixPath(dst)) + copies.append(([src], [dst], cmd, 'Copying %s to %s' % (src, dst))) + return copies + + +def _GetPathDict(root, path): + # |path| will eventually be empty (in the recursive calls) if it was initially + # relative; otherwise it will eventually end up as '\', 'D:\', etc. + if not path or path.endswith(os.sep): + return root + parent, folder = os.path.split(path) + parent_dict = _GetPathDict(root, parent) + if folder not in parent_dict: + parent_dict[folder] = dict() + return parent_dict[folder] + + +def _DictsToFolders(base_path, bucket, flat): + # Convert to folders recursively. + children = [] + for folder, contents in bucket.iteritems(): + if type(contents) == dict: + folder_children = _DictsToFolders(os.path.join(base_path, folder), + contents, flat) + if flat: + children += folder_children + else: + folder_children = MSVSNew.MSVSFolder(os.path.join(base_path, folder), + name='(' + folder + ')', + entries=folder_children) + children.append(folder_children) + else: + children.append(contents) + return children + + +def _CollapseSingles(parent, node): + # Recursively explorer the tree of dicts looking for projects which are + # the sole item in a folder which has the same name as the project. Bring + # such projects up one level. + if (type(node) == dict and + len(node) == 1 and + node.keys()[0] == parent + '.vcproj'): + return node[node.keys()[0]] + if type(node) != dict: + return node + for child in node: + node[child] = _CollapseSingles(child, node[child]) + return node + + +def _GatherSolutionFolders(sln_projects, project_objects, flat): + root = {} + # Convert into a tree of dicts on path. + for p in sln_projects: + gyp_file, target = gyp.common.ParseQualifiedTarget(p)[0:2] + gyp_dir = os.path.dirname(gyp_file) + path_dict = _GetPathDict(root, gyp_dir) + path_dict[target + '.vcproj'] = project_objects[p] + # Walk down from the top until we hit a folder that has more than one entry. + # In practice, this strips the top-level "src/" dir from the hierarchy in + # the solution. + while len(root) == 1 and type(root[root.keys()[0]]) == dict: + root = root[root.keys()[0]] + # Collapse singles. + root = _CollapseSingles('', root) + # Merge buckets until everything is a root entry. + return _DictsToFolders('', root, flat) + + +def _GetPathOfProject(qualified_target, spec, options, msvs_version): + default_config = _GetDefaultConfiguration(spec) + proj_filename = default_config.get('msvs_existing_vcproj') + if not proj_filename: + proj_filename = (spec['target_name'] + options.suffix + + msvs_version.ProjectExtension()) + + build_file = gyp.common.BuildFile(qualified_target) + proj_path = os.path.join(os.path.dirname(build_file), proj_filename) + fix_prefix = None + if options.generator_output: + project_dir_path = os.path.dirname(os.path.abspath(proj_path)) + proj_path = os.path.join(options.generator_output, proj_path) + fix_prefix = gyp.common.RelativePath(project_dir_path, + os.path.dirname(proj_path)) + return proj_path, fix_prefix + + +def _GetPlatformOverridesOfProject(spec): + # Prepare a dict indicating which project configurations are used for which + # solution configurations for this target. + config_platform_overrides = {} + for config_name, c in spec['configurations'].iteritems(): + config_fullname = _ConfigFullName(config_name, c) + platform = c.get('msvs_target_platform', _ConfigPlatform(c)) + fixed_config_fullname = '%s|%s' % ( + _ConfigBaseName(config_name, _ConfigPlatform(c)), platform) + config_platform_overrides[config_fullname] = fixed_config_fullname + return config_platform_overrides + + +def _CreateProjectObjects(target_list, target_dicts, options, msvs_version): + """Create a MSVSProject object for the targets found in target list. + + Arguments: + target_list: the list of targets to generate project objects for. + target_dicts: the dictionary of specifications. + options: global generator options. + msvs_version: the MSVSVersion object. + Returns: + A set of created projects, keyed by target. + """ + global fixpath_prefix + # Generate each project. + projects = {} + for qualified_target in target_list: + spec = target_dicts[qualified_target] + if spec['toolset'] != 'target': + raise GypError( + 'Multiple toolsets not supported in msvs build (target %s)' % + qualified_target) + proj_path, fixpath_prefix = _GetPathOfProject(qualified_target, spec, + options, msvs_version) + guid = _GetGuidOfProject(proj_path, spec) + overrides = _GetPlatformOverridesOfProject(spec) + build_file = gyp.common.BuildFile(qualified_target) + # Create object for this project. + obj = MSVSNew.MSVSProject( + proj_path, + name=spec['target_name'], + guid=guid, + spec=spec, + build_file=build_file, + config_platform_overrides=overrides, + fixpath_prefix=fixpath_prefix) + # Set project toolset if any (MS build only) + if msvs_version.UsesVcxproj(): + obj.set_msbuild_toolset( + _GetMsbuildToolsetOfProject(proj_path, spec, msvs_version)) + projects[qualified_target] = obj + # Set all the dependencies, but not if we are using an external builder like + # ninja + for project in projects.values(): + if not project.spec.get('msvs_external_builder'): + deps = project.spec.get('dependencies', []) + deps = [projects[d] for d in deps] + project.set_dependencies(deps) + return projects + + +def _InitNinjaFlavor(params, target_list, target_dicts): + """Initialize targets for the ninja flavor. + + This sets up the necessary variables in the targets to generate msvs projects + that use ninja as an external builder. The variables in the spec are only set + if they have not been set. This allows individual specs to override the + default values initialized here. + Arguments: + params: Params provided to the generator. + target_list: List of target pairs: 'base/base.gyp:base'. + target_dicts: Dict of target properties keyed on target pair. + """ + for qualified_target in target_list: + spec = target_dicts[qualified_target] + if spec.get('msvs_external_builder'): + # The spec explicitly defined an external builder, so don't change it. + continue + + path_to_ninja = spec.get('msvs_path_to_ninja', 'ninja.exe') + + spec['msvs_external_builder'] = 'ninja' + if not spec.get('msvs_external_builder_out_dir'): + gyp_file, _, _ = gyp.common.ParseQualifiedTarget(qualified_target) + gyp_dir = os.path.dirname(gyp_file) + configuration = '$(Configuration)' + if params.get('target_arch') == 'x64': + configuration += '_x64' + spec['msvs_external_builder_out_dir'] = os.path.join( + gyp.common.RelativePath(params['options'].toplevel_dir, gyp_dir), + ninja_generator.ComputeOutputDir(params), + configuration) + if not spec.get('msvs_external_builder_build_cmd'): + spec['msvs_external_builder_build_cmd'] = [ + path_to_ninja, + '-C', + '$(OutDir)', + '$(ProjectName)', + ] + if not spec.get('msvs_external_builder_clean_cmd'): + spec['msvs_external_builder_clean_cmd'] = [ + path_to_ninja, + '-C', + '$(OutDir)', + '-tclean', + '$(ProjectName)', + ] + + +def CalculateVariables(default_variables, params): + """Generated variables that require params to be known.""" + + generator_flags = params.get('generator_flags', {}) + + # Select project file format version (if unset, default to auto detecting). + msvs_version = MSVSVersion.SelectVisualStudioVersion( + generator_flags.get('msvs_version', 'auto')) + # Stash msvs_version for later (so we don't have to probe the system twice). + params['msvs_version'] = msvs_version + + # Set a variable so conditions can be based on msvs_version. + default_variables['MSVS_VERSION'] = msvs_version.ShortName() + + # To determine processor word size on Windows, in addition to checking + # PROCESSOR_ARCHITECTURE (which reflects the word size of the current + # process), it is also necessary to check PROCESSOR_ARCITEW6432 (which + # contains the actual word size of the system when running thru WOW64). + if (os.environ.get('PROCESSOR_ARCHITECTURE', '').find('64') >= 0 or + os.environ.get('PROCESSOR_ARCHITEW6432', '').find('64') >= 0): + default_variables['MSVS_OS_BITS'] = 64 + else: + default_variables['MSVS_OS_BITS'] = 32 + + if gyp.common.GetFlavor(params) == 'ninja': + default_variables['SHARED_INTERMEDIATE_DIR'] = '$(OutDir)gen' + + +def PerformBuild(data, configurations, params): + options = params['options'] + msvs_version = params['msvs_version'] + devenv = os.path.join(msvs_version.path, 'Common7', 'IDE', 'devenv.com') + + for build_file, build_file_dict in data.iteritems(): + (build_file_root, build_file_ext) = os.path.splitext(build_file) + if build_file_ext != '.gyp': + continue + sln_path = build_file_root + options.suffix + '.sln' + if options.generator_output: + sln_path = os.path.join(options.generator_output, sln_path) + + for config in configurations: + arguments = [devenv, sln_path, '/Build', config] + print 'Building [%s]: %s' % (config, arguments) + rtn = subprocess.check_call(arguments) + + +def GenerateOutput(target_list, target_dicts, data, params): + """Generate .sln and .vcproj files. + + This is the entry point for this generator. + Arguments: + target_list: List of target pairs: 'base/base.gyp:base'. + target_dicts: Dict of target properties keyed on target pair. + data: Dictionary containing per .gyp data. + """ + global fixpath_prefix + + options = params['options'] + + # Get the project file format version back out of where we stashed it in + # GeneratorCalculatedVariables. + msvs_version = params['msvs_version'] + + generator_flags = params.get('generator_flags', {}) + + # Optionally shard targets marked with 'msvs_shard': SHARD_COUNT. + (target_list, target_dicts) = MSVSUtil.ShardTargets(target_list, target_dicts) + + # Optionally use the large PDB workaround for targets marked with + # 'msvs_large_pdb': 1. + (target_list, target_dicts) = MSVSUtil.InsertLargePdbShims( + target_list, target_dicts, generator_default_variables) + + # Optionally configure each spec to use ninja as the external builder. + if params.get('flavor') == 'ninja': + _InitNinjaFlavor(params, target_list, target_dicts) + + # Prepare the set of configurations. + configs = set() + for qualified_target in target_list: + spec = target_dicts[qualified_target] + for config_name, config in spec['configurations'].iteritems(): + configs.add(_ConfigFullName(config_name, config)) + configs = list(configs) + + # Figure out all the projects that will be generated and their guids + project_objects = _CreateProjectObjects(target_list, target_dicts, options, + msvs_version) + + # Generate each project. + missing_sources = [] + for project in project_objects.values(): + fixpath_prefix = project.fixpath_prefix + missing_sources.extend(_GenerateProject(project, options, msvs_version, + generator_flags)) + fixpath_prefix = None + + for build_file in data: + # Validate build_file extension + if not build_file.endswith('.gyp'): + continue + sln_path = os.path.splitext(build_file)[0] + options.suffix + '.sln' + if options.generator_output: + sln_path = os.path.join(options.generator_output, sln_path) + # Get projects in the solution, and their dependents. + sln_projects = gyp.common.BuildFileTargets(target_list, build_file) + sln_projects += gyp.common.DeepDependencyTargets(target_dicts, sln_projects) + # Create folder hierarchy. + root_entries = _GatherSolutionFolders( + sln_projects, project_objects, flat=msvs_version.FlatSolution()) + # Create solution. + sln = MSVSNew.MSVSSolution(sln_path, + entries=root_entries, + variants=configs, + websiteProperties=False, + version=msvs_version) + sln.Write() + + if missing_sources: + error_message = "Missing input files:\n" + \ + '\n'.join(set(missing_sources)) + if generator_flags.get('msvs_error_on_missing_sources', False): + raise GypError(error_message) + else: + print >> sys.stdout, "Warning: " + error_message + + +def _GenerateMSBuildFiltersFile(filters_path, source_files, + rule_dependencies, extension_to_rule_name): + """Generate the filters file. + + This file is used by Visual Studio to organize the presentation of source + files into folders. + + Arguments: + filters_path: The path of the file to be created. + source_files: The hierarchical structure of all the sources. + extension_to_rule_name: A dictionary mapping file extensions to rules. + """ + filter_group = [] + source_group = [] + _AppendFiltersForMSBuild('', source_files, rule_dependencies, + extension_to_rule_name, filter_group, source_group) + if filter_group: + content = ['Project', + {'ToolsVersion': '4.0', + 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003' + }, + ['ItemGroup'] + filter_group, + ['ItemGroup'] + source_group + ] + easy_xml.WriteXmlIfChanged(content, filters_path, pretty=True, win32=True) + elif os.path.exists(filters_path): + # We don't need this filter anymore. Delete the old filter file. + os.unlink(filters_path) + + +def _AppendFiltersForMSBuild(parent_filter_name, sources, rule_dependencies, + extension_to_rule_name, + filter_group, source_group): + """Creates the list of filters and sources to be added in the filter file. + + Args: + parent_filter_name: The name of the filter under which the sources are + found. + sources: The hierarchy of filters and sources to process. + extension_to_rule_name: A dictionary mapping file extensions to rules. + filter_group: The list to which filter entries will be appended. + source_group: The list to which source entries will be appeneded. + """ + for source in sources: + if isinstance(source, MSVSProject.Filter): + # We have a sub-filter. Create the name of that sub-filter. + if not parent_filter_name: + filter_name = source.name + else: + filter_name = '%s\\%s' % (parent_filter_name, source.name) + # Add the filter to the group. + filter_group.append( + ['Filter', {'Include': filter_name}, + ['UniqueIdentifier', MSVSNew.MakeGuid(source.name)]]) + # Recurse and add its dependents. + _AppendFiltersForMSBuild(filter_name, source.contents, + rule_dependencies, extension_to_rule_name, + filter_group, source_group) + else: + # It's a source. Create a source entry. + _, element = _MapFileToMsBuildSourceType(source, rule_dependencies, + extension_to_rule_name) + source_entry = [element, {'Include': source}] + # Specify the filter it is part of, if any. + if parent_filter_name: + source_entry.append(['Filter', parent_filter_name]) + source_group.append(source_entry) + + +def _MapFileToMsBuildSourceType(source, rule_dependencies, + extension_to_rule_name): + """Returns the group and element type of the source file. + + Arguments: + source: The source file name. + extension_to_rule_name: A dictionary mapping file extensions to rules. + + Returns: + A pair of (group this file should be part of, the label of element) + """ + _, ext = os.path.splitext(source) + if ext in extension_to_rule_name: + group = 'rule' + element = extension_to_rule_name[ext] + elif ext in ['.cc', '.cpp', '.c', '.cxx', '.mm']: + group = 'compile' + element = 'ClCompile' + elif ext in ['.h', '.hxx']: + group = 'include' + element = 'ClInclude' + elif ext == '.rc': + group = 'resource' + element = 'ResourceCompile' + elif ext == '.asm': + group = 'masm' + element = 'MASM' + elif ext == '.idl': + group = 'midl' + element = 'Midl' + elif source in rule_dependencies: + group = 'rule_dependency' + element = 'CustomBuild' + else: + group = 'none' + element = 'None' + return (group, element) + + +def _GenerateRulesForMSBuild(output_dir, options, spec, + sources, excluded_sources, + props_files_of_rules, targets_files_of_rules, + actions_to_add, rule_dependencies, + extension_to_rule_name): + # MSBuild rules are implemented using three files: an XML file, a .targets + # file and a .props file. + # See http://blogs.msdn.com/b/vcblog/archive/2010/04/21/quick-help-on-vs2010-custom-build-rule.aspx + # for more details. + rules = spec.get('rules', []) + rules_native = [r for r in rules if not int(r.get('msvs_external_rule', 0))] + rules_external = [r for r in rules if int(r.get('msvs_external_rule', 0))] + + msbuild_rules = [] + for rule in rules_native: + # Skip a rule with no action and no inputs. + if 'action' not in rule and not rule.get('rule_sources', []): + continue + msbuild_rule = MSBuildRule(rule, spec) + msbuild_rules.append(msbuild_rule) + rule_dependencies.update(msbuild_rule.additional_dependencies.split(';')) + extension_to_rule_name[msbuild_rule.extension] = msbuild_rule.rule_name + if msbuild_rules: + base = spec['target_name'] + options.suffix + props_name = base + '.props' + targets_name = base + '.targets' + xml_name = base + '.xml' + + props_files_of_rules.add(props_name) + targets_files_of_rules.add(targets_name) + + props_path = os.path.join(output_dir, props_name) + targets_path = os.path.join(output_dir, targets_name) + xml_path = os.path.join(output_dir, xml_name) + + _GenerateMSBuildRulePropsFile(props_path, msbuild_rules) + _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules) + _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules) + + if rules_external: + _GenerateExternalRules(rules_external, output_dir, spec, + sources, options, actions_to_add) + _AdjustSourcesForRules(rules, sources, excluded_sources, True) + + +class MSBuildRule(object): + """Used to store information used to generate an MSBuild rule. + + Attributes: + rule_name: The rule name, sanitized to use in XML. + target_name: The name of the target. + after_targets: The name of the AfterTargets element. + before_targets: The name of the BeforeTargets element. + depends_on: The name of the DependsOn element. + compute_output: The name of the ComputeOutput element. + dirs_to_make: The name of the DirsToMake element. + inputs: The name of the _inputs element. + tlog: The name of the _tlog element. + extension: The extension this rule applies to. + description: The message displayed when this rule is invoked. + additional_dependencies: A string listing additional dependencies. + outputs: The outputs of this rule. + command: The command used to run the rule. + """ + + def __init__(self, rule, spec): + self.display_name = rule['rule_name'] + # Assure that the rule name is only characters and numbers + self.rule_name = re.sub(r'\W', '_', self.display_name) + # Create the various element names, following the example set by the + # Visual Studio 2008 to 2010 conversion. I don't know if VS2010 + # is sensitive to the exact names. + self.target_name = '_' + self.rule_name + self.after_targets = self.rule_name + 'AfterTargets' + self.before_targets = self.rule_name + 'BeforeTargets' + self.depends_on = self.rule_name + 'DependsOn' + self.compute_output = 'Compute%sOutput' % self.rule_name + self.dirs_to_make = self.rule_name + 'DirsToMake' + self.inputs = self.rule_name + '_inputs' + self.tlog = self.rule_name + '_tlog' + self.extension = rule['extension'] + if not self.extension.startswith('.'): + self.extension = '.' + self.extension + + self.description = MSVSSettings.ConvertVCMacrosToMSBuild( + rule.get('message', self.rule_name)) + old_additional_dependencies = _FixPaths(rule.get('inputs', [])) + self.additional_dependencies = ( + ';'.join([MSVSSettings.ConvertVCMacrosToMSBuild(i) + for i in old_additional_dependencies])) + old_outputs = _FixPaths(rule.get('outputs', [])) + self.outputs = ';'.join([MSVSSettings.ConvertVCMacrosToMSBuild(i) + for i in old_outputs]) + old_command = _BuildCommandLineForRule(spec, rule, has_input_path=True, + do_setup_env=True) + self.command = MSVSSettings.ConvertVCMacrosToMSBuild(old_command) + + +def _GenerateMSBuildRulePropsFile(props_path, msbuild_rules): + """Generate the .props file.""" + content = ['Project', + {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}] + for rule in msbuild_rules: + content.extend([ + ['PropertyGroup', + {'Condition': "'$(%s)' == '' and '$(%s)' == '' and " + "'$(ConfigurationType)' != 'Makefile'" % (rule.before_targets, + rule.after_targets) + }, + [rule.before_targets, 'Midl'], + [rule.after_targets, 'CustomBuild'], + ], + ['PropertyGroup', + [rule.depends_on, + {'Condition': "'$(ConfigurationType)' != 'Makefile'"}, + '_SelectedFiles;$(%s)' % rule.depends_on + ], + ], + ['ItemDefinitionGroup', + [rule.rule_name, + ['CommandLineTemplate', rule.command], + ['Outputs', rule.outputs], + ['ExecutionDescription', rule.description], + ['AdditionalDependencies', rule.additional_dependencies], + ], + ] + ]) + easy_xml.WriteXmlIfChanged(content, props_path, pretty=True, win32=True) + + +def _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules): + """Generate the .targets file.""" + content = ['Project', + {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003' + } + ] + item_group = [ + 'ItemGroup', + ['PropertyPageSchema', + {'Include': '$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml'} + ] + ] + for rule in msbuild_rules: + item_group.append( + ['AvailableItemName', + {'Include': rule.rule_name}, + ['Targets', rule.target_name], + ]) + content.append(item_group) + + for rule in msbuild_rules: + content.append( + ['UsingTask', + {'TaskName': rule.rule_name, + 'TaskFactory': 'XamlTaskFactory', + 'AssemblyName': 'Microsoft.Build.Tasks.v4.0' + }, + ['Task', '$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml'], + ]) + for rule in msbuild_rules: + rule_name = rule.rule_name + target_outputs = '%%(%s.Outputs)' % rule_name + target_inputs = ('%%(%s.Identity);%%(%s.AdditionalDependencies);' + '$(MSBuildProjectFile)') % (rule_name, rule_name) + rule_inputs = '%%(%s.Identity)' % rule_name + extension_condition = ("'%(Extension)'=='.obj' or " + "'%(Extension)'=='.res' or " + "'%(Extension)'=='.rsc' or " + "'%(Extension)'=='.lib'") + remove_section = [ + 'ItemGroup', + {'Condition': "'@(SelectedFiles)' != ''"}, + [rule_name, + {'Remove': '@(%s)' % rule_name, + 'Condition': "'%(Identity)' != '@(SelectedFiles)'" + } + ] + ] + inputs_section = [ + 'ItemGroup', + [rule.inputs, {'Include': '%%(%s.AdditionalDependencies)' % rule_name}] + ] + logging_section = [ + 'ItemGroup', + [rule.tlog, + {'Include': '%%(%s.Outputs)' % rule_name, + 'Condition': ("'%%(%s.Outputs)' != '' and " + "'%%(%s.ExcludedFromBuild)' != 'true'" % + (rule_name, rule_name)) + }, + ['Source', "@(%s, '|')" % rule_name], + ['Inputs', "@(%s -> '%%(Fullpath)', ';')" % rule.inputs], + ], + ] + message_section = [ + 'Message', + {'Importance': 'High', + 'Text': '%%(%s.ExecutionDescription)' % rule_name + } + ] + write_tlog_section = [ + 'WriteLinesToFile', + {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != " + "'true'" % (rule.tlog, rule.tlog), + 'File': '$(IntDir)$(ProjectName).write.1.tlog', + 'Lines': "^%%(%s.Source);@(%s->'%%(Fullpath)')" % (rule.tlog, + rule.tlog) + } + ] + read_tlog_section = [ + 'WriteLinesToFile', + {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != " + "'true'" % (rule.tlog, rule.tlog), + 'File': '$(IntDir)$(ProjectName).read.1.tlog', + 'Lines': "^%%(%s.Source);%%(%s.Inputs)" % (rule.tlog, rule.tlog) + } + ] + command_and_input_section = [ + rule_name, + {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != " + "'true'" % (rule_name, rule_name), + 'EchoOff': 'true', + 'StandardOutputImportance': 'High', + 'StandardErrorImportance': 'High', + 'CommandLineTemplate': '%%(%s.CommandLineTemplate)' % rule_name, + 'AdditionalOptions': '%%(%s.AdditionalOptions)' % rule_name, + 'Inputs': rule_inputs + } + ] + content.extend([ + ['Target', + {'Name': rule.target_name, + 'BeforeTargets': '$(%s)' % rule.before_targets, + 'AfterTargets': '$(%s)' % rule.after_targets, + 'Condition': "'@(%s)' != ''" % rule_name, + 'DependsOnTargets': '$(%s);%s' % (rule.depends_on, + rule.compute_output), + 'Outputs': target_outputs, + 'Inputs': target_inputs + }, + remove_section, + inputs_section, + logging_section, + message_section, + write_tlog_section, + read_tlog_section, + command_and_input_section, + ], + ['PropertyGroup', + ['ComputeLinkInputsTargets', + '$(ComputeLinkInputsTargets);', + '%s;' % rule.compute_output + ], + ['ComputeLibInputsTargets', + '$(ComputeLibInputsTargets);', + '%s;' % rule.compute_output + ], + ], + ['Target', + {'Name': rule.compute_output, + 'Condition': "'@(%s)' != ''" % rule_name + }, + ['ItemGroup', + [rule.dirs_to_make, + {'Condition': "'@(%s)' != '' and " + "'%%(%s.ExcludedFromBuild)' != 'true'" % (rule_name, rule_name), + 'Include': '%%(%s.Outputs)' % rule_name + } + ], + ['Link', + {'Include': '%%(%s.Identity)' % rule.dirs_to_make, + 'Condition': extension_condition + } + ], + ['Lib', + {'Include': '%%(%s.Identity)' % rule.dirs_to_make, + 'Condition': extension_condition + } + ], + ['ImpLib', + {'Include': '%%(%s.Identity)' % rule.dirs_to_make, + 'Condition': extension_condition + } + ], + ], + ['MakeDir', + {'Directories': ("@(%s->'%%(RootDir)%%(Directory)')" % + rule.dirs_to_make) + } + ] + ], + ]) + easy_xml.WriteXmlIfChanged(content, targets_path, pretty=True, win32=True) + + +def _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules): + # Generate the .xml file + content = [ + 'ProjectSchemaDefinitions', + {'xmlns': ('clr-namespace:Microsoft.Build.Framework.XamlTypes;' + 'assembly=Microsoft.Build.Framework'), + 'xmlns:x': 'http://schemas.microsoft.com/winfx/2006/xaml', + 'xmlns:sys': 'clr-namespace:System;assembly=mscorlib', + 'xmlns:transformCallback': + 'Microsoft.Cpp.Dev10.ConvertPropertyCallback' + } + ] + for rule in msbuild_rules: + content.extend([ + ['Rule', + {'Name': rule.rule_name, + 'PageTemplate': 'tool', + 'DisplayName': rule.display_name, + 'Order': '200' + }, + ['Rule.DataSource', + ['DataSource', + {'Persistence': 'ProjectFile', + 'ItemType': rule.rule_name + } + ] + ], + ['Rule.Categories', + ['Category', + {'Name': 'General'}, + ['Category.DisplayName', + ['sys:String', 'General'], + ], + ], + ['Category', + {'Name': 'Command Line', + 'Subtype': 'CommandLine' + }, + ['Category.DisplayName', + ['sys:String', 'Command Line'], + ], + ], + ], + ['StringListProperty', + {'Name': 'Inputs', + 'Category': 'Command Line', + 'IsRequired': 'true', + 'Switch': ' ' + }, + ['StringListProperty.DataSource', + ['DataSource', + {'Persistence': 'ProjectFile', + 'ItemType': rule.rule_name, + 'SourceType': 'Item' + } + ] + ], + ], + ['StringProperty', + {'Name': 'CommandLineTemplate', + 'DisplayName': 'Command Line', + 'Visible': 'False', + 'IncludeInCommandLine': 'False' + } + ], + ['DynamicEnumProperty', + {'Name': rule.before_targets, + 'Category': 'General', + 'EnumProvider': 'Targets', + 'IncludeInCommandLine': 'False' + }, + ['DynamicEnumProperty.DisplayName', + ['sys:String', 'Execute Before'], + ], + ['DynamicEnumProperty.Description', + ['sys:String', 'Specifies the targets for the build customization' + ' to run before.' + ], + ], + ['DynamicEnumProperty.ProviderSettings', + ['NameValuePair', + {'Name': 'Exclude', + 'Value': '^%s|^Compute' % rule.before_targets + } + ] + ], + ['DynamicEnumProperty.DataSource', + ['DataSource', + {'Persistence': 'ProjectFile', + 'HasConfigurationCondition': 'true' + } + ] + ], + ], + ['DynamicEnumProperty', + {'Name': rule.after_targets, + 'Category': 'General', + 'EnumProvider': 'Targets', + 'IncludeInCommandLine': 'False' + }, + ['DynamicEnumProperty.DisplayName', + ['sys:String', 'Execute After'], + ], + ['DynamicEnumProperty.Description', + ['sys:String', ('Specifies the targets for the build customization' + ' to run after.') + ], + ], + ['DynamicEnumProperty.ProviderSettings', + ['NameValuePair', + {'Name': 'Exclude', + 'Value': '^%s|^Compute' % rule.after_targets + } + ] + ], + ['DynamicEnumProperty.DataSource', + ['DataSource', + {'Persistence': 'ProjectFile', + 'ItemType': '', + 'HasConfigurationCondition': 'true' + } + ] + ], + ], + ['StringListProperty', + {'Name': 'Outputs', + 'DisplayName': 'Outputs', + 'Visible': 'False', + 'IncludeInCommandLine': 'False' + } + ], + ['StringProperty', + {'Name': 'ExecutionDescription', + 'DisplayName': 'Execution Description', + 'Visible': 'False', + 'IncludeInCommandLine': 'False' + } + ], + ['StringListProperty', + {'Name': 'AdditionalDependencies', + 'DisplayName': 'Additional Dependencies', + 'IncludeInCommandLine': 'False', + 'Visible': 'false' + } + ], + ['StringProperty', + {'Subtype': 'AdditionalOptions', + 'Name': 'AdditionalOptions', + 'Category': 'Command Line' + }, + ['StringProperty.DisplayName', + ['sys:String', 'Additional Options'], + ], + ['StringProperty.Description', + ['sys:String', 'Additional Options'], + ], + ], + ], + ['ItemType', + {'Name': rule.rule_name, + 'DisplayName': rule.display_name + } + ], + ['FileExtension', + {'Name': '*' + rule.extension, + 'ContentType': rule.rule_name + } + ], + ['ContentType', + {'Name': rule.rule_name, + 'DisplayName': '', + 'ItemType': rule.rule_name + } + ] + ]) + easy_xml.WriteXmlIfChanged(content, xml_path, pretty=True, win32=True) + + +def _GetConfigurationAndPlatform(name, settings): + configuration = name.rsplit('_', 1)[0] + platform = settings.get('msvs_configuration_platform', 'Win32') + return (configuration, platform) + + +def _GetConfigurationCondition(name, settings): + return (r"'$(Configuration)|$(Platform)'=='%s|%s'" % + _GetConfigurationAndPlatform(name, settings)) + + +def _GetMSBuildProjectConfigurations(configurations): + group = ['ItemGroup', {'Label': 'ProjectConfigurations'}] + for (name, settings) in sorted(configurations.iteritems()): + configuration, platform = _GetConfigurationAndPlatform(name, settings) + designation = '%s|%s' % (configuration, platform) + group.append( + ['ProjectConfiguration', {'Include': designation}, + ['Configuration', configuration], + ['Platform', platform]]) + return [group] + + +def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name): + namespace = os.path.splitext(gyp_file_name)[0] + properties = [ + ['PropertyGroup', {'Label': 'Globals'}, + ['ProjectGuid', guid], + ['Keyword', 'Win32Proj'], + ['RootNamespace', namespace], + ['IgnoreWarnCompileDuplicatedFilename', 'true'], + ] + ] + + if os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or \ + os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64': + properties[0].append(['PreferredToolArchitecture', 'x64']) + + if spec.get('msvs_enable_winrt'): + properties[0].append(['DefaultLanguage', 'en-US']) + properties[0].append(['AppContainerApplication', 'true']) + if spec.get('msvs_application_type_revision'): + app_type_revision = spec.get('msvs_application_type_revision') + properties[0].append(['ApplicationTypeRevision', app_type_revision]) + else: + properties[0].append(['ApplicationTypeRevision', '8.1']) + + if spec.get('msvs_target_platform_version'): + target_platform_version = spec.get('msvs_target_platform_version') + properties[0].append(['WindowsTargetPlatformVersion', + target_platform_version]) + if spec.get('msvs_target_platform_minversion'): + target_platform_minversion = spec.get('msvs_target_platform_minversion') + properties[0].append(['WindowsTargetPlatformMinVersion', + target_platform_minversion]) + else: + properties[0].append(['WindowsTargetPlatformMinVersion', + target_platform_version]) + if spec.get('msvs_enable_winphone'): + properties[0].append(['ApplicationType', 'Windows Phone']) + else: + properties[0].append(['ApplicationType', 'Windows Store']) + + platform_name = None + msvs_windows_target_platform_version = None + for configuration in spec['configurations'].itervalues(): + platform_name = platform_name or _ConfigPlatform(configuration) + msvs_windows_target_platform_version = \ + msvs_windows_target_platform_version or \ + _ConfigWindowsTargetPlatformVersion(configuration) + if platform_name and msvs_windows_target_platform_version: + break + + if platform_name == 'ARM': + properties[0].append(['WindowsSDKDesktopARMSupport', 'true']) + if msvs_windows_target_platform_version: + properties[0].append(['WindowsTargetPlatformVersion', \ + str(msvs_windows_target_platform_version)]) + + return properties + +def _GetMSBuildConfigurationDetails(spec, build_file): + properties = {} + for name, settings in spec['configurations'].iteritems(): + msbuild_attributes = _GetMSBuildAttributes(spec, settings, build_file) + condition = _GetConfigurationCondition(name, settings) + character_set = msbuild_attributes.get('CharacterSet') + _AddConditionalProperty(properties, condition, 'ConfigurationType', + msbuild_attributes['ConfigurationType']) + if character_set: + if 'msvs_enable_winrt' not in spec : + _AddConditionalProperty(properties, condition, 'CharacterSet', + character_set) + return _GetMSBuildPropertyGroup(spec, 'Configuration', properties) + + +def _GetMSBuildLocalProperties(msbuild_toolset): + # Currently the only local property we support is PlatformToolset + properties = {} + if msbuild_toolset: + properties = [ + ['PropertyGroup', {'Label': 'Locals'}, + ['PlatformToolset', msbuild_toolset], + ] + ] + return properties + + +def _GetMSBuildPropertySheets(configurations): + user_props = r'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props' + additional_props = {} + props_specified = False + for name, settings in sorted(configurations.iteritems()): + configuration = _GetConfigurationCondition(name, settings) + if settings.has_key('msbuild_props'): + additional_props[configuration] = _FixPaths(settings['msbuild_props']) + props_specified = True + else: + additional_props[configuration] = '' + + if not props_specified: + return [ + ['ImportGroup', + {'Label': 'PropertySheets'}, + ['Import', + {'Project': user_props, + 'Condition': "exists('%s')" % user_props, + 'Label': 'LocalAppDataPlatform' + } + ] + ] + ] + else: + sheets = [] + for condition, props in additional_props.iteritems(): + import_group = [ + 'ImportGroup', + {'Label': 'PropertySheets', + 'Condition': condition + }, + ['Import', + {'Project': user_props, + 'Condition': "exists('%s')" % user_props, + 'Label': 'LocalAppDataPlatform' + } + ] + ] + for props_file in props: + import_group.append(['Import', {'Project':props_file}]) + sheets.append(import_group) + return sheets + +def _ConvertMSVSBuildAttributes(spec, config, build_file): + config_type = _GetMSVSConfigurationType(spec, build_file) + msvs_attributes = _GetMSVSAttributes(spec, config, config_type) + msbuild_attributes = {} + for a in msvs_attributes: + if a in ['IntermediateDirectory', 'OutputDirectory']: + directory = MSVSSettings.ConvertVCMacrosToMSBuild(msvs_attributes[a]) + if not directory.endswith('\\'): + directory += '\\' + msbuild_attributes[a] = directory + elif a == 'CharacterSet': + msbuild_attributes[a] = _ConvertMSVSCharacterSet(msvs_attributes[a]) + elif a == 'ConfigurationType': + msbuild_attributes[a] = _ConvertMSVSConfigurationType(msvs_attributes[a]) + else: + print 'Warning: Do not know how to convert MSVS attribute ' + a + return msbuild_attributes + + +def _ConvertMSVSCharacterSet(char_set): + if char_set.isdigit(): + char_set = { + '0': 'MultiByte', + '1': 'Unicode', + '2': 'MultiByte', + }[char_set] + return char_set + + +def _ConvertMSVSConfigurationType(config_type): + if config_type.isdigit(): + config_type = { + '1': 'Application', + '2': 'DynamicLibrary', + '4': 'StaticLibrary', + '10': 'Utility' + }[config_type] + return config_type + + +def _GetMSBuildAttributes(spec, config, build_file): + if 'msbuild_configuration_attributes' not in config: + msbuild_attributes = _ConvertMSVSBuildAttributes(spec, config, build_file) + + else: + config_type = _GetMSVSConfigurationType(spec, build_file) + config_type = _ConvertMSVSConfigurationType(config_type) + msbuild_attributes = config.get('msbuild_configuration_attributes', {}) + msbuild_attributes.setdefault('ConfigurationType', config_type) + output_dir = msbuild_attributes.get('OutputDirectory', + '$(SolutionDir)$(Configuration)') + msbuild_attributes['OutputDirectory'] = _FixPath(output_dir) + '\\' + if 'IntermediateDirectory' not in msbuild_attributes: + intermediate = _FixPath('$(Configuration)') + '\\' + msbuild_attributes['IntermediateDirectory'] = intermediate + if 'CharacterSet' in msbuild_attributes: + msbuild_attributes['CharacterSet'] = _ConvertMSVSCharacterSet( + msbuild_attributes['CharacterSet']) + if 'TargetName' not in msbuild_attributes: + prefix = spec.get('product_prefix', '') + product_name = spec.get('product_name', '$(ProjectName)') + target_name = prefix + product_name + msbuild_attributes['TargetName'] = target_name + if 'TargetExt' not in msbuild_attributes and 'product_extension' in spec: + ext = spec.get('product_extension') + msbuild_attributes['TargetExt'] = '.' + ext + + if spec.get('msvs_external_builder'): + external_out_dir = spec.get('msvs_external_builder_out_dir', '.') + msbuild_attributes['OutputDirectory'] = _FixPath(external_out_dir) + '\\' + + # Make sure that 'TargetPath' matches 'Lib.OutputFile' or 'Link.OutputFile' + # (depending on the tool used) to avoid MSB8012 warning. + msbuild_tool_map = { + 'executable': 'Link', + 'shared_library': 'Link', + 'loadable_module': 'Link', + 'static_library': 'Lib', + } + msbuild_tool = msbuild_tool_map.get(spec['type']) + if msbuild_tool: + msbuild_settings = config['finalized_msbuild_settings'] + out_file = msbuild_settings[msbuild_tool].get('OutputFile') + if out_file: + msbuild_attributes['TargetPath'] = _FixPath(out_file) + target_ext = msbuild_settings[msbuild_tool].get('TargetExt') + if target_ext: + msbuild_attributes['TargetExt'] = target_ext + + return msbuild_attributes + + +def _GetMSBuildConfigurationGlobalProperties(spec, configurations, build_file): + # TODO(jeanluc) We could optimize out the following and do it only if + # there are actions. + # TODO(jeanluc) Handle the equivalent of setting 'CYGWIN=nontsec'. + new_paths = [] + cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.'])[0] + if cygwin_dirs: + cyg_path = '$(MSBuildProjectDirectory)\\%s\\bin\\' % _FixPath(cygwin_dirs) + new_paths.append(cyg_path) + # TODO(jeanluc) Change the convention to have both a cygwin_dir and a + # python_dir. + python_path = cyg_path.replace('cygwin\\bin', 'python_26') + new_paths.append(python_path) + if new_paths: + new_paths = '$(ExecutablePath);' + ';'.join(new_paths) + + properties = {} + for (name, configuration) in sorted(configurations.iteritems()): + condition = _GetConfigurationCondition(name, configuration) + attributes = _GetMSBuildAttributes(spec, configuration, build_file) + msbuild_settings = configuration['finalized_msbuild_settings'] + _AddConditionalProperty(properties, condition, 'IntDir', + attributes['IntermediateDirectory']) + _AddConditionalProperty(properties, condition, 'OutDir', + attributes['OutputDirectory']) + _AddConditionalProperty(properties, condition, 'TargetName', + attributes['TargetName']) + if 'TargetExt' in attributes: + _AddConditionalProperty(properties, condition, 'TargetExt', + attributes['TargetExt']) + + if attributes.get('TargetPath'): + _AddConditionalProperty(properties, condition, 'TargetPath', + attributes['TargetPath']) + if attributes.get('TargetExt'): + _AddConditionalProperty(properties, condition, 'TargetExt', + attributes['TargetExt']) + + if new_paths: + _AddConditionalProperty(properties, condition, 'ExecutablePath', + new_paths) + tool_settings = msbuild_settings.get('', {}) + for name, value in sorted(tool_settings.iteritems()): + formatted_value = _GetValueFormattedForMSBuild('', name, value) + _AddConditionalProperty(properties, condition, name, formatted_value) + return _GetMSBuildPropertyGroup(spec, None, properties) + + +def _AddConditionalProperty(properties, condition, name, value): + """Adds a property / conditional value pair to a dictionary. + + Arguments: + properties: The dictionary to be modified. The key is the name of the + property. The value is itself a dictionary; its key is the value and + the value a list of condition for which this value is true. + condition: The condition under which the named property has the value. + name: The name of the property. + value: The value of the property. + """ + if name not in properties: + properties[name] = {} + values = properties[name] + if value not in values: + values[value] = [] + conditions = values[value] + conditions.append(condition) + + +# Regex for msvs variable references ( i.e. $(FOO) ). +MSVS_VARIABLE_REFERENCE = re.compile(r'\$\(([a-zA-Z_][a-zA-Z0-9_]*)\)') + + +def _GetMSBuildPropertyGroup(spec, label, properties): + """Returns a PropertyGroup definition for the specified properties. + + Arguments: + spec: The target project dict. + label: An optional label for the PropertyGroup. + properties: The dictionary to be converted. The key is the name of the + property. The value is itself a dictionary; its key is the value and + the value a list of condition for which this value is true. + """ + group = ['PropertyGroup'] + if label: + group.append({'Label': label}) + num_configurations = len(spec['configurations']) + def GetEdges(node): + # Use a definition of edges such that user_of_variable -> used_varible. + # This happens to be easier in this case, since a variable's + # definition contains all variables it references in a single string. + edges = set() + for value in sorted(properties[node].keys()): + # Add to edges all $(...) references to variables. + # + # Variable references that refer to names not in properties are excluded + # These can exist for instance to refer built in definitions like + # $(SolutionDir). + # + # Self references are ignored. Self reference is used in a few places to + # append to the default value. I.e. PATH=$(PATH);other_path + edges.update(set([v for v in MSVS_VARIABLE_REFERENCE.findall(value) + if v in properties and v != node])) + return edges + properties_ordered = gyp.common.TopologicallySorted( + properties.keys(), GetEdges) + # Walk properties in the reverse of a topological sort on + # user_of_variable -> used_variable as this ensures variables are + # defined before they are used. + # NOTE: reverse(topsort(DAG)) = topsort(reverse_edges(DAG)) + for name in reversed(properties_ordered): + values = properties[name] + for value, conditions in sorted(values.iteritems()): + if len(conditions) == num_configurations: + # If the value is the same all configurations, + # just add one unconditional entry. + group.append([name, value]) + else: + for condition in conditions: + group.append([name, {'Condition': condition}, value]) + return [group] + + +def _GetMSBuildToolSettingsSections(spec, configurations): + groups = [] + for (name, configuration) in sorted(configurations.iteritems()): + msbuild_settings = configuration['finalized_msbuild_settings'] + group = ['ItemDefinitionGroup', + {'Condition': _GetConfigurationCondition(name, configuration)} + ] + for tool_name, tool_settings in sorted(msbuild_settings.iteritems()): + # Skip the tool named '' which is a holder of global settings handled + # by _GetMSBuildConfigurationGlobalProperties. + if tool_name: + if tool_settings: + tool = [tool_name] + for name, value in sorted(tool_settings.iteritems()): + formatted_value = _GetValueFormattedForMSBuild(tool_name, name, + value) + tool.append([name, formatted_value]) + group.append(tool) + groups.append(group) + return groups + + +def _FinalizeMSBuildSettings(spec, configuration): + if 'msbuild_settings' in configuration: + converted = False + msbuild_settings = configuration['msbuild_settings'] + MSVSSettings.ValidateMSBuildSettings(msbuild_settings) + else: + converted = True + msvs_settings = configuration.get('msvs_settings', {}) + msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(msvs_settings) + include_dirs, midl_include_dirs, resource_include_dirs = \ + _GetIncludeDirs(configuration) + libraries = _GetLibraries(spec) + library_dirs = _GetLibraryDirs(configuration) + out_file, _, msbuild_tool = _GetOutputFilePathAndTool(spec, msbuild=True) + target_ext = _GetOutputTargetExt(spec) + defines = _GetDefines(configuration) + if converted: + # Visual Studio 2010 has TR1 + defines = [d for d in defines if d != '_HAS_TR1=0'] + # Warn of ignored settings + ignored_settings = ['msvs_tool_files'] + for ignored_setting in ignored_settings: + value = configuration.get(ignored_setting) + if value: + print ('Warning: The automatic conversion to MSBuild does not handle ' + '%s. Ignoring setting of %s' % (ignored_setting, str(value))) + + defines = [_EscapeCppDefineForMSBuild(d) for d in defines] + disabled_warnings = _GetDisabledWarnings(configuration) + prebuild = configuration.get('msvs_prebuild') + postbuild = configuration.get('msvs_postbuild') + def_file = _GetModuleDefinition(spec) + precompiled_header = configuration.get('msvs_precompiled_header') + + # Add the information to the appropriate tool + # TODO(jeanluc) We could optimize and generate these settings only if + # the corresponding files are found, e.g. don't generate ResourceCompile + # if you don't have any resources. + _ToolAppend(msbuild_settings, 'ClCompile', + 'AdditionalIncludeDirectories', include_dirs) + _ToolAppend(msbuild_settings, 'Midl', + 'AdditionalIncludeDirectories', midl_include_dirs) + _ToolAppend(msbuild_settings, 'ResourceCompile', + 'AdditionalIncludeDirectories', resource_include_dirs) + # Add in libraries, note that even for empty libraries, we want this + # set, to prevent inheriting default libraries from the enviroment. + _ToolSetOrAppend(msbuild_settings, 'Link', 'AdditionalDependencies', + libraries) + _ToolAppend(msbuild_settings, 'Link', 'AdditionalLibraryDirectories', + library_dirs) + if out_file: + _ToolAppend(msbuild_settings, msbuild_tool, 'OutputFile', out_file, + only_if_unset=True) + if target_ext: + _ToolAppend(msbuild_settings, msbuild_tool, 'TargetExt', target_ext, + only_if_unset=True) + # Add defines. + _ToolAppend(msbuild_settings, 'ClCompile', + 'PreprocessorDefinitions', defines) + _ToolAppend(msbuild_settings, 'ResourceCompile', + 'PreprocessorDefinitions', defines) + # Add disabled warnings. + _ToolAppend(msbuild_settings, 'ClCompile', + 'DisableSpecificWarnings', disabled_warnings) + # Turn on precompiled headers if appropriate. + if precompiled_header: + precompiled_header = os.path.split(precompiled_header)[1] + _ToolAppend(msbuild_settings, 'ClCompile', 'PrecompiledHeader', 'Use') + _ToolAppend(msbuild_settings, 'ClCompile', + 'PrecompiledHeaderFile', precompiled_header) + _ToolAppend(msbuild_settings, 'ClCompile', + 'ForcedIncludeFiles', [precompiled_header]) + else: + _ToolAppend(msbuild_settings, 'ClCompile', 'PrecompiledHeader', 'NotUsing') + # Turn off WinRT compilation + _ToolAppend(msbuild_settings, 'ClCompile', 'CompileAsWinRT', 'false') + # Turn on import libraries if appropriate + if spec.get('msvs_requires_importlibrary'): + _ToolAppend(msbuild_settings, '', 'IgnoreImportLibrary', 'false') + # Loadable modules don't generate import libraries; + # tell dependent projects to not expect one. + if spec['type'] == 'loadable_module': + _ToolAppend(msbuild_settings, '', 'IgnoreImportLibrary', 'true') + # Set the module definition file if any. + if def_file: + _ToolAppend(msbuild_settings, 'Link', 'ModuleDefinitionFile', def_file) + configuration['finalized_msbuild_settings'] = msbuild_settings + if prebuild: + _ToolAppend(msbuild_settings, 'PreBuildEvent', 'Command', prebuild) + if postbuild: + _ToolAppend(msbuild_settings, 'PostBuildEvent', 'Command', postbuild) + + +def _GetValueFormattedForMSBuild(tool_name, name, value): + if type(value) == list: + # For some settings, VS2010 does not automatically extends the settings + # TODO(jeanluc) Is this what we want? + if name in ['AdditionalIncludeDirectories', + 'AdditionalLibraryDirectories', + 'AdditionalOptions', + 'DelayLoadDLLs', + 'DisableSpecificWarnings', + 'PreprocessorDefinitions']: + value.append('%%(%s)' % name) + # For most tools, entries in a list should be separated with ';' but some + # settings use a space. Check for those first. + exceptions = { + 'ClCompile': ['AdditionalOptions'], + 'Link': ['AdditionalOptions'], + 'Lib': ['AdditionalOptions']} + if tool_name in exceptions and name in exceptions[tool_name]: + char = ' ' + else: + char = ';' + formatted_value = char.join( + [MSVSSettings.ConvertVCMacrosToMSBuild(i) for i in value]) + else: + formatted_value = MSVSSettings.ConvertVCMacrosToMSBuild(value) + return formatted_value + + +def _VerifySourcesExist(sources, root_dir): + """Verifies that all source files exist on disk. + + Checks that all regular source files, i.e. not created at run time, + exist on disk. Missing files cause needless recompilation but no otherwise + visible errors. + + Arguments: + sources: A recursive list of Filter/file names. + root_dir: The root directory for the relative path names. + Returns: + A list of source files that cannot be found on disk. + """ + missing_sources = [] + for source in sources: + if isinstance(source, MSVSProject.Filter): + missing_sources.extend(_VerifySourcesExist(source.contents, root_dir)) + else: + if '$' not in source: + full_path = os.path.join(root_dir, source) + if not os.path.exists(full_path): + missing_sources.append(full_path) + return missing_sources + + +def _GetMSBuildSources(spec, sources, exclusions, rule_dependencies, + extension_to_rule_name, actions_spec, + sources_handled_by_action, list_excluded): + groups = ['none', 'masm', 'midl', 'include', 'compile', 'resource', 'rule', + 'rule_dependency'] + grouped_sources = {} + for g in groups: + grouped_sources[g] = [] + + _AddSources2(spec, sources, exclusions, grouped_sources, + rule_dependencies, extension_to_rule_name, + sources_handled_by_action, list_excluded) + sources = [] + for g in groups: + if grouped_sources[g]: + sources.append(['ItemGroup'] + grouped_sources[g]) + if actions_spec: + sources.append(['ItemGroup'] + actions_spec) + return sources + + +def _AddSources2(spec, sources, exclusions, grouped_sources, + rule_dependencies, extension_to_rule_name, + sources_handled_by_action, + list_excluded): + extensions_excluded_from_precompile = [] + for source in sources: + if isinstance(source, MSVSProject.Filter): + _AddSources2(spec, source.contents, exclusions, grouped_sources, + rule_dependencies, extension_to_rule_name, + sources_handled_by_action, + list_excluded) + else: + if not source in sources_handled_by_action: + detail = [] + excluded_configurations = exclusions.get(source, []) + if len(excluded_configurations) == len(spec['configurations']): + detail.append(['ExcludedFromBuild', 'true']) + else: + for config_name, configuration in sorted(excluded_configurations): + condition = _GetConfigurationCondition(config_name, configuration) + detail.append(['ExcludedFromBuild', + {'Condition': condition}, + 'true']) + # Add precompile if needed + for config_name, configuration in spec['configurations'].iteritems(): + precompiled_source = configuration.get('msvs_precompiled_source', '') + if precompiled_source != '': + precompiled_source = _FixPath(precompiled_source) + if not extensions_excluded_from_precompile: + # If the precompiled header is generated by a C source, we must + # not try to use it for C++ sources, and vice versa. + basename, extension = os.path.splitext(precompiled_source) + if extension == '.c': + extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx'] + else: + extensions_excluded_from_precompile = ['.c'] + + if precompiled_source == source: + condition = _GetConfigurationCondition(config_name, configuration) + detail.append(['PrecompiledHeader', + {'Condition': condition}, + 'Create' + ]) + else: + # Turn off precompiled header usage for source files of a + # different type than the file that generated the + # precompiled header. + for extension in extensions_excluded_from_precompile: + if source.endswith(extension): + detail.append(['PrecompiledHeader', '']) + detail.append(['ForcedIncludeFiles', '']) + + group, element = _MapFileToMsBuildSourceType(source, rule_dependencies, + extension_to_rule_name) + grouped_sources[group].append([element, {'Include': source}] + detail) + + +def _GetMSBuildProjectReferences(project): + references = [] + if project.dependencies: + group = ['ItemGroup'] + for dependency in project.dependencies: + guid = dependency.guid + project_dir = os.path.split(project.path)[0] + relative_path = gyp.common.RelativePath(dependency.path, project_dir) + project_ref = ['ProjectReference', + {'Include': relative_path}, + ['Project', guid], + ['ReferenceOutputAssembly', 'false'] + ] + for config in dependency.spec.get('configurations', {}).itervalues(): + if config.get('msvs_use_library_dependency_inputs', 0): + project_ref.append(['UseLibraryDependencyInputs', 'true']) + break + # If it's disabled in any config, turn it off in the reference. + if config.get('msvs_2010_disable_uldi_when_referenced', 0): + project_ref.append(['UseLibraryDependencyInputs', 'false']) + break + group.append(project_ref) + references.append(group) + return references + + +def _GenerateMSBuildProject(project, options, version, generator_flags): + spec = project.spec + configurations = spec['configurations'] + project_dir, project_file_name = os.path.split(project.path) + 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) + + gyp_file = os.path.split(project.build_file)[1] + sources, excluded_sources = _PrepareListOfSources(spec, generator_flags, + gyp_file) + # Add rules. + actions_to_add = {} + props_files_of_rules = set() + targets_files_of_rules = set() + rule_dependencies = set() + extension_to_rule_name = {} + list_excluded = generator_flags.get('msvs_list_excluded_files', True) + + # Don't generate rules if we are using an external builder like ninja. + if not spec.get('msvs_external_builder'): + _GenerateRulesForMSBuild(project_dir, options, spec, + sources, excluded_sources, + props_files_of_rules, targets_files_of_rules, + actions_to_add, rule_dependencies, + extension_to_rule_name) + else: + rules = spec.get('rules', []) + _AdjustSourcesForRules(rules, sources, excluded_sources, True) + + sources, excluded_sources, excluded_idl = ( + _AdjustSourcesAndConvertToFilterHierarchy(spec, options, + project_dir, sources, + excluded_sources, + list_excluded, version)) + + # Don't add actions if we are using an external builder like ninja. + if not spec.get('msvs_external_builder'): + _AddActions(actions_to_add, spec, project.build_file) + _AddCopies(actions_to_add, spec) + + # NOTE: this stanza must appear after all actions have been decided. + # Don't excluded sources with actions attached, or they won't run. + excluded_sources = _FilterActionsFromExcluded( + excluded_sources, actions_to_add) + + exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl) + actions_spec, sources_handled_by_action = _GenerateActionsForMSBuild( + spec, actions_to_add) + + _GenerateMSBuildFiltersFile(project.path + '.filters', sources, + rule_dependencies, + extension_to_rule_name) + missing_sources = _VerifySourcesExist(sources, project_dir) + + for configuration in configurations.itervalues(): + _FinalizeMSBuildSettings(spec, configuration) + + # Add attributes to root element + + import_default_section = [ + ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.Default.props'}]] + import_cpp_props_section = [ + ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.props'}]] + import_cpp_targets_section = [ + ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.targets'}]] + import_masm_props_section = [ + ['Import', + {'Project': r'$(VCTargetsPath)\BuildCustomizations\masm.props'}]] + import_masm_targets_section = [ + ['Import', + {'Project': r'$(VCTargetsPath)\BuildCustomizations\masm.targets'}]] + macro_section = [['PropertyGroup', {'Label': 'UserMacros'}]] + + content = [ + 'Project', + {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003', + 'ToolsVersion': version.ProjectVersion(), + 'DefaultTargets': 'Build' + }] + + content += _GetMSBuildProjectConfigurations(configurations) + content += _GetMSBuildGlobalProperties(spec, project.guid, project_file_name) + content += import_default_section + content += _GetMSBuildConfigurationDetails(spec, project.build_file) + if spec.get('msvs_enable_winphone'): + content += _GetMSBuildLocalProperties('v120_wp81') + else: + content += _GetMSBuildLocalProperties(project.msbuild_toolset) + content += import_cpp_props_section + content += import_masm_props_section + content += _GetMSBuildExtensions(props_files_of_rules) + content += _GetMSBuildPropertySheets(configurations) + content += macro_section + content += _GetMSBuildConfigurationGlobalProperties(spec, configurations, + project.build_file) + content += _GetMSBuildToolSettingsSections(spec, configurations) + content += _GetMSBuildSources( + spec, sources, exclusions, rule_dependencies, extension_to_rule_name, + actions_spec, sources_handled_by_action, list_excluded) + content += _GetMSBuildProjectReferences(project) + content += import_cpp_targets_section + content += import_masm_targets_section + content += _GetMSBuildExtensionTargets(targets_files_of_rules) + + if spec.get('msvs_external_builder'): + content += _GetMSBuildExternalBuilderTargets(spec) + + # TODO(jeanluc) File a bug to get rid of runas. We had in MSVS: + # has_run_as = _WriteMSVSUserFile(project.path, version, spec) + + easy_xml.WriteXmlIfChanged(content, project.path, pretty=True, win32=True) + + return missing_sources + + +def _GetMSBuildExternalBuilderTargets(spec): + """Return a list of MSBuild targets for external builders. + + The "Build" and "Clean" targets are always generated. If the spec contains + 'msvs_external_builder_clcompile_cmd', then the "ClCompile" target will also + be generated, to support building selected C/C++ files. + + Arguments: + spec: The gyp target spec. + Returns: + List of MSBuild 'Target' specs. + """ + build_cmd = _BuildCommandLineForRuleRaw( + spec, spec['msvs_external_builder_build_cmd'], + False, False, False, False) + build_target = ['Target', {'Name': 'Build'}] + build_target.append(['Exec', {'Command': build_cmd}]) + + clean_cmd = _BuildCommandLineForRuleRaw( + spec, spec['msvs_external_builder_clean_cmd'], + False, False, False, False) + clean_target = ['Target', {'Name': 'Clean'}] + clean_target.append(['Exec', {'Command': clean_cmd}]) + + targets = [build_target, clean_target] + + if spec.get('msvs_external_builder_clcompile_cmd'): + clcompile_cmd = _BuildCommandLineForRuleRaw( + spec, spec['msvs_external_builder_clcompile_cmd'], + False, False, False, False) + clcompile_target = ['Target', {'Name': 'ClCompile'}] + clcompile_target.append(['Exec', {'Command': clcompile_cmd}]) + targets.append(clcompile_target) + + return targets + + +def _GetMSBuildExtensions(props_files_of_rules): + extensions = ['ImportGroup', {'Label': 'ExtensionSettings'}] + for props_file in props_files_of_rules: + extensions.append(['Import', {'Project': props_file}]) + return [extensions] + + +def _GetMSBuildExtensionTargets(targets_files_of_rules): + targets_node = ['ImportGroup', {'Label': 'ExtensionTargets'}] + for targets_file in sorted(targets_files_of_rules): + targets_node.append(['Import', {'Project': targets_file}]) + return [targets_node] + + +def _GenerateActionsForMSBuild(spec, actions_to_add): + """Add actions accumulated into an actions_to_add, merging as needed. + + Arguments: + spec: the target project dict + actions_to_add: dictionary keyed on input name, which maps to a list of + dicts describing the actions attached to that input file. + + Returns: + A pair of (action specification, the sources handled by this action). + """ + sources_handled_by_action = OrderedSet() + actions_spec = [] + for primary_input, actions in actions_to_add.iteritems(): + inputs = OrderedSet() + outputs = OrderedSet() + descriptions = [] + commands = [] + for action in actions: + 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 + # return and continue executing. msbuild_use_call provides a way to + # disable this but I have not seen any adverse effect from doing that + # for everything. + if action.get('msbuild_use_call', True): + cmd = 'call ' + cmd + commands.append(cmd) + # Add the custom build action for one input file. + description = ', and also '.join(descriptions) + + # We can't join the commands simply with && because the command line will + # get too long. See also _AddActions: cygwin's setup_env mustn't be called + # for every invocation or the command that sets the PATH will grow too + # long. + command = '\r\n'.join([c + '\r\nif %errorlevel% neq 0 exit /b %errorlevel%' + for c in commands]) + _AddMSBuildAction(spec, + primary_input, + inputs, + outputs, + command, + description, + sources_handled_by_action, + actions_spec) + return actions_spec, sources_handled_by_action + + +def _AddMSBuildAction(spec, primary_input, inputs, outputs, cmd, description, + sources_handled_by_action, actions_spec): + command = MSVSSettings.ConvertVCMacrosToMSBuild(cmd) + primary_input = _FixPath(primary_input) + inputs_array = _FixPaths(inputs) + outputs_array = _FixPaths(outputs) + additional_inputs = ';'.join([i for i in inputs_array + if i != primary_input]) + outputs = ';'.join(outputs_array) + sources_handled_by_action.add(primary_input) + action_spec = ['CustomBuild', {'Include': primary_input}] + action_spec.extend( + # TODO(jeanluc) 'Document' for all or just if as_sources? + [['FileType', 'Document'], + ['Command', command], + ['Message', description], + ['Outputs', outputs] + ]) + if additional_inputs: + action_spec.append(['AdditionalInputs', additional_inputs]) + actions_spec.append(action_spec) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py new file mode 100755 index 0000000000000..c0b021df502bf --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py @@ -0,0 +1,37 @@ +#!/usr/bin/env python +# Copyright (c) 2012 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. + +""" Unit tests for the msvs.py file. """ + +import gyp.generator.msvs as msvs +import unittest +import StringIO + + +class TestSequenceFunctions(unittest.TestCase): + + def setUp(self): + self.stderr = StringIO.StringIO() + + def test_GetLibraries(self): + self.assertEqual( + msvs._GetLibraries({}), + []) + self.assertEqual( + msvs._GetLibraries({'libraries': []}), + []) + self.assertEqual( + msvs._GetLibraries({'other':'foo', 'libraries': ['a.lib']}), + ['a.lib']) + self.assertEqual( + msvs._GetLibraries({'libraries': ['-la']}), + ['a.lib']) + self.assertEqual( + msvs._GetLibraries({'libraries': ['a.lib', 'b.lib', 'c.lib', '-lb.lib', + '-lb.lib', 'd.lib', 'a.lib']}), + ['c.lib', 'b.lib', 'd.lib', 'a.lib']) + +if __name__ == '__main__': + unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py new file mode 100644 index 0000000000000..a00573ebf2345 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py @@ -0,0 +1,2422 @@ +# 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. + +import collections +import copy +import hashlib +import json +import multiprocessing +import os.path +import re +import signal +import subprocess +import sys +import gyp +import gyp.common +from gyp.common import OrderedSet +import gyp.msvs_emulation +import gyp.MSVSUtil as MSVSUtil +import gyp.xcode_emulation +from cStringIO import StringIO + +from gyp.common import GetEnvironFallback +import gyp.ninja_syntax as ninja_syntax + +generator_default_variables = { + 'EXECUTABLE_PREFIX': '', + 'EXECUTABLE_SUFFIX': '', + 'STATIC_LIB_PREFIX': 'lib', + 'STATIC_LIB_SUFFIX': '.a', + 'SHARED_LIB_PREFIX': 'lib', + + # Gyp expects the following variables to be expandable by the build + # system to the appropriate locations. Ninja prefers paths to be + # known at gyp time. To resolve this, introduce special + # variables starting with $! and $| (which begin with a $ so gyp knows it + # should be treated specially, but is otherwise an invalid + # ninja/shell variable) that are passed to gyp here but expanded + # before writing out into the target .ninja files; see + # ExpandSpecial. + # $! is used for variables that represent a path and that can only appear at + # the start of a string, while $| is used for variables that can appear + # anywhere in a string. + 'INTERMEDIATE_DIR': '$!INTERMEDIATE_DIR', + 'SHARED_INTERMEDIATE_DIR': '$!PRODUCT_DIR/gen', + 'PRODUCT_DIR': '$!PRODUCT_DIR', + 'CONFIGURATION_NAME': '$|CONFIGURATION_NAME', + + # Special variables that may be used by gyp 'rule' targets. + # We generate definitions for these variables on the fly when processing a + # rule. + 'RULE_INPUT_ROOT': '${root}', + 'RULE_INPUT_DIRNAME': '${dirname}', + 'RULE_INPUT_PATH': '${source}', + 'RULE_INPUT_EXT': '${ext}', + 'RULE_INPUT_NAME': '${name}', +} + +# Placates pylint. +generator_additional_non_configuration_keys = [] +generator_additional_path_sections = [] +generator_extra_sources_for_rules = [] +generator_filelist_paths = None + +generator_supports_multiple_toolsets = gyp.common.CrossCompileRequested() + +def StripPrefix(arg, prefix): + if arg.startswith(prefix): + return arg[len(prefix):] + return arg + + +def QuoteShellArgument(arg, flavor): + """Quote a string such that it will be interpreted as a single argument + by the shell.""" + # Rather than attempting to enumerate the bad shell characters, just + # whitelist common OK ones and quote anything else. + if re.match(r'^[a-zA-Z0-9_=.\\/-]+$', arg): + return arg # No quoting necessary. + if flavor == 'win': + return gyp.msvs_emulation.QuoteForRspFile(arg) + return "'" + arg.replace("'", "'" + '"\'"' + "'") + "'" + + +def Define(d, flavor): + """Takes a preprocessor define and returns a -D parameter that's ninja- and + shell-escaped.""" + if flavor == 'win': + # cl.exe replaces literal # characters with = in preprocesor definitions for + # some reason. Octal-encode to work around that. + d = d.replace('#', '\\%03o' % ord('#')) + return QuoteShellArgument(ninja_syntax.escape('-D' + d), flavor) + + +def AddArch(output, arch): + """Adds an arch string to an output path.""" + output, extension = os.path.splitext(output) + return '%s.%s%s' % (output, arch, extension) + + +class Target(object): + """Target represents the paths used within a single gyp target. + + Conceptually, building a single target A is a series of steps: + + 1) actions/rules/copies generates source/resources/etc. + 2) compiles generates .o files + 3) link generates a binary (library/executable) + 4) bundle merges the above in a mac bundle + + (Any of these steps can be optional.) + + From a build ordering perspective, a dependent target B could just + depend on the last output of this series of steps. + + But some dependent commands sometimes need to reach inside the box. + For example, when linking B it needs to get the path to the static + library generated by A. + + This object stores those paths. To keep things simple, member + variables only store concrete paths to single files, while methods + compute derived values like "the last output of the target". + """ + def __init__(self, type): + # Gyp type ("static_library", etc.) of this target. + self.type = type + # File representing whether any input dependencies necessary for + # dependent actions have completed. + self.preaction_stamp = None + # File representing whether any input dependencies necessary for + # dependent compiles have completed. + self.precompile_stamp = None + # File representing the completion of actions/rules/copies, if any. + self.actions_stamp = None + # Path to the output of the link step, if any. + self.binary = None + # Path to the file representing the completion of building the bundle, + # if any. + self.bundle = None + # On Windows, incremental linking requires linking against all the .objs + # that compose a .lib (rather than the .lib itself). That list is stored + # here. In this case, we also need to save the compile_deps for the target, + # so that the target that directly depends on the .objs can also depend + # on those. + self.component_objs = None + self.compile_deps = None + # Windows only. The import .lib is the output of a build step, but + # because dependents only link against the lib (not both the lib and the + # dll) we keep track of the import library here. + self.import_lib = None + + def Linkable(self): + """Return true if this is a target that can be linked against.""" + return self.type in ('static_library', 'shared_library') + + def UsesToc(self, flavor): + """Return true if the target should produce a restat rule based on a TOC + file.""" + # For bundles, the .TOC should be produced for the binary, not for + # FinalOutput(). But the naive approach would put the TOC file into the + # bundle, so don't do this for bundles for now. + if flavor == 'win' or self.bundle: + return False + return self.type in ('shared_library', 'loadable_module') + + def PreActionInput(self, flavor): + """Return the path, if any, that should be used as a dependency of + any dependent action step.""" + if self.UsesToc(flavor): + return self.FinalOutput() + '.TOC' + return self.FinalOutput() or self.preaction_stamp + + def PreCompileInput(self): + """Return the path, if any, that should be used as a dependency of + any dependent compile step.""" + return self.actions_stamp or self.precompile_stamp + + def FinalOutput(self): + """Return the last output of the target, which depends on all prior + steps.""" + return self.bundle or self.binary or self.actions_stamp + + +# A small discourse on paths as used within the Ninja build: +# All files we produce (both at gyp and at build time) appear in the +# build directory (e.g. out/Debug). +# +# Paths within a given .gyp file are always relative to the directory +# containing the .gyp file. Call these "gyp paths". This includes +# sources as well as the starting directory a given gyp rule/action +# expects to be run from. We call the path from the source root to +# the gyp file the "base directory" within the per-.gyp-file +# NinjaWriter code. +# +# All paths as written into the .ninja files are relative to the build +# directory. Call these paths "ninja paths". +# +# We translate between these two notions of paths with two helper +# functions: +# +# - GypPathToNinja translates a gyp path (i.e. relative to the .gyp file) +# into the equivalent ninja path. +# +# - GypPathToUniqueOutput translates a gyp path into a ninja path to write +# an output file; the result can be namespaced such that it is unique +# to the input file name as well as the output target name. + +class NinjaWriter(object): + def __init__(self, hash_for_rules, target_outputs, base_dir, build_dir, + output_file, toplevel_build, output_file_name, flavor, + toplevel_dir=None): + """ + base_dir: path from source root to directory containing this gyp file, + by gyp semantics, all input paths are relative to this + build_dir: path from source root to build output + toplevel_dir: path to the toplevel directory + """ + + self.hash_for_rules = hash_for_rules + self.target_outputs = target_outputs + self.base_dir = base_dir + self.build_dir = build_dir + self.ninja = ninja_syntax.Writer(output_file) + self.toplevel_build = toplevel_build + self.output_file_name = output_file_name + + self.flavor = flavor + self.abs_build_dir = None + if toplevel_dir is not None: + self.abs_build_dir = os.path.abspath(os.path.join(toplevel_dir, + build_dir)) + self.obj_ext = '.obj' if flavor == 'win' else '.o' + if flavor == 'win': + # See docstring of msvs_emulation.GenerateEnvironmentFiles(). + self.win_env = {} + for arch in ('x86', 'x64'): + self.win_env[arch] = 'environment.' + arch + + # Relative path from build output dir to base dir. + build_to_top = gyp.common.InvertRelativePath(build_dir, toplevel_dir) + self.build_to_base = os.path.join(build_to_top, base_dir) + # Relative path from base dir to build dir. + base_to_top = gyp.common.InvertRelativePath(base_dir, toplevel_dir) + self.base_to_build = os.path.join(base_to_top, build_dir) + + def ExpandSpecial(self, path, product_dir=None): + """Expand specials like $!PRODUCT_DIR in |path|. + + If |product_dir| is None, assumes the cwd is already the product + dir. Otherwise, |product_dir| is the relative path to the product + dir. + """ + + PRODUCT_DIR = '$!PRODUCT_DIR' + if PRODUCT_DIR in path: + if product_dir: + path = path.replace(PRODUCT_DIR, product_dir) + else: + path = path.replace(PRODUCT_DIR + '/', '') + path = path.replace(PRODUCT_DIR + '\\', '') + path = path.replace(PRODUCT_DIR, '.') + + INTERMEDIATE_DIR = '$!INTERMEDIATE_DIR' + if INTERMEDIATE_DIR in path: + int_dir = self.GypPathToUniqueOutput('gen') + # GypPathToUniqueOutput generates a path relative to the product dir, + # so insert product_dir in front if it is provided. + path = path.replace(INTERMEDIATE_DIR, + os.path.join(product_dir or '', int_dir)) + + CONFIGURATION_NAME = '$|CONFIGURATION_NAME' + path = path.replace(CONFIGURATION_NAME, self.config_name) + + return path + + def ExpandRuleVariables(self, path, root, dirname, source, ext, name): + if self.flavor == 'win': + path = self.msvs_settings.ConvertVSMacros( + path, config=self.config_name) + path = path.replace(generator_default_variables['RULE_INPUT_ROOT'], root) + path = path.replace(generator_default_variables['RULE_INPUT_DIRNAME'], + dirname) + path = path.replace(generator_default_variables['RULE_INPUT_PATH'], source) + path = path.replace(generator_default_variables['RULE_INPUT_EXT'], ext) + path = path.replace(generator_default_variables['RULE_INPUT_NAME'], name) + return path + + def GypPathToNinja(self, path, env=None): + """Translate a gyp path to a ninja path, optionally expanding environment + variable references in |path| with |env|. + + See the above discourse on path conversions.""" + if env: + if self.flavor == 'mac': + path = gyp.xcode_emulation.ExpandEnvVars(path, env) + elif self.flavor == 'win': + path = gyp.msvs_emulation.ExpandMacros(path, env) + if path.startswith('$!'): + expanded = self.ExpandSpecial(path) + if self.flavor == 'win': + expanded = os.path.normpath(expanded) + return expanded + if '$|' in path: + path = self.ExpandSpecial(path) + assert '$' not in path, path + return os.path.normpath(os.path.join(self.build_to_base, path)) + + def GypPathToUniqueOutput(self, path, qualified=True): + """Translate a gyp path to a ninja path for writing output. + + If qualified is True, qualify the resulting filename with the name + of the target. This is necessary when e.g. compiling the same + path twice for two separate output targets. + + See the above discourse on path conversions.""" + + path = self.ExpandSpecial(path) + assert not path.startswith('$'), path + + # Translate the path following this scheme: + # Input: foo/bar.gyp, target targ, references baz/out.o + # Output: obj/foo/baz/targ.out.o (if qualified) + # obj/foo/baz/out.o (otherwise) + # (and obj.host instead of obj for cross-compiles) + # + # Why this scheme and not some other one? + # 1) for a given input, you can compute all derived outputs by matching + # its path, even if the input is brought via a gyp file with '..'. + # 2) simple files like libraries and stamps have a simple filename. + + obj = 'obj' + if self.toolset != 'target': + obj += '.' + self.toolset + + path_dir, path_basename = os.path.split(path) + assert not os.path.isabs(path_dir), ( + "'%s' can not be absolute path (see crbug.com/462153)." % path_dir) + + if qualified: + path_basename = self.name + '.' + path_basename + return os.path.normpath(os.path.join(obj, self.base_dir, path_dir, + path_basename)) + + def WriteCollapsedDependencies(self, name, targets, order_only=None): + """Given a list of targets, return a path for a single file + representing the result of building all the targets or None. + + Uses a stamp file if necessary.""" + + assert targets == filter(None, targets), targets + if len(targets) == 0: + assert not order_only + return None + if len(targets) > 1 or order_only: + stamp = self.GypPathToUniqueOutput(name + '.stamp') + targets = self.ninja.build(stamp, 'stamp', targets, order_only=order_only) + self.ninja.newline() + return targets[0] + + def _SubninjaNameForArch(self, arch): + output_file_base = os.path.splitext(self.output_file_name)[0] + return '%s.%s.ninja' % (output_file_base, arch) + + def WriteSpec(self, spec, config_name, generator_flags): + """The main entry point for NinjaWriter: write the build rules for a spec. + + Returns a Target object, which represents the output paths for this spec. + Returns None if there are no outputs (e.g. a settings-only 'none' type + target).""" + + self.config_name = config_name + self.name = spec['target_name'] + self.toolset = spec['toolset'] + config = spec['configurations'][config_name] + self.target = Target(spec['type']) + self.is_standalone_static_library = bool( + spec.get('standalone_static_library', 0)) + # Track if this target contains any C++ files, to decide if gcc or g++ + # should be used for linking. + self.uses_cpp = False + + self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec) + self.xcode_settings = self.msvs_settings = None + if self.flavor == 'mac': + self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec) + if self.flavor == 'win': + self.msvs_settings = gyp.msvs_emulation.MsvsSettings(spec, + generator_flags) + arch = self.msvs_settings.GetArch(config_name) + self.ninja.variable('arch', self.win_env[arch]) + self.ninja.variable('cc', '$cl_' + arch) + self.ninja.variable('cxx', '$cl_' + arch) + self.ninja.variable('cc_host', '$cl_' + arch) + self.ninja.variable('cxx_host', '$cl_' + arch) + self.ninja.variable('asm', '$ml_' + arch) + + if self.flavor == 'mac': + self.archs = self.xcode_settings.GetActiveArchs(config_name) + if len(self.archs) > 1: + self.arch_subninjas = dict( + (arch, ninja_syntax.Writer( + OpenOutput(os.path.join(self.toplevel_build, + self._SubninjaNameForArch(arch)), + 'w'))) + for arch in self.archs) + + # Compute predepends for all rules. + # actions_depends is the dependencies this target depends on before running + # any of its action/rule/copy steps. + # compile_depends is the dependencies this target depends on before running + # any of its compile steps. + actions_depends = [] + compile_depends = [] + # TODO(evan): it is rather confusing which things are lists and which + # are strings. Fix these. + if 'dependencies' in spec: + for dep in spec['dependencies']: + if dep in self.target_outputs: + target = self.target_outputs[dep] + actions_depends.append(target.PreActionInput(self.flavor)) + compile_depends.append(target.PreCompileInput()) + actions_depends = filter(None, actions_depends) + compile_depends = filter(None, compile_depends) + actions_depends = self.WriteCollapsedDependencies('actions_depends', + actions_depends) + compile_depends = self.WriteCollapsedDependencies('compile_depends', + compile_depends) + self.target.preaction_stamp = actions_depends + self.target.precompile_stamp = compile_depends + + # Write out actions, rules, and copies. These must happen before we + # compile any sources, so compute a list of predependencies for sources + # while we do it. + extra_sources = [] + mac_bundle_depends = [] + self.target.actions_stamp = self.WriteActionsRulesCopies( + spec, extra_sources, actions_depends, mac_bundle_depends) + + # If we have actions/rules/copies, we depend directly on those, but + # otherwise we depend on dependent target's actions/rules/copies etc. + # We never need to explicitly depend on previous target's link steps, + # because no compile ever depends on them. + compile_depends_stamp = (self.target.actions_stamp or compile_depends) + + # Write out the compilation steps, if any. + link_deps = [] + sources = extra_sources + spec.get('sources', []) + if sources: + if self.flavor == 'mac' and len(self.archs) > 1: + # Write subninja file containing compile and link commands scoped to + # a single arch if a fat binary is being built. + for arch in self.archs: + self.ninja.subninja(self._SubninjaNameForArch(arch)) + + pch = None + if self.flavor == 'win': + gyp.msvs_emulation.VerifyMissingSources( + sources, self.abs_build_dir, generator_flags, self.GypPathToNinja) + pch = gyp.msvs_emulation.PrecompiledHeader( + self.msvs_settings, config_name, self.GypPathToNinja, + self.GypPathToUniqueOutput, self.obj_ext) + else: + pch = gyp.xcode_emulation.MacPrefixHeader( + self.xcode_settings, self.GypPathToNinja, + lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang)) + link_deps = self.WriteSources( + self.ninja, config_name, config, sources, compile_depends_stamp, pch, + spec) + # Some actions/rules output 'sources' that are already object files. + obj_outputs = [f for f in sources if f.endswith(self.obj_ext)] + if obj_outputs: + if self.flavor != 'mac' or len(self.archs) == 1: + link_deps += [self.GypPathToNinja(o) for o in obj_outputs] + else: + print "Warning: Actions/rules writing object files don't work with " \ + "multiarch targets, dropping. (target %s)" % spec['target_name'] + elif self.flavor == 'mac' and len(self.archs) > 1: + link_deps = collections.defaultdict(list) + + compile_deps = self.target.actions_stamp or actions_depends + if self.flavor == 'win' and self.target.type == 'static_library': + self.target.component_objs = link_deps + self.target.compile_deps = compile_deps + + # Write out a link step, if needed. + output = None + is_empty_bundle = not link_deps and not mac_bundle_depends + if link_deps or self.target.actions_stamp or actions_depends: + output = self.WriteTarget(spec, config_name, config, link_deps, + compile_deps) + if self.is_mac_bundle: + mac_bundle_depends.append(output) + + # Bundle all of the above together, if needed. + if self.is_mac_bundle: + output = self.WriteMacBundle(spec, mac_bundle_depends, is_empty_bundle) + + if not output: + return None + + assert self.target.FinalOutput(), output + return self.target + + def _WinIdlRule(self, source, prebuild, outputs): + """Handle the implicit VS .idl rule for one source file. Fills |outputs| + with files that are generated.""" + outdir, output, vars, flags = self.msvs_settings.GetIdlBuildData( + source, self.config_name) + outdir = self.GypPathToNinja(outdir) + def fix_path(path, rel=None): + path = os.path.join(outdir, path) + dirname, basename = os.path.split(source) + root, ext = os.path.splitext(basename) + path = self.ExpandRuleVariables( + path, root, dirname, source, ext, basename) + if rel: + path = os.path.relpath(path, rel) + return path + vars = [(name, fix_path(value, outdir)) for name, value in vars] + output = [fix_path(p) for p in output] + vars.append(('outdir', outdir)) + vars.append(('idlflags', flags)) + input = self.GypPathToNinja(source) + self.ninja.build(output, 'idl', input, + variables=vars, order_only=prebuild) + outputs.extend(output) + + def WriteWinIdlFiles(self, spec, prebuild): + """Writes rules to match MSVS's implicit idl handling.""" + assert self.flavor == 'win' + if self.msvs_settings.HasExplicitIdlRulesOrActions(spec): + return [] + outputs = [] + for source in filter(lambda x: x.endswith('.idl'), spec['sources']): + self._WinIdlRule(source, prebuild, outputs) + return outputs + + def WriteActionsRulesCopies(self, spec, extra_sources, prebuild, + mac_bundle_depends): + """Write out the Actions, Rules, and Copies steps. Return a path + representing the outputs of these steps.""" + outputs = [] + if self.is_mac_bundle: + mac_bundle_resources = spec.get('mac_bundle_resources', [])[:] + else: + mac_bundle_resources = [] + extra_mac_bundle_resources = [] + + if 'actions' in spec: + outputs += self.WriteActions(spec['actions'], extra_sources, prebuild, + extra_mac_bundle_resources) + if 'rules' in spec: + outputs += self.WriteRules(spec['rules'], extra_sources, prebuild, + mac_bundle_resources, + extra_mac_bundle_resources) + if 'copies' in spec: + outputs += self.WriteCopies(spec['copies'], prebuild, mac_bundle_depends) + + if 'sources' in spec and self.flavor == 'win': + outputs += self.WriteWinIdlFiles(spec, prebuild) + + stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs) + + if self.is_mac_bundle: + xcassets = self.WriteMacBundleResources( + extra_mac_bundle_resources + mac_bundle_resources, mac_bundle_depends) + partial_info_plist = self.WriteMacXCassets(xcassets, mac_bundle_depends) + self.WriteMacInfoPlist(partial_info_plist, mac_bundle_depends) + + return stamp + + def GenerateDescription(self, verb, message, fallback): + """Generate and return a description of a build step. + + |verb| is the short summary, e.g. ACTION or RULE. + |message| is a hand-written description, or None if not available. + |fallback| is the gyp-level name of the step, usable as a fallback. + """ + if self.toolset != 'target': + verb += '(%s)' % self.toolset + if message: + return '%s %s' % (verb, self.ExpandSpecial(message)) + else: + return '%s %s: %s' % (verb, self.name, fallback) + + def WriteActions(self, actions, extra_sources, prebuild, + extra_mac_bundle_resources): + # Actions cd into the base directory. + env = self.GetToolchainEnv() + all_outputs = [] + for action in actions: + # First write out a rule for the action. + name = '%s_%s' % (action['action_name'], self.hash_for_rules) + description = self.GenerateDescription('ACTION', + action.get('message', None), + name) + is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(action) + if self.flavor == 'win' else False) + args = action['action'] + depfile = action.get('depfile', None) + if depfile: + depfile = self.ExpandSpecial(depfile, self.base_to_build) + pool = 'console' if int(action.get('ninja_use_console', 0)) else None + rule_name, _ = self.WriteNewNinjaRule(name, args, description, + is_cygwin, env, pool, + depfile=depfile) + + inputs = [self.GypPathToNinja(i, env) for i in action['inputs']] + if int(action.get('process_outputs_as_sources', False)): + extra_sources += action['outputs'] + if int(action.get('process_outputs_as_mac_bundle_resources', False)): + extra_mac_bundle_resources += action['outputs'] + outputs = [self.GypPathToNinja(o, env) for o in action['outputs']] + + # Then write out an edge using the rule. + self.ninja.build(outputs, rule_name, inputs, + order_only=prebuild) + all_outputs += outputs + + self.ninja.newline() + + return all_outputs + + def WriteRules(self, rules, extra_sources, prebuild, + mac_bundle_resources, extra_mac_bundle_resources): + env = self.GetToolchainEnv() + all_outputs = [] + for rule in rules: + # Skip a rule with no action and no inputs. + if 'action' not in rule and not rule.get('rule_sources', []): + continue + + # First write out a rule for the rule action. + name = '%s_%s' % (rule['rule_name'], self.hash_for_rules) + + args = rule['action'] + description = self.GenerateDescription( + 'RULE', + rule.get('message', None), + ('%s ' + generator_default_variables['RULE_INPUT_PATH']) % name) + is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(rule) + if self.flavor == 'win' else False) + pool = 'console' if int(rule.get('ninja_use_console', 0)) else None + rule_name, args = self.WriteNewNinjaRule( + name, args, description, is_cygwin, env, pool) + + # TODO: if the command references the outputs directly, we should + # simplify it to just use $out. + + # Rules can potentially make use of some special variables which + # must vary per source file. + # Compute the list of variables we'll need to provide. + special_locals = ('source', 'root', 'dirname', 'ext', 'name') + needed_variables = set(['source']) + for argument in args: + for var in special_locals: + if '${%s}' % var in argument: + needed_variables.add(var) + + def cygwin_munge(path): + # pylint: disable=cell-var-from-loop + if is_cygwin: + return path.replace('\\', '/') + return path + + inputs = [self.GypPathToNinja(i, env) for i in rule.get('inputs', [])] + + # If there are n source files matching the rule, and m additional rule + # inputs, then adding 'inputs' to each build edge written below will + # write m * n inputs. Collapsing reduces this to m + n. + sources = rule.get('rule_sources', []) + num_inputs = len(inputs) + if prebuild: + num_inputs += 1 + if num_inputs > 2 and len(sources) > 2: + inputs = [self.WriteCollapsedDependencies( + rule['rule_name'], inputs, order_only=prebuild)] + prebuild = [] + + # For each source file, write an edge that generates all the outputs. + for source in sources: + source = os.path.normpath(source) + dirname, basename = os.path.split(source) + root, ext = os.path.splitext(basename) + + # Gather the list of inputs and outputs, expanding $vars if possible. + outputs = [self.ExpandRuleVariables(o, root, dirname, + source, ext, basename) + for o in rule['outputs']] + + if int(rule.get('process_outputs_as_sources', False)): + extra_sources += outputs + + was_mac_bundle_resource = source in mac_bundle_resources + if was_mac_bundle_resource or \ + int(rule.get('process_outputs_as_mac_bundle_resources', False)): + extra_mac_bundle_resources += outputs + # Note: This is n_resources * n_outputs_in_rule. Put to-be-removed + # items in a set and remove them all in a single pass if this becomes + # a performance issue. + if was_mac_bundle_resource: + mac_bundle_resources.remove(source) + + extra_bindings = [] + for var in needed_variables: + if var == 'root': + extra_bindings.append(('root', cygwin_munge(root))) + elif var == 'dirname': + # '$dirname' is a parameter to the rule action, which means + # it shouldn't be converted to a Ninja path. But we don't + # want $!PRODUCT_DIR in there either. + dirname_expanded = self.ExpandSpecial(dirname, self.base_to_build) + extra_bindings.append(('dirname', cygwin_munge(dirname_expanded))) + elif var == 'source': + # '$source' is a parameter to the rule action, which means + # it shouldn't be converted to a Ninja path. But we don't + # want $!PRODUCT_DIR in there either. + source_expanded = self.ExpandSpecial(source, self.base_to_build) + extra_bindings.append(('source', cygwin_munge(source_expanded))) + elif var == 'ext': + extra_bindings.append(('ext', ext)) + elif var == 'name': + extra_bindings.append(('name', cygwin_munge(basename))) + else: + assert var == None, repr(var) + + outputs = [self.GypPathToNinja(o, env) for o in outputs] + if self.flavor == 'win': + # WriteNewNinjaRule uses unique_name for creating an rsp file on win. + extra_bindings.append(('unique_name', + hashlib.md5(outputs[0]).hexdigest())) + self.ninja.build(outputs, rule_name, self.GypPathToNinja(source), + implicit=inputs, + order_only=prebuild, + variables=extra_bindings) + + all_outputs.extend(outputs) + + return all_outputs + + def WriteCopies(self, copies, prebuild, mac_bundle_depends): + outputs = [] + env = self.GetToolchainEnv() + for copy in copies: + for path in copy['files']: + # Normalize the path so trailing slashes don't confuse us. + path = os.path.normpath(path) + basename = os.path.split(path)[1] + src = self.GypPathToNinja(path, env) + dst = self.GypPathToNinja(os.path.join(copy['destination'], basename), + env) + outputs += self.ninja.build(dst, 'copy', src, order_only=prebuild) + if self.is_mac_bundle: + # gyp has mac_bundle_resources to copy things into a bundle's + # Resources folder, but there's no built-in way to copy files to other + # places in the bundle. Hence, some targets use copies for this. Check + # if this file is copied into the current bundle, and if so add it to + # the bundle depends so that dependent targets get rebuilt if the copy + # input changes. + if dst.startswith(self.xcode_settings.GetBundleContentsFolderPath()): + mac_bundle_depends.append(dst) + + return outputs + + def WriteMacBundleResources(self, resources, bundle_depends): + """Writes ninja edges for 'mac_bundle_resources'.""" + xcassets = [] + for output, res in gyp.xcode_emulation.GetMacBundleResources( + generator_default_variables['PRODUCT_DIR'], + self.xcode_settings, map(self.GypPathToNinja, resources)): + output = self.ExpandSpecial(output) + if os.path.splitext(output)[-1] != '.xcassets': + isBinary = self.xcode_settings.IsBinaryOutputFormat(self.config_name) + self.ninja.build(output, 'mac_tool', res, + variables=[('mactool_cmd', 'copy-bundle-resource'), \ + ('binary', isBinary)]) + bundle_depends.append(output) + else: + xcassets.append(res) + return xcassets + + def WriteMacXCassets(self, xcassets, bundle_depends): + """Writes ninja edges for 'mac_bundle_resources' .xcassets files. + + This add an invocation of 'actool' via the 'mac_tool.py' helper script. + It assumes that the assets catalogs define at least one imageset and + thus an Assets.car file will be generated in the application resources + directory. If this is not the case, then the build will probably be done + at each invocation of ninja.""" + if not xcassets: + return + + extra_arguments = {} + settings_to_arg = { + 'XCASSETS_APP_ICON': 'app-icon', + 'XCASSETS_LAUNCH_IMAGE': 'launch-image', + } + settings = self.xcode_settings.xcode_settings[self.config_name] + for settings_key, arg_name in settings_to_arg.iteritems(): + value = settings.get(settings_key) + if value: + extra_arguments[arg_name] = value + + partial_info_plist = None + if extra_arguments: + partial_info_plist = self.GypPathToUniqueOutput( + 'assetcatalog_generated_info.plist') + extra_arguments['output-partial-info-plist'] = partial_info_plist + + outputs = [] + outputs.append( + os.path.join( + self.xcode_settings.GetBundleResourceFolder(), + 'Assets.car')) + if partial_info_plist: + outputs.append(partial_info_plist) + + keys = QuoteShellArgument(json.dumps(extra_arguments), self.flavor) + extra_env = self.xcode_settings.GetPerTargetSettings() + env = self.GetSortedXcodeEnv(additional_settings=extra_env) + env = self.ComputeExportEnvString(env) + + bundle_depends.extend(self.ninja.build( + outputs, 'compile_xcassets', xcassets, + variables=[('env', env), ('keys', keys)])) + return partial_info_plist + + def WriteMacInfoPlist(self, partial_info_plist, bundle_depends): + """Write build rules for bundle Info.plist files.""" + info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist( + generator_default_variables['PRODUCT_DIR'], + self.xcode_settings, self.GypPathToNinja) + if not info_plist: + return + out = self.ExpandSpecial(out) + if defines: + # Create an intermediate file to store preprocessed results. + intermediate_plist = self.GypPathToUniqueOutput( + os.path.basename(info_plist)) + defines = ' '.join([Define(d, self.flavor) for d in defines]) + info_plist = self.ninja.build( + intermediate_plist, 'preprocess_infoplist', info_plist, + variables=[('defines',defines)]) + + env = self.GetSortedXcodeEnv(additional_settings=extra_env) + env = self.ComputeExportEnvString(env) + + if partial_info_plist: + intermediate_plist = self.GypPathToUniqueOutput('merged_info.plist') + info_plist = self.ninja.build( + intermediate_plist, 'merge_infoplist', + [partial_info_plist, info_plist]) + + keys = self.xcode_settings.GetExtraPlistItems(self.config_name) + keys = QuoteShellArgument(json.dumps(keys), self.flavor) + isBinary = self.xcode_settings.IsBinaryOutputFormat(self.config_name) + self.ninja.build(out, 'copy_infoplist', info_plist, + variables=[('env', env), ('keys', keys), + ('binary', isBinary)]) + bundle_depends.append(out) + + def WriteSources(self, ninja_file, config_name, config, sources, predepends, + precompiled_header, spec): + """Write build rules to compile all of |sources|.""" + if self.toolset == 'host': + self.ninja.variable('ar', '$ar_host') + self.ninja.variable('cc', '$cc_host') + self.ninja.variable('cxx', '$cxx_host') + self.ninja.variable('ld', '$ld_host') + self.ninja.variable('ldxx', '$ldxx_host') + self.ninja.variable('nm', '$nm_host') + self.ninja.variable('readelf', '$readelf_host') + + if self.flavor != 'mac' or len(self.archs) == 1: + return self.WriteSourcesForArch( + self.ninja, config_name, config, sources, predepends, + precompiled_header, spec) + else: + return dict((arch, self.WriteSourcesForArch( + self.arch_subninjas[arch], config_name, config, sources, predepends, + precompiled_header, spec, arch=arch)) + for arch in self.archs) + + def WriteSourcesForArch(self, ninja_file, config_name, config, sources, + predepends, precompiled_header, spec, arch=None): + """Write build rules to compile all of |sources|.""" + + extra_defines = [] + if self.flavor == 'mac': + cflags = self.xcode_settings.GetCflags(config_name, arch=arch) + cflags_c = self.xcode_settings.GetCflagsC(config_name) + cflags_cc = self.xcode_settings.GetCflagsCC(config_name) + cflags_objc = ['$cflags_c'] + \ + self.xcode_settings.GetCflagsObjC(config_name) + cflags_objcc = ['$cflags_cc'] + \ + self.xcode_settings.GetCflagsObjCC(config_name) + elif self.flavor == 'win': + asmflags = self.msvs_settings.GetAsmflags(config_name) + cflags = self.msvs_settings.GetCflags(config_name) + cflags_c = self.msvs_settings.GetCflagsC(config_name) + cflags_cc = self.msvs_settings.GetCflagsCC(config_name) + extra_defines = self.msvs_settings.GetComputedDefines(config_name) + # 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_c: + obj = 'obj' + if self.toolset != 'target': + obj += '.' + self.toolset + 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', []) + cflags_c = config.get('cflags_c', []) + cflags_cc = config.get('cflags_cc', []) + + # Respect environment variables related to build, but target-specific + # flags can still override them. + if self.toolset == 'target': + cflags_c = (os.environ.get('CPPFLAGS', '').split() + + os.environ.get('CFLAGS', '').split() + cflags_c) + cflags_cc = (os.environ.get('CPPFLAGS', '').split() + + os.environ.get('CXXFLAGS', '').split() + cflags_cc) + elif self.toolset == 'host': + cflags_c = (os.environ.get('CPPFLAGS_host', '').split() + + os.environ.get('CFLAGS_host', '').split() + cflags_c) + cflags_cc = (os.environ.get('CPPFLAGS_host', '').split() + + os.environ.get('CXXFLAGS_host', '').split() + cflags_cc) + + defines = config.get('defines', []) + extra_defines + self.WriteVariableList(ninja_file, 'defines', + [Define(d, self.flavor) for d in defines]) + if self.flavor == 'win': + self.WriteVariableList(ninja_file, 'asmflags', + map(self.ExpandSpecial, asmflags)) + self.WriteVariableList(ninja_file, 'rcflags', + [QuoteShellArgument(self.ExpandSpecial(f), self.flavor) + for f in self.msvs_settings.GetRcflags(config_name, + self.GypPathToNinja)]) + + include_dirs = config.get('include_dirs', []) + + env = self.GetToolchainEnv() + if self.flavor == 'win': + include_dirs = self.msvs_settings.AdjustIncludeDirs(include_dirs, + config_name) + self.WriteVariableList(ninja_file, 'includes', + [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor) + for i in include_dirs]) + + if self.flavor == 'win': + midl_include_dirs = config.get('midl_include_dirs', []) + midl_include_dirs = self.msvs_settings.AdjustMidlIncludeDirs( + midl_include_dirs, config_name) + self.WriteVariableList(ninja_file, 'midl_includes', + [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor) + for i in midl_include_dirs]) + + pch_commands = precompiled_header.GetPchBuildCommands(arch) + if self.flavor == 'mac': + # Most targets use no precompiled headers, so only write these if needed. + for ext, var in [('c', 'cflags_pch_c'), ('cc', 'cflags_pch_cc'), + ('m', 'cflags_pch_objc'), ('mm', 'cflags_pch_objcc')]: + include = precompiled_header.GetInclude(ext, arch) + if include: ninja_file.variable(var, include) + + arflags = config.get('arflags', []) + + self.WriteVariableList(ninja_file, 'cflags', + map(self.ExpandSpecial, cflags)) + self.WriteVariableList(ninja_file, 'cflags_c', + map(self.ExpandSpecial, cflags_c)) + self.WriteVariableList(ninja_file, 'cflags_cc', + map(self.ExpandSpecial, cflags_cc)) + if self.flavor == 'mac': + self.WriteVariableList(ninja_file, 'cflags_objc', + map(self.ExpandSpecial, cflags_objc)) + self.WriteVariableList(ninja_file, 'cflags_objcc', + map(self.ExpandSpecial, cflags_objcc)) + self.WriteVariableList(ninja_file, 'arflags', + map(self.ExpandSpecial, arflags)) + ninja_file.newline() + outputs = [] + has_rc_source = False + for source in sources: + filename, ext = os.path.splitext(source) + ext = ext[1:] + obj_ext = self.obj_ext + if ext in ('cc', 'cpp', 'cxx'): + command = 'cxx' + self.uses_cpp = True + elif ext == 'c' or (ext == 'S' and self.flavor != 'win'): + command = 'cc' + elif ext == 's' and self.flavor != 'win': # Doesn't generate .o.d files. + command = 'cc_s' + elif (self.flavor == 'win' and ext == 'asm' and + not self.msvs_settings.HasExplicitAsmRules(spec)): + command = 'asm' + # Add the _asm suffix as msvs is capable of handling .cc and + # .asm files of the same name without collision. + obj_ext = '_asm.obj' + elif self.flavor == 'mac' and ext == 'm': + command = 'objc' + elif self.flavor == 'mac' and ext == 'mm': + command = 'objcxx' + self.uses_cpp = True + elif self.flavor == 'win' and ext == 'rc': + command = 'rc' + obj_ext = '.res' + has_rc_source = True + else: + # Ignore unhandled extensions. + continue + input = self.GypPathToNinja(source) + output = self.GypPathToUniqueOutput(filename + obj_ext) + if arch is not None: + output = AddArch(output, arch) + implicit = precompiled_header.GetObjDependencies([input], [output], arch) + variables = [] + if self.flavor == 'win': + variables, output, implicit = precompiled_header.GetFlagsModifications( + input, output, implicit, command, cflags_c, cflags_cc, + self.ExpandSpecial) + ninja_file.build(output, command, input, + implicit=[gch for _, _, gch in implicit], + order_only=predepends, variables=variables) + outputs.append(output) + + if has_rc_source: + resource_include_dirs = config.get('resource_include_dirs', include_dirs) + self.WriteVariableList(ninja_file, 'resource_includes', + [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor) + for i in resource_include_dirs]) + + self.WritePchTargets(ninja_file, pch_commands) + + ninja_file.newline() + return outputs + + def WritePchTargets(self, ninja_file, pch_commands): + """Writes ninja rules to compile prefix headers.""" + if not pch_commands: + return + + for gch, lang_flag, lang, input in pch_commands: + var_name = { + 'c': 'cflags_pch_c', + 'cc': 'cflags_pch_cc', + 'm': 'cflags_pch_objc', + 'mm': 'cflags_pch_objcc', + }[lang] + + map = { 'c': 'cc', 'cc': 'cxx', 'm': 'objc', 'mm': 'objcxx', } + cmd = map.get(lang) + ninja_file.build(gch, cmd, input, variables=[(var_name, lang_flag)]) + + def WriteLink(self, spec, config_name, config, link_deps): + """Write out a link step. Fills out target.binary. """ + if self.flavor != 'mac' or len(self.archs) == 1: + return self.WriteLinkForArch( + self.ninja, spec, config_name, config, link_deps) + else: + output = self.ComputeOutput(spec) + inputs = [self.WriteLinkForArch(self.arch_subninjas[arch], spec, + config_name, config, link_deps[arch], + arch=arch) + for arch in self.archs] + extra_bindings = [] + build_output = output + if not self.is_mac_bundle: + self.AppendPostbuildVariable(extra_bindings, spec, output, output) + + # TODO(yyanagisawa): more work needed to fix: + # https://code.google.com/p/gyp/issues/detail?id=411 + if (spec['type'] in ('shared_library', 'loadable_module') and + not self.is_mac_bundle): + extra_bindings.append(('lib', output)) + self.ninja.build([output, output + '.TOC'], 'solipo', inputs, + variables=extra_bindings) + else: + self.ninja.build(build_output, 'lipo', inputs, variables=extra_bindings) + return output + + def WriteLinkForArch(self, ninja_file, spec, config_name, config, + link_deps, arch=None): + """Write out a link step. Fills out target.binary. """ + command = { + 'executable': 'link', + 'loadable_module': 'solink_module', + 'shared_library': 'solink', + }[spec['type']] + command_suffix = '' + + implicit_deps = set() + solibs = set() + order_deps = set() + + if 'dependencies' in spec: + # Two kinds of dependencies: + # - Linkable dependencies (like a .a or a .so): add them to the link line. + # - Non-linkable dependencies (like a rule that generates a file + # and writes a stamp file): add them to implicit_deps + extra_link_deps = set() + for dep in spec['dependencies']: + target = self.target_outputs.get(dep) + if not target: + continue + linkable = target.Linkable() + if linkable: + new_deps = [] + if (self.flavor == 'win' and + target.component_objs and + self.msvs_settings.IsUseLibraryDependencyInputs(config_name)): + new_deps = target.component_objs + if target.compile_deps: + order_deps.add(target.compile_deps) + elif self.flavor == 'win' and target.import_lib: + new_deps = [target.import_lib] + elif target.UsesToc(self.flavor): + solibs.add(target.binary) + implicit_deps.add(target.binary + '.TOC') + else: + new_deps = [target.binary] + for new_dep in new_deps: + if new_dep not in extra_link_deps: + extra_link_deps.add(new_dep) + link_deps.append(new_dep) + + final_output = target.FinalOutput() + if not linkable or final_output != target.binary: + implicit_deps.add(final_output) + + extra_bindings = [] + if self.uses_cpp and self.flavor != 'win': + extra_bindings.append(('ld', '$ldxx')) + + output = self.ComputeOutput(spec, arch) + if arch is None and not self.is_mac_bundle: + self.AppendPostbuildVariable(extra_bindings, spec, output, output) + + is_executable = spec['type'] == 'executable' + # The ldflags config key is not used on mac or win. On those platforms + # linker flags are set via xcode_settings and msvs_settings, respectively. + env_ldflags = os.environ.get('LDFLAGS', '').split() + if self.flavor == 'mac': + ldflags = self.xcode_settings.GetLdflags(config_name, + self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']), + self.GypPathToNinja, arch) + ldflags = env_ldflags + ldflags + elif self.flavor == 'win': + manifest_base_name = self.GypPathToUniqueOutput( + self.ComputeOutputFileName(spec)) + 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)) + def_file = self.msvs_settings.GetDefFile(self.GypPathToNinja) + if def_file: + implicit_deps.add(def_file) + else: + # Respect environment variables related to build, but target-specific + # flags can still override them. + ldflags = env_ldflags + config.get('ldflags', []) + if is_executable and len(solibs): + rpath = 'lib/' + if self.toolset != 'target': + rpath += self.toolset + ldflags.append(r'-Wl,-rpath=\$$ORIGIN/%s' % rpath) + ldflags.append('-Wl,-rpath-link=%s' % rpath) + self.WriteVariableList(ninja_file, 'ldflags', + map(self.ExpandSpecial, ldflags)) + + library_dirs = config.get('library_dirs', []) + if self.flavor == 'win': + library_dirs = [self.msvs_settings.ConvertVSMacros(l, config_name) + for l in library_dirs] + library_dirs = ['/LIBPATH:' + QuoteShellArgument(self.GypPathToNinja(l), + self.flavor) + for l in library_dirs] + else: + library_dirs = [QuoteShellArgument('-L' + self.GypPathToNinja(l), + self.flavor) + for l in library_dirs] + + libraries = gyp.common.uniquer(map(self.ExpandSpecial, + spec.get('libraries', []))) + if self.flavor == 'mac': + libraries = self.xcode_settings.AdjustLibraries(libraries, config_name) + elif self.flavor == 'win': + libraries = self.msvs_settings.AdjustLibraries(libraries) + + self.WriteVariableList(ninja_file, 'libs', library_dirs + libraries) + + linked_binary = output + + if command in ('solink', 'solink_module'): + extra_bindings.append(('soname', os.path.split(output)[1])) + extra_bindings.append(('lib', + gyp.common.EncodePOSIXShellArgument(output))) + if self.flavor != 'win': + link_file_list = output + if self.is_mac_bundle: + # 'Dependency Framework.framework/Versions/A/Dependency Framework' -> + # 'Dependency Framework.framework.rsp' + link_file_list = self.xcode_settings.GetWrapperName() + if arch: + link_file_list += '.' + arch + link_file_list += '.rsp' + # If an rspfile contains spaces, ninja surrounds the filename with + # quotes around it and then passes it to open(), creating a file with + # quotes in its name (and when looking for the rsp file, the name + # makes it through bash which strips the quotes) :-/ + link_file_list = link_file_list.replace(' ', '_') + extra_bindings.append( + ('link_file_list', + gyp.common.EncodePOSIXShellArgument(link_file_list))) + if self.flavor == 'win': + extra_bindings.append(('binary', output)) + if ('/NOENTRY' not in ldflags and + not self.msvs_settings.GetNoImportLibrary(config_name)): + 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))) + + ninja_file.build(output, command + command_suffix, link_deps, + implicit=list(implicit_deps), + order_only=list(order_deps), + variables=extra_bindings) + return linked_binary + + def WriteTarget(self, spec, config_name, config, link_deps, compile_deps): + extra_link_deps = any(self.target_outputs.get(dep).Linkable() + for dep in spec.get('dependencies', []) + if dep in self.target_outputs) + if spec['type'] == 'none' or (not link_deps and not extra_link_deps): + # TODO(evan): don't call this function for 'none' target types, as + # it doesn't do anything, and we fake out a 'binary' with a stamp file. + self.target.binary = compile_deps + self.target.type = 'none' + elif spec['type'] == 'static_library': + self.target.binary = self.ComputeOutput(spec) + if (self.flavor not in ('mac', 'openbsd', 'netbsd', 'win') and not + self.is_standalone_static_library): + self.ninja.build(self.target.binary, 'alink_thin', link_deps, + order_only=compile_deps) + else: + variables = [] + if self.xcode_settings: + libtool_flags = self.xcode_settings.GetLibtoolflags(config_name) + if libtool_flags: + variables.append(('libtool_flags', libtool_flags)) + if self.msvs_settings: + libflags = self.msvs_settings.GetLibFlags(config_name, + self.GypPathToNinja) + variables.append(('libflags', libflags)) + + if self.flavor != 'mac' or len(self.archs) == 1: + self.AppendPostbuildVariable(variables, spec, + self.target.binary, self.target.binary) + self.ninja.build(self.target.binary, 'alink', link_deps, + order_only=compile_deps, variables=variables) + else: + inputs = [] + for arch in self.archs: + output = self.ComputeOutput(spec, arch) + self.arch_subninjas[arch].build(output, 'alink', link_deps[arch], + order_only=compile_deps, + variables=variables) + inputs.append(output) + # TODO: It's not clear if libtool_flags should be passed to the alink + # call that combines single-arch .a files into a fat .a file. + self.AppendPostbuildVariable(variables, spec, + self.target.binary, self.target.binary) + self.ninja.build(self.target.binary, 'alink', inputs, + # FIXME: test proving order_only=compile_deps isn't + # needed. + variables=variables) + else: + self.target.binary = self.WriteLink(spec, config_name, config, link_deps) + return self.target.binary + + def WriteMacBundle(self, spec, mac_bundle_depends, is_empty): + assert self.is_mac_bundle + package_framework = spec['type'] in ('shared_library', 'loadable_module') + output = self.ComputeMacBundleOutput() + if is_empty: + output += '.stamp' + variables = [] + self.AppendPostbuildVariable(variables, spec, output, self.target.binary, + is_command_start=not package_framework) + if package_framework and not is_empty: + variables.append(('version', self.xcode_settings.GetFrameworkVersion())) + self.ninja.build(output, 'package_framework', mac_bundle_depends, + variables=variables) + else: + self.ninja.build(output, 'stamp', mac_bundle_depends, + variables=variables) + self.target.bundle = output + return output + + def GetToolchainEnv(self, additional_settings=None): + """Returns the variables toolchain would set for build steps.""" + env = self.GetSortedXcodeEnv(additional_settings=additional_settings) + if self.flavor == 'win': + env = self.GetMsvsToolchainEnv( + additional_settings=additional_settings) + return env + + def GetMsvsToolchainEnv(self, additional_settings=None): + """Returns the variables Visual Studio would set for build steps.""" + return self.msvs_settings.GetVSMacroEnv('$!PRODUCT_DIR', + config=self.config_name) + + def GetSortedXcodeEnv(self, additional_settings=None): + """Returns the variables Xcode would set for build steps.""" + assert self.abs_build_dir + abs_build_dir = self.abs_build_dir + return gyp.xcode_emulation.GetSortedXcodeEnv( + self.xcode_settings, abs_build_dir, + os.path.join(abs_build_dir, self.build_to_base), self.config_name, + additional_settings) + + def GetSortedXcodePostbuildEnv(self): + """Returns the variables Xcode would set for postbuild steps.""" + postbuild_settings = {} + # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack. + # TODO(thakis): It would be nice to have some general mechanism instead. + strip_save_file = self.xcode_settings.GetPerTargetSetting( + 'CHROMIUM_STRIP_SAVE_FILE') + if strip_save_file: + postbuild_settings['CHROMIUM_STRIP_SAVE_FILE'] = strip_save_file + return self.GetSortedXcodeEnv(additional_settings=postbuild_settings) + + def AppendPostbuildVariable(self, variables, spec, output, binary, + is_command_start=False): + """Adds a 'postbuild' variable if there is a postbuild for |output|.""" + postbuild = self.GetPostbuildCommand(spec, output, binary, is_command_start) + if postbuild: + variables.append(('postbuilds', postbuild)) + + def GetPostbuildCommand(self, spec, output, output_binary, is_command_start): + """Returns a shell command that runs all the postbuilds, and removes + |output| if any of them fails. If |is_command_start| is False, then the + returned string will start with ' && '.""" + if not self.xcode_settings or spec['type'] == 'none' or not output: + return '' + output = QuoteShellArgument(output, self.flavor) + postbuilds = gyp.xcode_emulation.GetSpecPostbuildCommands(spec, quiet=True) + if output_binary is not None: + postbuilds = self.xcode_settings.AddImplicitPostbuilds( + self.config_name, + os.path.normpath(os.path.join(self.base_to_build, output)), + QuoteShellArgument( + os.path.normpath(os.path.join(self.base_to_build, output_binary)), + self.flavor), + postbuilds, quiet=True) + + if not postbuilds: + return '' + # Postbuilds expect to be run in the gyp file's directory, so insert an + # implicit postbuild to cd to there. + postbuilds.insert(0, gyp.common.EncodePOSIXShellList( + ['cd', self.build_to_base])) + env = self.ComputeExportEnvString(self.GetSortedXcodePostbuildEnv()) + # G will be non-null if any postbuild fails. Run all postbuilds in a + # subshell. + commands = env + ' (' + \ + ' && '.join([ninja_syntax.escape(command) for command in postbuilds]) + command_string = (commands + '); G=$$?; ' + # Remove the final output if any postbuild failed. + '((exit $$G) || rm -rf %s) ' % output + '&& exit $$G)') + if is_command_start: + return '(' + command_string + ' && ' + else: + return '$ && (' + command_string + + def ComputeExportEnvString(self, env): + """Given an environment, returns a string looking like + 'export FOO=foo; export BAR="${FOO} bar;' + that exports |env| to the shell.""" + export_str = [] + for k, v in env: + export_str.append('export %s=%s;' % + (k, ninja_syntax.escape(gyp.common.EncodePOSIXShellArgument(v)))) + return ' '.join(export_str) + + def ComputeMacBundleOutput(self): + """Return the 'output' (full output path) to a bundle output directory.""" + assert self.is_mac_bundle + path = generator_default_variables['PRODUCT_DIR'] + return self.ExpandSpecial( + os.path.join(path, self.xcode_settings.GetWrapperName())) + + def ComputeOutputFileName(self, spec, type=None): + """Compute the filename of the final output for the current target.""" + if not type: + type = spec['type'] + + default_variables = copy.copy(generator_default_variables) + CalculateVariables(default_variables, {'flavor': self.flavor}) + + # Compute filename prefix: the product prefix, or a default for + # the product type. + DEFAULT_PREFIX = { + 'loadable_module': default_variables['SHARED_LIB_PREFIX'], + 'shared_library': default_variables['SHARED_LIB_PREFIX'], + 'static_library': default_variables['STATIC_LIB_PREFIX'], + 'executable': default_variables['EXECUTABLE_PREFIX'], + } + prefix = spec.get('product_prefix', DEFAULT_PREFIX.get(type, '')) + + # Compute filename extension: the product extension, or a default + # for the product type. + DEFAULT_EXTENSION = { + 'loadable_module': default_variables['SHARED_LIB_SUFFIX'], + 'shared_library': default_variables['SHARED_LIB_SUFFIX'], + 'static_library': default_variables['STATIC_LIB_SUFFIX'], + 'executable': default_variables['EXECUTABLE_SUFFIX'], + } + extension = spec.get('product_extension') + if extension: + extension = '.' + extension + else: + extension = DEFAULT_EXTENSION.get(type, '') + + if 'product_name' in spec: + # If we were given an explicit name, use that. + target = spec['product_name'] + else: + # Otherwise, derive a name from the target name. + target = spec['target_name'] + if prefix == 'lib': + # Snip out an extra 'lib' from libs if appropriate. + target = StripPrefix(target, 'lib') + + if type in ('static_library', 'loadable_module', 'shared_library', + 'executable'): + return '%s%s%s' % (prefix, target, extension) + elif type == 'none': + return '%s.stamp' % target + else: + raise Exception('Unhandled output type %s' % type) + + def ComputeOutput(self, spec, arch=None): + """Compute the path for the final output of the spec.""" + type = spec['type'] + + if self.flavor == 'win': + override = self.msvs_settings.GetOutputName(self.config_name, + self.ExpandSpecial) + if override: + return override + + if arch is None and self.flavor == 'mac' and type in ( + 'static_library', 'executable', 'shared_library', 'loadable_module'): + filename = self.xcode_settings.GetExecutablePath() + else: + filename = self.ComputeOutputFileName(spec, type) + + if arch is None and 'product_dir' in spec: + path = os.path.join(spec['product_dir'], filename) + return self.ExpandSpecial(path) + + # Some products go into the output root, libraries go into shared library + # dir, and everything else goes into the normal place. + type_in_output_root = ['executable', 'loadable_module'] + if self.flavor == 'mac' and self.toolset == 'target': + type_in_output_root += ['shared_library', 'static_library'] + elif self.flavor == 'win' and self.toolset == 'target': + type_in_output_root += ['shared_library'] + + if arch is not None: + # Make sure partial executables don't end up in a bundle or the regular + # output directory. + archdir = 'arch' + if self.toolset != 'target': + archdir = os.path.join('arch', '%s' % self.toolset) + return os.path.join(archdir, AddArch(filename, arch)) + elif type in type_in_output_root or self.is_standalone_static_library: + return filename + elif type == 'shared_library': + libdir = 'lib' + if self.toolset != 'target': + libdir = os.path.join('lib', '%s' % self.toolset) + return os.path.join(libdir, filename) + else: + return self.GypPathToUniqueOutput(filename, qualified=False) + + def WriteVariableList(self, ninja_file, var, values): + assert not isinstance(values, str) + if values is None: + values = [] + ninja_file.variable(var, ' '.join(values)) + + def WriteNewNinjaRule(self, name, args, description, is_cygwin, env, pool, + depfile=None): + """Write out a new ninja "rule" statement for a given command. + + Returns the name of the new rule, and a copy of |args| with variables + expanded.""" + + if self.flavor == 'win': + args = [self.msvs_settings.ConvertVSMacros( + arg, self.base_to_build, config=self.config_name) + for arg in args] + description = self.msvs_settings.ConvertVSMacros( + description, config=self.config_name) + elif self.flavor == 'mac': + # |env| is an empty list on non-mac. + args = [gyp.xcode_emulation.ExpandEnvVars(arg, env) for arg in args] + description = gyp.xcode_emulation.ExpandEnvVars(description, env) + + # TODO: we shouldn't need to qualify names; we do it because + # currently the ninja rule namespace is global, but it really + # should be scoped to the subninja. + rule_name = self.name + if self.toolset == 'target': + rule_name += '.' + self.toolset + rule_name += '.' + name + rule_name = re.sub('[^a-zA-Z0-9_]', '_', rule_name) + + # Remove variable references, but not if they refer to the magic rule + # variables. This is not quite right, as it also protects these for + # actions, not just for rules where they are valid. Good enough. + protect = [ '${root}', '${dirname}', '${source}', '${ext}', '${name}' ] + protect = '(?!' + '|'.join(map(re.escape, protect)) + ')' + description = re.sub(protect + r'\$', '_', description) + + # gyp dictates that commands are run from the base directory. + # cd into the directory before running, and adjust paths in + # the arguments to point to the proper locations. + rspfile = None + rspfile_content = None + args = [self.ExpandSpecial(arg, self.base_to_build) for arg in args] + if self.flavor == 'win': + rspfile = rule_name + '.$unique_name.rsp' + # The cygwin case handles this inside the bash sub-shell. + run_in = '' if is_cygwin else ' ' + self.build_to_base + if is_cygwin: + rspfile_content = self.msvs_settings.BuildCygwinBashCommandLine( + args, self.build_to_base) + else: + rspfile_content = gyp.msvs_emulation.EncodeRspFileList(args) + command = ('%s gyp-win-tool action-wrapper $arch ' % sys.executable + + rspfile + run_in) + else: + env = self.ComputeExportEnvString(env) + command = gyp.common.EncodePOSIXShellList(args) + command = 'cd %s; ' % self.build_to_base + env + command + + # GYP rules/actions express being no-ops by not touching their outputs. + # Avoid executing downstream dependencies in this case by specifying + # restat=1 to ninja. + self.ninja.rule(rule_name, command, description, depfile=depfile, + restat=True, pool=pool, + rspfile=rspfile, rspfile_content=rspfile_content) + self.ninja.newline() + + return rule_name, args + + +def CalculateVariables(default_variables, params): + """Calculate additional variables for use in the build (called by gyp).""" + global generator_additional_non_configuration_keys + global generator_additional_path_sections + flavor = gyp.common.GetFlavor(params) + if flavor == 'mac': + default_variables.setdefault('OS', 'mac') + default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib') + default_variables.setdefault('SHARED_LIB_DIR', + generator_default_variables['PRODUCT_DIR']) + default_variables.setdefault('LIB_DIR', + generator_default_variables['PRODUCT_DIR']) + + # Copy additional generator configuration data from Xcode, which is shared + # by the Mac Ninja generator. + import gyp.generator.xcode as xcode_generator + generator_additional_non_configuration_keys = getattr(xcode_generator, + 'generator_additional_non_configuration_keys', []) + generator_additional_path_sections = getattr(xcode_generator, + 'generator_additional_path_sections', []) + global generator_extra_sources_for_rules + generator_extra_sources_for_rules = getattr(xcode_generator, + 'generator_extra_sources_for_rules', []) + elif flavor == 'win': + exts = gyp.MSVSUtil.TARGET_TYPE_EXT + default_variables.setdefault('OS', 'win') + default_variables['EXECUTABLE_SUFFIX'] = '.' + exts['executable'] + default_variables['STATIC_LIB_PREFIX'] = '' + default_variables['STATIC_LIB_SUFFIX'] = '.' + exts['static_library'] + default_variables['SHARED_LIB_PREFIX'] = '' + default_variables['SHARED_LIB_SUFFIX'] = '.' + exts['shared_library'] + + # Copy additional generator configuration data from VS, which is shared + # by the Windows Ninja generator. + import gyp.generator.msvs as msvs_generator + generator_additional_non_configuration_keys = getattr(msvs_generator, + 'generator_additional_non_configuration_keys', []) + generator_additional_path_sections = getattr(msvs_generator, + 'generator_additional_path_sections', []) + + gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) + else: + operating_system = flavor + if flavor == 'android': + operating_system = 'linux' # Keep this legacy behavior for now. + default_variables.setdefault('OS', operating_system) + default_variables.setdefault('SHARED_LIB_SUFFIX', '.so') + default_variables.setdefault('SHARED_LIB_DIR', + os.path.join('$!PRODUCT_DIR', 'lib')) + default_variables.setdefault('LIB_DIR', + os.path.join('$!PRODUCT_DIR', 'obj')) + +def ComputeOutputDir(params): + """Returns the path from the toplevel_dir to the build output directory.""" + # generator_dir: relative path from pwd to where make puts build files. + # Makes migrating from make to ninja easier, ninja doesn't put anything here. + generator_dir = os.path.relpath(params['options'].generator_output or '.') + + # output_dir: relative path from generator_dir to the build directory. + output_dir = params.get('generator_flags', {}).get('output_dir', 'out') + + # Relative path from source root to our output files. e.g. "out" + return os.path.normpath(os.path.join(generator_dir, output_dir)) + + +def CalculateGeneratorInputInfo(params): + """Called by __init__ to initialize generator values based on params.""" + # E.g. "out/gypfiles" + toplevel = params['options'].toplevel_dir + qualified_out_dir = os.path.normpath(os.path.join( + toplevel, ComputeOutputDir(params), 'gypfiles')) + + global generator_filelist_paths + generator_filelist_paths = { + 'toplevel': toplevel, + 'qualified_out_dir': qualified_out_dir, + } + + +def OpenOutput(path, mode='w'): + """Open |path| for writing, creating directories if necessary.""" + gyp.common.EnsureDirExists(path) + return open(path, mode) + + +def CommandWithWrapper(cmd, wrappers, prog): + wrapper = wrappers.get(cmd, '') + if wrapper: + return wrapper + ' ' + prog + return prog + + +def GetDefaultConcurrentLinks(): + """Returns a best-guess for a number of concurrent links.""" + pool_size = int(os.environ.get('GYP_LINK_CONCURRENCY', 0)) + if pool_size: + return pool_size + + if sys.platform in ('win32', 'cygwin'): + import ctypes + + class MEMORYSTATUSEX(ctypes.Structure): + _fields_ = [ + ("dwLength", ctypes.c_ulong), + ("dwMemoryLoad", ctypes.c_ulong), + ("ullTotalPhys", ctypes.c_ulonglong), + ("ullAvailPhys", ctypes.c_ulonglong), + ("ullTotalPageFile", ctypes.c_ulonglong), + ("ullAvailPageFile", ctypes.c_ulonglong), + ("ullTotalVirtual", ctypes.c_ulonglong), + ("ullAvailVirtual", ctypes.c_ulonglong), + ("sullAvailExtendedVirtual", ctypes.c_ulonglong), + ] + + stat = MEMORYSTATUSEX() + stat.dwLength = ctypes.sizeof(stat) + ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat)) + + # VS 2015 uses 20% more working set than VS 2013 and can consume all RAM + # on a 64 GB machine. + mem_limit = max(1, stat.ullTotalPhys / (5 * (2 ** 30))) # total / 5GB + hard_cap = max(1, int(os.environ.get('GYP_LINK_CONCURRENCY_MAX', 2**32))) + return min(mem_limit, hard_cap) + elif sys.platform.startswith('linux'): + if os.path.exists("/proc/meminfo"): + with open("/proc/meminfo") as meminfo: + memtotal_re = re.compile(r'^MemTotal:\s*(\d*)\s*kB') + for line in meminfo: + match = memtotal_re.match(line) + if not match: + continue + # Allow 8Gb per link on Linux because Gold is quite memory hungry + return max(1, int(match.group(1)) / (8 * (2 ** 20))) + return 1 + elif sys.platform == 'darwin': + try: + avail_bytes = int(subprocess.check_output(['sysctl', '-n', 'hw.memsize'])) + # A static library debug build of Chromium's unit_tests takes ~2.7GB, so + # 4GB per ld process allows for some more bloat. + return max(1, avail_bytes / (4 * (2 ** 30))) # total / 4GB + except: + return 1 + else: + # TODO(scottmg): Implement this for other platforms. + return 1 + + +def _GetWinLinkRuleNameSuffix(embed_manifest): + """Returns the suffix used to select an appropriate linking rule depending on + whether the manifest embedding is enabled.""" + return '_embed' if embed_manifest else '' + + +def _AddWinLinkRules(master_ninja, embed_manifest): + """Adds link rules for Windows platform to |master_ninja|.""" + def FullLinkCommand(ldcmd, out, binary_type): + resource_name = { + 'exe': '1', + 'dll': '2', + }[binary_type] + 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='$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='$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 %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 $binary' % rule_name_suffix.upper(), + command=exe_cmd, + rspfile='$binary.rsp', + rspfile_content='$in_newline $libs $ldflags', + pool='link_pool') + + +def GenerateOutputForConfig(target_list, target_dicts, data, params, + config_name): + options = params['options'] + flavor = gyp.common.GetFlavor(params) + generator_flags = params.get('generator_flags', {}) + + # build_dir: relative path from source root to our output files. + # e.g. "out/Debug" + build_dir = os.path.normpath( + os.path.join(ComputeOutputDir(params), config_name)) + + toplevel_build = os.path.join(options.toplevel_dir, build_dir) + + 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) + + # Grab make settings for CC/CXX. + # The rules are + # - The priority from low to high is gcc/g++, the 'make_global_settings' in + # gyp, the environment variable. + # - If there is no 'make_global_settings' for CC.host/CXX.host or + # 'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set + # to cc/cxx. + if flavor == 'win': + ar = 'lib.exe' + # cc and cxx must be set to the correct architecture by overriding with one + # of cl_x86 or cl_x64 below. + cc = 'UNSET' + cxx = 'UNSET' + ld = 'link.exe' + ld_host = '$ld' + else: + ar = 'ar' + cc = 'cc' + cxx = 'c++' + ld = '$cc' + ldxx = '$cxx' + ld_host = '$cc_host' + ldxx_host = '$cxx_host' + + ar_host = 'ar' + cc_host = None + cxx_host = None + cc_host_global_setting = None + cxx_host_global_setting = None + clang_cl = None + nm = 'nm' + nm_host = 'nm' + readelf = 'readelf' + readelf_host = 'readelf' + + build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) + make_global_settings = data[build_file].get('make_global_settings', []) + build_to_root = gyp.common.InvertRelativePath(build_dir, + options.toplevel_dir) + wrappers = {} + for key, value in make_global_settings: + if key == 'AR': + ar = os.path.join(build_to_root, value) + if key == 'AR.host': + ar_host = os.path.join(build_to_root, value) + if key == 'CC': + cc = os.path.join(build_to_root, value) + if cc.endswith('clang-cl'): + clang_cl = cc + if key == 'CXX': + cxx = os.path.join(build_to_root, value) + if key == 'CC.host': + cc_host = os.path.join(build_to_root, value) + cc_host_global_setting = value + if key == 'CXX.host': + cxx_host = os.path.join(build_to_root, value) + cxx_host_global_setting = value + if key == 'LD': + ld = os.path.join(build_to_root, value) + if key == 'LD.host': + ld_host = os.path.join(build_to_root, value) + if key == 'LDXX': + ldxx = os.path.join(build_to_root, value) + if key == 'LDXX.host': + ldxx_host = os.path.join(build_to_root, value) + if key == 'NM': + nm = os.path.join(build_to_root, value) + if key == 'NM.host': + nm_host = os.path.join(build_to_root, value) + if key == 'READELF': + readelf = os.path.join(build_to_root, value) + if key == 'READELF.host': + readelf_host = os.path.join(build_to_root, value) + if key.endswith('_wrapper'): + wrappers[key[:-len('_wrapper')]] = os.path.join(build_to_root, value) + + # Support wrappers from environment variables too. + for key, value in os.environ.iteritems(): + if key.lower().endswith('_wrapper'): + key_prefix = key[:-len('_wrapper')] + key_prefix = re.sub(r'\.HOST$', '.host', key_prefix) + wrappers[key_prefix] = os.path.join(build_to_root, value) + + if flavor == 'win': + configs = [target_dicts[qualified_target]['configurations'][config_name] + for qualified_target in target_list] + shared_system_includes = None + if not generator_flags.get('ninja_use_custom_environment_files', 0): + shared_system_includes = \ + gyp.msvs_emulation.ExtractSharedMSVSSystemIncludes( + configs, generator_flags) + cl_paths = gyp.msvs_emulation.GenerateEnvironmentFiles( + toplevel_build, generator_flags, shared_system_includes, OpenOutput) + for arch, path in cl_paths.iteritems(): + if clang_cl: + # If we have selected clang-cl, use that instead. + path = clang_cl + command = CommandWithWrapper('CC', wrappers, + QuoteShellArgument(path, 'win')) + if clang_cl: + # Use clang-cl to cross-compile for x86 or x86_64. + command += (' -m32' if arch == 'x86' else ' -m64') + master_ninja.variable('cl_' + arch, command) + + cc = GetEnvironFallback(['CC_target', 'CC'], cc) + master_ninja.variable('cc', CommandWithWrapper('CC', wrappers, cc)) + cxx = GetEnvironFallback(['CXX_target', 'CXX'], cxx) + master_ninja.variable('cxx', CommandWithWrapper('CXX', wrappers, cxx)) + + if flavor == 'win': + master_ninja.variable('ld', ld) + master_ninja.variable('idl', 'midl.exe') + master_ninja.variable('ar', ar) + master_ninja.variable('rc', 'rc.exe') + master_ninja.variable('ml_x86', 'ml.exe') + master_ninja.variable('ml_x64', 'ml64.exe') + master_ninja.variable('mt', 'mt.exe') + else: + master_ninja.variable('ld', CommandWithWrapper('LINK', wrappers, ld)) + master_ninja.variable('ldxx', CommandWithWrapper('LINK', wrappers, ldxx)) + master_ninja.variable('ar', GetEnvironFallback(['AR_target', 'AR'], ar)) + if flavor != 'mac': + # Mac does not use readelf/nm for .TOC generation, so avoiding polluting + # the master ninja with extra unused variables. + master_ninja.variable( + 'nm', GetEnvironFallback(['NM_target', 'NM'], nm)) + master_ninja.variable( + 'readelf', GetEnvironFallback(['READELF_target', 'READELF'], readelf)) + + if generator_supports_multiple_toolsets: + if not cc_host: + cc_host = cc + if not cxx_host: + cxx_host = cxx + + master_ninja.variable('ar_host', GetEnvironFallback(['AR_host'], ar_host)) + master_ninja.variable('nm_host', GetEnvironFallback(['NM_host'], nm_host)) + master_ninja.variable('readelf_host', + GetEnvironFallback(['READELF_host'], readelf_host)) + cc_host = GetEnvironFallback(['CC_host'], cc_host) + cxx_host = GetEnvironFallback(['CXX_host'], cxx_host) + + # The environment variable could be used in 'make_global_settings', like + # ['CC.host', '$(CC)'] or ['CXX.host', '$(CXX)'], transform them here. + if '$(CC)' in cc_host and cc_host_global_setting: + cc_host = cc_host_global_setting.replace('$(CC)', cc) + if '$(CXX)' in cxx_host and cxx_host_global_setting: + cxx_host = cxx_host_global_setting.replace('$(CXX)', cxx) + master_ninja.variable('cc_host', + CommandWithWrapper('CC.host', wrappers, cc_host)) + master_ninja.variable('cxx_host', + CommandWithWrapper('CXX.host', wrappers, cxx_host)) + if flavor == 'win': + master_ninja.variable('ld_host', ld_host) + master_ninja.variable('ldxx_host', ldxx_host) + else: + master_ninja.variable('ld_host', CommandWithWrapper( + 'LINK', wrappers, ld_host)) + master_ninja.variable('ldxx_host', CommandWithWrapper( + 'LINK', wrappers, ldxx_host)) + + master_ninja.newline() + + master_ninja.pool('link_pool', depth=GetDefaultConcurrentLinks()) + master_ninja.newline() + + deps = 'msvc' if flavor == 'win' else 'gcc' + + if flavor != 'win': + master_ninja.rule( + 'cc', + description='CC $out', + command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c ' + '$cflags_pch_c -c $in -o $out'), + depfile='$out.d', + deps=deps) + master_ninja.rule( + 'cc_s', + description='CC $out', + command=('$cc $defines $includes $cflags $cflags_c ' + '$cflags_pch_c -c $in -o $out')) + master_ninja.rule( + 'cxx', + description='CXX $out', + command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc ' + '$cflags_pch_cc -c $in -o $out'), + 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_c ') + cxx_command = ('ninja -t msvc -e $arch ' + + '-- ' + '$cxx /nologo /showIncludes /FC ' + '@$out.rsp /c $in /Fo$out /Fd$pdbname_cc ') + master_ninja.rule( + 'cc', + description='CC $out', + command=cc_command, + rspfile='$out.rsp', + rspfile_content='$defines $includes $cflags $cflags_c', + deps=deps) + master_ninja.rule( + 'cxx', + description='CXX $out', + command=cxx_command, + rspfile='$out.rsp', + rspfile_content='$defines $includes $cflags $cflags_cc', + deps=deps) + master_ninja.rule( + 'idl', + description='IDL $in', + command=('%s gyp-win-tool midl-wrapper $arch $outdir ' + '$tlb $h $dlldata $iid $proxy $in ' + '$midl_includes $idlflags' % sys.executable)) + master_ninja.rule( + 'rc', + description='RC $in', + # Note: $in must be last otherwise rc.exe complains. + command=('%s gyp-win-tool rc-wrapper ' + '$arch $rc $defines $resource_includes $rcflags /fo$out $in' % + sys.executable)) + master_ninja.rule( + 'asm', + description='ASM $out', + command=('%s gyp-win-tool asm-wrapper ' + '$arch $asm $defines $includes $asmflags /c /Fo $out $in' % + sys.executable)) + + if flavor != 'mac' and flavor != 'win': + master_ninja.rule( + 'alink', + description='AR $out', + command='rm -f $out && $ar rcs $arflags $out $in') + master_ninja.rule( + 'alink_thin', + description='AR $out', + command='rm -f $out && $ar rcsT $arflags $out $in') + + # This allows targets that only need to depend on $lib's API to declare an + # order-only dependency on $lib.TOC and avoid relinking such downstream + # dependencies when $lib changes only in non-public ways. + # The resulting string leaves an uninterpolated %{suffix} which + # is used in the final substitution below. + mtime_preserving_solink_base = ( + 'if [ ! -e $lib -o ! -e $lib.TOC ]; then ' + '%(solink)s && %(extract_toc)s > $lib.TOC; else ' + '%(solink)s && %(extract_toc)s > $lib.tmp && ' + 'if ! cmp -s $lib.tmp $lib.TOC; then mv $lib.tmp $lib.TOC ; ' + 'fi; fi' + % { 'solink': + '$ld -shared $ldflags -o $lib -Wl,-soname=$soname %(suffix)s', + 'extract_toc': + ('{ $readelf -d $lib | grep SONAME ; ' + '$nm -gD -f p $lib | cut -f1-2 -d\' \'; }')}) + + master_ninja.rule( + 'solink', + description='SOLINK $lib', + restat=True, + command=mtime_preserving_solink_base % {'suffix': '@$link_file_list'}, + rspfile='$link_file_list', + rspfile_content= + '-Wl,--whole-archive $in $solibs -Wl,--no-whole-archive $libs', + pool='link_pool') + master_ninja.rule( + 'solink_module', + description='SOLINK(module) $lib', + restat=True, + command=mtime_preserving_solink_base % {'suffix': '@$link_file_list'}, + rspfile='$link_file_list', + rspfile_content='-Wl,--start-group $in $solibs $libs -Wl,--end-group', + pool='link_pool') + master_ninja.rule( + 'link', + description='LINK $out', + command=('$ld $ldflags -o $out ' + '-Wl,--start-group $in $solibs $libs -Wl,--end-group'), + pool='link_pool') + elif flavor == 'win': + master_ninja.rule( + 'alink', + description='LIB $out', + 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) + _AddWinLinkRules(master_ninja, embed_manifest=False) + else: + master_ninja.rule( + 'objc', + description='OBJC $out', + command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc ' + '$cflags_pch_objc -c $in -o $out'), + depfile='$out.d', + deps=deps) + master_ninja.rule( + 'objcxx', + description='OBJCXX $out', + command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_objcc ' + '$cflags_pch_objcc -c $in -o $out'), + depfile='$out.d', + deps=deps) + master_ninja.rule( + 'alink', + description='LIBTOOL-STATIC $out, POSTBUILDS', + command='rm -f $out && ' + './gyp-mac-tool filter-libtool libtool $libtool_flags ' + '-static -o $out $in' + '$postbuilds') + master_ninja.rule( + 'lipo', + description='LIPO $out, POSTBUILDS', + command='rm -f $out && lipo -create $in -output $out$postbuilds') + master_ninja.rule( + 'solipo', + description='SOLIPO $out, POSTBUILDS', + command=( + 'rm -f $lib $lib.TOC && lipo -create $in -output $lib$postbuilds &&' + '%(extract_toc)s > $lib.TOC' + % { 'extract_toc': + '{ otool -l $lib | grep LC_ID_DYLIB -A 5; ' + 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'})) + + + # Record the public interface of $lib in $lib.TOC. See the corresponding + # comment in the posix section above for details. + solink_base = '$ld %(type)s $ldflags -o $lib %(suffix)s' + mtime_preserving_solink_base = ( + 'if [ ! -e $lib -o ! -e $lib.TOC ] || ' + # Always force dependent targets to relink if this library + # reexports something. Handling this correctly would require + # recursive TOC dumping but this is rare in practice, so punt. + 'otool -l $lib | grep -q LC_REEXPORT_DYLIB ; then ' + '%(solink)s && %(extract_toc)s > $lib.TOC; ' + 'else ' + '%(solink)s && %(extract_toc)s > $lib.tmp && ' + 'if ! cmp -s $lib.tmp $lib.TOC; then ' + 'mv $lib.tmp $lib.TOC ; ' + 'fi; ' + 'fi' + % { 'solink': solink_base, + 'extract_toc': + '{ otool -l $lib | grep LC_ID_DYLIB -A 5; ' + 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'}) + + + solink_suffix = '@$link_file_list$postbuilds' + master_ninja.rule( + 'solink', + description='SOLINK $lib, POSTBUILDS', + restat=True, + command=mtime_preserving_solink_base % {'suffix': solink_suffix, + 'type': '-shared'}, + rspfile='$link_file_list', + rspfile_content='$in $solibs $libs', + pool='link_pool') + master_ninja.rule( + 'solink_notoc', + description='SOLINK $lib, POSTBUILDS', + restat=True, + command=solink_base % {'suffix':solink_suffix, 'type': '-shared'}, + rspfile='$link_file_list', + rspfile_content='$in $solibs $libs', + pool='link_pool') + + master_ninja.rule( + 'solink_module', + description='SOLINK(module) $lib, POSTBUILDS', + restat=True, + command=mtime_preserving_solink_base % {'suffix': solink_suffix, + 'type': '-bundle'}, + rspfile='$link_file_list', + rspfile_content='$in $solibs $libs', + pool='link_pool') + master_ninja.rule( + 'solink_module_notoc', + description='SOLINK(module) $lib, POSTBUILDS', + restat=True, + command=solink_base % {'suffix': solink_suffix, 'type': '-bundle'}, + rspfile='$link_file_list', + rspfile_content='$in $solibs $libs', + pool='link_pool') + + master_ninja.rule( + 'link', + description='LINK $out, POSTBUILDS', + command=('$ld $ldflags -o $out ' + '$in $solibs $libs$postbuilds'), + pool='link_pool') + master_ninja.rule( + 'preprocess_infoplist', + description='PREPROCESS INFOPLIST $out', + command=('$cc -E -P -Wno-trigraphs -x c $defines $in -o $out && ' + 'plutil -convert xml1 $out $out')) + master_ninja.rule( + 'copy_infoplist', + description='COPY INFOPLIST $in', + command='$env ./gyp-mac-tool copy-info-plist $in $out $binary $keys') + master_ninja.rule( + 'merge_infoplist', + description='MERGE INFOPLISTS $in', + command='$env ./gyp-mac-tool merge-info-plist $out $in') + master_ninja.rule( + 'compile_xcassets', + description='COMPILE XCASSETS $in', + command='$env ./gyp-mac-tool compile-xcassets $keys $in') + master_ninja.rule( + 'mac_tool', + description='MACTOOL $mactool_cmd $in', + command='$env ./gyp-mac-tool $mactool_cmd $in $out $binary') + master_ninja.rule( + 'package_framework', + description='PACKAGE FRAMEWORK $out, POSTBUILDS', + command='./gyp-mac-tool package-framework $out $version$postbuilds ' + '&& touch $out') + if flavor == 'win': + master_ninja.rule( + 'stamp', + description='STAMP $out', + command='%s gyp-win-tool stamp $out' % sys.executable) + else: + master_ninja.rule( + 'stamp', + description='STAMP $out', + command='${postbuilds}touch $out') + if flavor == 'win': + master_ninja.rule( + 'copy', + description='COPY $in $out', + command='%s gyp-win-tool recursive-mirror $in $out' % sys.executable) + elif flavor == 'zos': + master_ninja.rule( + 'copy', + description='COPY $in $out', + command='rm -rf $out && cp -fRP $in $out') + else: + master_ninja.rule( + 'copy', + description='COPY $in $out', + command='rm -rf $out && cp -af $in $out') + master_ninja.newline() + + all_targets = set() + for build_file in params['build_files']: + for target in gyp.common.AllTargets(target_list, + target_dicts, + os.path.normpath(build_file)): + all_targets.add(target) + all_outputs = set() + + # target_outputs is a map from qualified target name to a Target object. + target_outputs = {} + # target_short_names is a map from target short name to a list of Target + # objects. + target_short_names = {} + + # short name of targets that were skipped because they didn't contain anything + # interesting. + # NOTE: there may be overlap between this an non_empty_target_names. + empty_target_names = set() + + # Set of non-empty short target names. + # NOTE: there may be overlap between this an empty_target_names. + non_empty_target_names = set() + + for qualified_target in target_list: + # qualified_target is like: third_party/icu/icu.gyp:icui18n#target + build_file, name, toolset = \ + gyp.common.ParseQualifiedTarget(qualified_target) + + 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. %s vs. %s" % + (this_make_global_settings, make_global_settings)) + + spec = target_dicts[qualified_target] + if flavor == 'mac': + gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec) + + # If build_file is a symlink, we must not follow it because there's a chance + # it could point to a path above toplevel_dir, and we cannot correctly deal + # with that case at the moment. + build_file = gyp.common.RelativePath(build_file, options.toplevel_dir, + False) + + qualified_target_for_hash = gyp.common.QualifiedTarget(build_file, name, + toolset) + hash_for_rules = hashlib.md5(qualified_target_for_hash).hexdigest() + + base_path = os.path.dirname(build_file) + obj = 'obj' + if toolset != 'target': + obj += '.' + toolset + output_file = os.path.join(obj, base_path, name + '.ninja') + + ninja_output = StringIO() + writer = NinjaWriter(hash_for_rules, target_outputs, base_path, build_dir, + ninja_output, + toplevel_build, output_file, + flavor, toplevel_dir=options.toplevel_dir) + + target = writer.WriteSpec(spec, config_name, generator_flags) + + if ninja_output.tell() > 0: + # Only create files for ninja files that actually have contents. + with OpenOutput(os.path.join(toplevel_build, output_file)) as ninja_file: + ninja_file.write(ninja_output.getvalue()) + ninja_output.close() + master_ninja.subninja(output_file) + + if target: + if name != target.FinalOutput() and spec['toolset'] == 'target': + target_short_names.setdefault(name, []).append(target) + target_outputs[qualified_target] = target + if qualified_target in all_targets: + all_outputs.add(target.FinalOutput()) + non_empty_target_names.add(name) + else: + empty_target_names.add(name) + + if target_short_names: + # Write a short name to build this target. This benefits both the + # "build chrome" case as well as the gyp tests, which expect to be + # able to run actions and build libraries by their short name. + master_ninja.newline() + master_ninja.comment('Short names for targets.') + for short_name in target_short_names: + master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in + target_short_names[short_name]]) + + # Write phony targets for any empty targets that weren't written yet. As + # short names are not necessarily unique only do this for short names that + # haven't already been output for another target. + empty_target_names = empty_target_names - non_empty_target_names + if empty_target_names: + master_ninja.newline() + master_ninja.comment('Empty targets (output for completeness).') + for name in sorted(empty_target_names): + master_ninja.build(name, 'phony') + + if all_outputs: + master_ninja.newline() + 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'] + for config in configurations: + builddir = os.path.join(options.toplevel_dir, 'out', config) + arguments = ['ninja', '-C', builddir] + print 'Building [%s]: %s' % (config, 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): + # Update target_dicts for iOS device builds. + target_dicts = gyp.xcode_emulation.CloneConfigurationForDeviceAndEmulator( + target_dicts) + + user_config = params.get('generator_flags', {}).get('config', None) + if gyp.common.GetFlavor(params) == 'win': + target_list, target_dicts = MSVSUtil.ShardTargets(target_list, target_dicts) + target_list, target_dicts = MSVSUtil.InsertLargePdbShims( + target_list, target_dicts, generator_default_variables) + + 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/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py new file mode 100644 index 0000000000000..1767b2f45a04c --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py @@ -0,0 +1,47 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 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. + +""" Unit tests for the ninja.py file. """ + +import gyp.generator.ninja as ninja +import unittest +import StringIO +import sys +import TestCommon + + +class TestPrefixesAndSuffixes(unittest.TestCase): + def test_BinaryNamesWindows(self): + # These cannot run on non-Windows as they require a VS installation to + # correctly handle variable expansion. + if sys.platform.startswith('win'): + writer = ninja.NinjaWriter('foo', 'wee', '.', '.', 'build.ninja', '.', + 'build.ninja', 'win') + spec = { 'target_name': 'wee' } + self.assertTrue(writer.ComputeOutputFileName(spec, 'executable'). + endswith('.exe')) + self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). + endswith('.dll')) + self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). + endswith('.lib')) + + def test_BinaryNamesLinux(self): + writer = ninja.NinjaWriter('foo', 'wee', '.', '.', 'build.ninja', '.', + 'build.ninja', 'linux') + spec = { 'target_name': 'wee' } + self.assertTrue('.' not in writer.ComputeOutputFileName(spec, + 'executable')) + self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). + startswith('lib')) + self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). + startswith('lib')) + self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). + endswith('.so')) + self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). + endswith('.a')) + +if __name__ == '__main__': + unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py new file mode 100644 index 0000000000000..0e3fb9301ecb9 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py @@ -0,0 +1,1300 @@ +# Copyright (c) 2012 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. + +import filecmp +import gyp.common +import gyp.xcodeproj_file +import gyp.xcode_ninja +import errno +import os +import sys +import posixpath +import re +import shutil +import subprocess +import tempfile + + +# Project files generated by this module will use _intermediate_var as a +# custom Xcode setting whose value is a DerivedSources-like directory that's +# project-specific and configuration-specific. The normal choice, +# DERIVED_FILE_DIR, is target-specific, which is thought to be too restrictive +# as it is likely that multiple targets within a single project file will want +# to access the same set of generated files. The other option, +# PROJECT_DERIVED_FILE_DIR, is unsuitable because while it is project-specific, +# it is not configuration-specific. INTERMEDIATE_DIR is defined as +# $(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION). +_intermediate_var = 'INTERMEDIATE_DIR' + +# SHARED_INTERMEDIATE_DIR is the same, except that it is shared among all +# targets that share the same BUILT_PRODUCTS_DIR. +_shared_intermediate_var = 'SHARED_INTERMEDIATE_DIR' + +_library_search_paths_var = 'LIBRARY_SEARCH_PATHS' + +generator_default_variables = { + 'EXECUTABLE_PREFIX': '', + 'EXECUTABLE_SUFFIX': '', + 'STATIC_LIB_PREFIX': 'lib', + 'SHARED_LIB_PREFIX': 'lib', + 'STATIC_LIB_SUFFIX': '.a', + 'SHARED_LIB_SUFFIX': '.dylib', + # INTERMEDIATE_DIR is a place for targets to build up intermediate products. + # It is specific to each build environment. It is only guaranteed to exist + # and be constant within the context of a project, corresponding to a single + # input file. Some build environments may allow their intermediate directory + # to be shared on a wider scale, but this is not guaranteed. + 'INTERMEDIATE_DIR': '$(%s)' % _intermediate_var, + 'OS': 'mac', + 'PRODUCT_DIR': '$(BUILT_PRODUCTS_DIR)', + 'LIB_DIR': '$(BUILT_PRODUCTS_DIR)', + 'RULE_INPUT_ROOT': '$(INPUT_FILE_BASE)', + 'RULE_INPUT_EXT': '$(INPUT_FILE_SUFFIX)', + 'RULE_INPUT_NAME': '$(INPUT_FILE_NAME)', + 'RULE_INPUT_PATH': '$(INPUT_FILE_PATH)', + 'RULE_INPUT_DIRNAME': '$(INPUT_FILE_DIRNAME)', + 'SHARED_INTERMEDIATE_DIR': '$(%s)' % _shared_intermediate_var, + 'CONFIGURATION_NAME': '$(CONFIGURATION)', +} + +# The Xcode-specific sections that hold paths. +generator_additional_path_sections = [ + 'mac_bundle_resources', + 'mac_framework_headers', + 'mac_framework_private_headers', + # 'mac_framework_dirs', input already handles _dirs endings. +] + +# The Xcode-specific keys that exist on targets and aren't moved down to +# configurations. +generator_additional_non_configuration_keys = [ + 'ios_app_extension', + 'ios_watch_app', + 'ios_watchkit_extension', + 'mac_bundle', + 'mac_bundle_resources', + 'mac_framework_headers', + 'mac_framework_private_headers', + 'mac_xctest_bundle', + 'xcode_create_dependents_test_runner', +] + +# We want to let any rules apply to files that are resources also. +generator_extra_sources_for_rules = [ + 'mac_bundle_resources', + 'mac_framework_headers', + 'mac_framework_private_headers', +] + +generator_filelist_paths = None + +# Xcode's standard set of library directories, which don't need to be duplicated +# in LIBRARY_SEARCH_PATHS. This list is not exhaustive, but that's okay. +xcode_standard_library_dirs = frozenset([ + '$(SDKROOT)/usr/lib', + '$(SDKROOT)/usr/local/lib', +]) + +def CreateXCConfigurationList(configuration_names): + xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) + if len(configuration_names) == 0: + configuration_names = ['Default'] + for configuration_name in configuration_names: + xcbc = gyp.xcodeproj_file.XCBuildConfiguration({ + 'name': configuration_name}) + xccl.AppendProperty('buildConfigurations', xcbc) + xccl.SetProperty('defaultConfigurationName', configuration_names[0]) + return xccl + + +class XcodeProject(object): + def __init__(self, gyp_path, path, build_file_dict): + self.gyp_path = gyp_path + self.path = path + self.project = gyp.xcodeproj_file.PBXProject(path=path) + projectDirPath = gyp.common.RelativePath( + os.path.dirname(os.path.abspath(self.gyp_path)), + os.path.dirname(path) or '.') + self.project.SetProperty('projectDirPath', projectDirPath) + self.project_file = \ + gyp.xcodeproj_file.XCProjectFile({'rootObject': self.project}) + self.build_file_dict = build_file_dict + + # TODO(mark): add destructor that cleans up self.path if created_dir is + # True and things didn't complete successfully. Or do something even + # better with "try"? + self.created_dir = False + try: + os.makedirs(self.path) + self.created_dir = True + except OSError, e: + if e.errno != errno.EEXIST: + raise + + def Finalize1(self, xcode_targets, serialize_all_tests): + # Collect a list of all of the build configuration names used by the + # various targets in the file. It is very heavily advised to keep each + # target in an entire project (even across multiple project files) using + # the same set of configuration names. + configurations = [] + for xct in self.project.GetProperty('targets'): + xccl = xct.GetProperty('buildConfigurationList') + xcbcs = xccl.GetProperty('buildConfigurations') + for xcbc in xcbcs: + name = xcbc.GetProperty('name') + if name not in configurations: + configurations.append(name) + + # Replace the XCConfigurationList attached to the PBXProject object with + # a new one specifying all of the configuration names used by the various + # targets. + try: + xccl = CreateXCConfigurationList(configurations) + self.project.SetProperty('buildConfigurationList', xccl) + except: + sys.stderr.write("Problem with gyp file %s\n" % self.gyp_path) + raise + + # The need for this setting is explained above where _intermediate_var is + # defined. The comments below about wanting to avoid project-wide build + # settings apply here too, but this needs to be set on a project-wide basis + # so that files relative to the _intermediate_var setting can be displayed + # properly in the Xcode UI. + # + # Note that for configuration-relative files such as anything relative to + # _intermediate_var, for the purposes of UI tree view display, Xcode will + # only resolve the configuration name once, when the project file is + # opened. If the active build configuration is changed, the project file + # must be closed and reopened if it is desired for the tree view to update. + # This is filed as Apple radar 6588391. + xccl.SetBuildSetting(_intermediate_var, + '$(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION)') + xccl.SetBuildSetting(_shared_intermediate_var, + '$(SYMROOT)/DerivedSources/$(CONFIGURATION)') + + # Set user-specified project-wide build settings and config files. This + # is intended to be used very sparingly. Really, almost everything should + # go into target-specific build settings sections. The project-wide + # settings are only intended to be used in cases where Xcode attempts to + # resolve variable references in a project context as opposed to a target + # context, such as when resolving sourceTree references while building up + # the tree tree view for UI display. + # Any values set globally are applied to all configurations, then any + # per-configuration values are applied. + for xck, xcv in self.build_file_dict.get('xcode_settings', {}).iteritems(): + xccl.SetBuildSetting(xck, xcv) + if 'xcode_config_file' in self.build_file_dict: + config_ref = self.project.AddOrGetFileInRootGroup( + self.build_file_dict['xcode_config_file']) + xccl.SetBaseConfiguration(config_ref) + build_file_configurations = self.build_file_dict.get('configurations', {}) + if build_file_configurations: + for config_name in configurations: + build_file_configuration_named = \ + build_file_configurations.get(config_name, {}) + if build_file_configuration_named: + xcc = xccl.ConfigurationNamed(config_name) + for xck, xcv in build_file_configuration_named.get('xcode_settings', + {}).iteritems(): + xcc.SetBuildSetting(xck, xcv) + if 'xcode_config_file' in build_file_configuration_named: + config_ref = self.project.AddOrGetFileInRootGroup( + build_file_configurations[config_name]['xcode_config_file']) + xcc.SetBaseConfiguration(config_ref) + + # Sort the targets based on how they appeared in the input. + # TODO(mark): Like a lot of other things here, this assumes internal + # knowledge of PBXProject - in this case, of its "targets" property. + + # ordinary_targets are ordinary targets that are already in the project + # file. run_test_targets are the targets that run unittests and should be + # used for the Run All Tests target. support_targets are the action/rule + # targets used by GYP file targets, just kept for the assert check. + ordinary_targets = [] + run_test_targets = [] + support_targets = [] + + # targets is full list of targets in the project. + targets = [] + + # does the it define it's own "all"? + has_custom_all = False + + # targets_for_all is the list of ordinary_targets that should be listed + # in this project's "All" target. It includes each non_runtest_target + # that does not have suppress_wildcard set. + targets_for_all = [] + + for target in self.build_file_dict['targets']: + target_name = target['target_name'] + toolset = target['toolset'] + qualified_target = gyp.common.QualifiedTarget(self.gyp_path, target_name, + toolset) + xcode_target = xcode_targets[qualified_target] + # Make sure that the target being added to the sorted list is already in + # the unsorted list. + assert xcode_target in self.project._properties['targets'] + targets.append(xcode_target) + ordinary_targets.append(xcode_target) + if xcode_target.support_target: + support_targets.append(xcode_target.support_target) + targets.append(xcode_target.support_target) + + if not int(target.get('suppress_wildcard', False)): + targets_for_all.append(xcode_target) + + if target_name.lower() == 'all': + has_custom_all = True; + + # If this target has a 'run_as' attribute, add its target to the + # targets, and add it to the test targets. + if target.get('run_as'): + # Make a target to run something. It should have one + # dependency, the parent xcode target. + xccl = CreateXCConfigurationList(configurations) + run_target = gyp.xcodeproj_file.PBXAggregateTarget({ + 'name': 'Run ' + target_name, + 'productName': xcode_target.GetProperty('productName'), + 'buildConfigurationList': xccl, + }, + parent=self.project) + run_target.AddDependency(xcode_target) + + command = target['run_as'] + script = '' + if command.get('working_directory'): + script = script + 'cd "%s"\n' % \ + gyp.xcodeproj_file.ConvertVariablesToShellSyntax( + command.get('working_directory')) + + if command.get('environment'): + script = script + "\n".join( + ['export %s="%s"' % + (key, gyp.xcodeproj_file.ConvertVariablesToShellSyntax(val)) + for (key, val) in command.get('environment').iteritems()]) + "\n" + + # Some test end up using sockets, files on disk, etc. and can get + # confused if more then one test runs at a time. The generator + # flag 'xcode_serialize_all_test_runs' controls the forcing of all + # tests serially. It defaults to True. To get serial runs this + # little bit of python does the same as the linux flock utility to + # make sure only one runs at a time. + command_prefix = '' + if serialize_all_tests: + command_prefix = \ +"""python -c "import fcntl, subprocess, sys +file = open('$TMPDIR/GYP_serialize_test_runs', 'a') +fcntl.flock(file.fileno(), fcntl.LOCK_EX) +sys.exit(subprocess.call(sys.argv[1:]))" """ + + # If we were unable to exec for some reason, we want to exit + # with an error, and fixup variable references to be shell + # syntax instead of xcode syntax. + script = script + 'exec ' + command_prefix + '%s\nexit 1\n' % \ + gyp.xcodeproj_file.ConvertVariablesToShellSyntax( + gyp.common.EncodePOSIXShellList(command.get('action'))) + + ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ + 'shellScript': script, + 'showEnvVarsInLog': 0, + }) + run_target.AppendProperty('buildPhases', ssbp) + + # Add the run target to the project file. + targets.append(run_target) + run_test_targets.append(run_target) + xcode_target.test_runner = run_target + + + # Make sure that the list of targets being replaced is the same length as + # the one replacing it, but allow for the added test runner targets. + assert len(self.project._properties['targets']) == \ + len(ordinary_targets) + len(support_targets) + + self.project._properties['targets'] = targets + + # Get rid of unnecessary levels of depth in groups like the Source group. + self.project.RootGroupsTakeOverOnlyChildren(True) + + # Sort the groups nicely. Do this after sorting the targets, because the + # Products group is sorted based on the order of the targets. + self.project.SortGroups() + + # Create an "All" target if there's more than one target in this project + # file and the project didn't define its own "All" target. Put a generated + # "All" target first so that people opening up the project for the first + # time will build everything by default. + if len(targets_for_all) > 1 and not has_custom_all: + xccl = CreateXCConfigurationList(configurations) + all_target = gyp.xcodeproj_file.PBXAggregateTarget( + { + 'buildConfigurationList': xccl, + 'name': 'All', + }, + parent=self.project) + + for target in targets_for_all: + all_target.AddDependency(target) + + # TODO(mark): This is evil because it relies on internal knowledge of + # PBXProject._properties. It's important to get the "All" target first, + # though. + self.project._properties['targets'].insert(0, all_target) + + # The same, but for run_test_targets. + if len(run_test_targets) > 1: + xccl = CreateXCConfigurationList(configurations) + run_all_tests_target = gyp.xcodeproj_file.PBXAggregateTarget( + { + 'buildConfigurationList': xccl, + 'name': 'Run All Tests', + }, + parent=self.project) + for run_test_target in run_test_targets: + run_all_tests_target.AddDependency(run_test_target) + + # Insert after the "All" target, which must exist if there is more than + # one run_test_target. + self.project._properties['targets'].insert(1, run_all_tests_target) + + def Finalize2(self, xcode_targets, xcode_target_to_target_dict): + # Finalize2 needs to happen in a separate step because the process of + # updating references to other projects depends on the ordering of targets + # within remote project files. Finalize1 is responsible for sorting duty, + # and once all project files are sorted, Finalize2 can come in and update + # these references. + + # To support making a "test runner" target that will run all the tests + # that are direct dependents of any given target, we look for + # xcode_create_dependents_test_runner being set on an Aggregate target, + # and generate a second target that will run the tests runners found under + # the marked target. + for bf_tgt in self.build_file_dict['targets']: + if int(bf_tgt.get('xcode_create_dependents_test_runner', 0)): + tgt_name = bf_tgt['target_name'] + toolset = bf_tgt['toolset'] + qualified_target = gyp.common.QualifiedTarget(self.gyp_path, + tgt_name, toolset) + xcode_target = xcode_targets[qualified_target] + if isinstance(xcode_target, gyp.xcodeproj_file.PBXAggregateTarget): + # Collect all the run test targets. + all_run_tests = [] + pbxtds = xcode_target.GetProperty('dependencies') + for pbxtd in pbxtds: + pbxcip = pbxtd.GetProperty('targetProxy') + dependency_xct = pbxcip.GetProperty('remoteGlobalIDString') + if hasattr(dependency_xct, 'test_runner'): + all_run_tests.append(dependency_xct.test_runner) + + # Directly depend on all the runners as they depend on the target + # that builds them. + if len(all_run_tests) > 0: + run_all_target = gyp.xcodeproj_file.PBXAggregateTarget({ + 'name': 'Run %s Tests' % tgt_name, + 'productName': tgt_name, + }, + parent=self.project) + for run_test_target in all_run_tests: + run_all_target.AddDependency(run_test_target) + + # Insert the test runner after the related target. + idx = self.project._properties['targets'].index(xcode_target) + self.project._properties['targets'].insert(idx + 1, run_all_target) + + # Update all references to other projects, to make sure that the lists of + # remote products are complete. Otherwise, Xcode will fill them in when + # it opens the project file, which will result in unnecessary diffs. + # TODO(mark): This is evil because it relies on internal knowledge of + # PBXProject._other_pbxprojects. + for other_pbxproject in self.project._other_pbxprojects.keys(): + self.project.AddOrGetProjectReference(other_pbxproject) + + self.project.SortRemoteProductReferences() + + # Give everything an ID. + self.project_file.ComputeIDs() + + # Make sure that no two objects in the project file have the same ID. If + # multiple objects wind up with the same ID, upon loading the file, Xcode + # will only recognize one object (the last one in the file?) and the + # results are unpredictable. + self.project_file.EnsureNoIDCollisions() + + def Write(self): + # Write the project file to a temporary location first. Xcode watches for + # changes to the project file and presents a UI sheet offering to reload + # the project when it does change. However, in some cases, especially when + # multiple projects are open or when Xcode is busy, things don't work so + # seamlessly. Sometimes, Xcode is able to detect that a project file has + # changed but can't unload it because something else is referencing it. + # To mitigate this problem, and to avoid even having Xcode present the UI + # sheet when an open project is rewritten for inconsequential changes, the + # project file is written to a temporary file in the xcodeproj directory + # first. The new temporary file is then compared to the existing project + # file, if any. If they differ, the new file replaces the old; otherwise, + # the new project file is simply deleted. Xcode properly detects a file + # being renamed over an open project file as a change and so it remains + # able to present the "project file changed" sheet under this system. + # Writing to a temporary file first also avoids the possible problem of + # Xcode rereading an incomplete project file. + (output_fd, new_pbxproj_path) = \ + tempfile.mkstemp(suffix='.tmp', prefix='project.pbxproj.gyp.', + dir=self.path) + + try: + output_file = os.fdopen(output_fd, 'wb') + + self.project_file.Print(output_file) + output_file.close() + + pbxproj_path = os.path.join(self.path, 'project.pbxproj') + + same = False + try: + same = filecmp.cmp(pbxproj_path, new_pbxproj_path, False) + except OSError, e: + if e.errno != errno.ENOENT: + raise + + if same: + # The new file is identical to the old one, just get rid of the new + # one. + os.unlink(new_pbxproj_path) + else: + # The new file is different from the old one, or there is no old one. + # Rename the new file to the permanent name. + # + # tempfile.mkstemp uses an overly restrictive mode, resulting in a + # file that can only be read by the owner, regardless of the umask. + # There's no reason to not respect the umask here, which means that + # an extra hoop is required to fetch it and reset the new file's mode. + # + # No way to get the umask without setting a new one? Set a safe one + # and then set it back to the old value. + umask = os.umask(077) + os.umask(umask) + + os.chmod(new_pbxproj_path, 0666 & ~umask) + os.rename(new_pbxproj_path, pbxproj_path) + + except Exception: + # Don't leave turds behind. In fact, if this code was responsible for + # creating the xcodeproj directory, get rid of that too. + os.unlink(new_pbxproj_path) + if self.created_dir: + shutil.rmtree(self.path, True) + raise + + +def AddSourceToTarget(source, type, pbxp, xct): + # TODO(mark): Perhaps source_extensions and library_extensions can be made a + # little bit fancier. + source_extensions = ['c', 'cc', 'cpp', 'cxx', 'm', 'mm', 's', 'swift'] + + # .o is conceptually more of a "source" than a "library," but Xcode thinks + # of "sources" as things to compile and "libraries" (or "frameworks") as + # things to link with. Adding an object file to an Xcode target's frameworks + # phase works properly. + library_extensions = ['a', 'dylib', 'framework', 'o'] + + basename = posixpath.basename(source) + (root, ext) = posixpath.splitext(basename) + if ext: + ext = ext[1:].lower() + + if ext in source_extensions and type != 'none': + xct.SourcesPhase().AddFile(source) + elif ext in library_extensions and type != 'none': + xct.FrameworksPhase().AddFile(source) + else: + # Files that aren't added to a sources or frameworks build phase can still + # go into the project file, just not as part of a build phase. + pbxp.AddOrGetFileInRootGroup(source) + + +def AddResourceToTarget(resource, pbxp, xct): + # TODO(mark): Combine with AddSourceToTarget above? Or just inline this call + # where it's used. + xct.ResourcesPhase().AddFile(resource) + + +def AddHeaderToTarget(header, pbxp, xct, is_public): + # TODO(mark): Combine with AddSourceToTarget above? Or just inline this call + # where it's used. + settings = '{ATTRIBUTES = (%s, ); }' % ('Private', 'Public')[is_public] + xct.HeadersPhase().AddFile(header, settings) + + +_xcode_variable_re = re.compile(r'(\$\((.*?)\))') +def ExpandXcodeVariables(string, expansions): + """Expands Xcode-style $(VARIABLES) in string per the expansions dict. + + In some rare cases, it is appropriate to expand Xcode variables when a + project file is generated. For any substring $(VAR) in string, if VAR is a + key in the expansions dict, $(VAR) will be replaced with expansions[VAR]. + Any $(VAR) substring in string for which VAR is not a key in the expansions + dict will remain in the returned string. + """ + + matches = _xcode_variable_re.findall(string) + if matches == None: + return string + + matches.reverse() + for match in matches: + (to_replace, variable) = match + if not variable in expansions: + continue + + replacement = expansions[variable] + string = re.sub(re.escape(to_replace), replacement, string) + + return string + + +_xcode_define_re = re.compile(r'([\\\"\' ])') +def EscapeXcodeDefine(s): + """We must escape the defines that we give to XCode so that it knows not to + split on spaces and to respect backslash and quote literals. However, we + must not quote the define, or Xcode will incorrectly intepret variables + especially $(inherited).""" + return re.sub(_xcode_define_re, r'\\\1', s) + + +def PerformBuild(data, configurations, params): + options = params['options'] + + for build_file, build_file_dict in data.iteritems(): + (build_file_root, build_file_ext) = os.path.splitext(build_file) + if build_file_ext != '.gyp': + continue + xcodeproj_path = build_file_root + options.suffix + '.xcodeproj' + if options.generator_output: + xcodeproj_path = os.path.join(options.generator_output, xcodeproj_path) + + for config in configurations: + arguments = ['xcodebuild', '-project', xcodeproj_path] + arguments += ['-configuration', config] + print "Building [%s]: %s" % (config, arguments) + subprocess.check_call(arguments) + + +def CalculateGeneratorInputInfo(params): + toplevel = params['options'].toplevel_dir + if params.get('flavor') == 'ninja': + generator_dir = os.path.relpath(params['options'].generator_output or '.') + output_dir = params.get('generator_flags', {}).get('output_dir', 'out') + output_dir = os.path.normpath(os.path.join(generator_dir, output_dir)) + qualified_out_dir = os.path.normpath(os.path.join( + toplevel, output_dir, 'gypfiles-xcode-ninja')) + else: + output_dir = os.path.normpath(os.path.join(toplevel, 'xcodebuild')) + qualified_out_dir = os.path.normpath(os.path.join( + toplevel, output_dir, 'gypfiles')) + + global generator_filelist_paths + generator_filelist_paths = { + 'toplevel': toplevel, + 'qualified_out_dir': qualified_out_dir, + } + + +def GenerateOutput(target_list, target_dicts, data, params): + # Optionally configure each spec to use ninja as the external builder. + ninja_wrapper = params.get('flavor') == 'ninja' + if ninja_wrapper: + (target_list, target_dicts, data) = \ + gyp.xcode_ninja.CreateWrapper(target_list, target_dicts, data, params) + + options = params['options'] + generator_flags = params.get('generator_flags', {}) + parallel_builds = generator_flags.get('xcode_parallel_builds', True) + serialize_all_tests = \ + generator_flags.get('xcode_serialize_all_test_runs', True) + upgrade_check_project_version = \ + generator_flags.get('xcode_upgrade_check_project_version', None) + + # Format upgrade_check_project_version with leading zeros as needed. + if upgrade_check_project_version: + upgrade_check_project_version = str(upgrade_check_project_version) + while len(upgrade_check_project_version) < 4: + upgrade_check_project_version = '0' + upgrade_check_project_version + + skip_excluded_files = \ + not generator_flags.get('xcode_list_excluded_files', True) + xcode_projects = {} + for build_file, build_file_dict in data.iteritems(): + (build_file_root, build_file_ext) = os.path.splitext(build_file) + if build_file_ext != '.gyp': + continue + xcodeproj_path = build_file_root + options.suffix + '.xcodeproj' + if options.generator_output: + xcodeproj_path = os.path.join(options.generator_output, xcodeproj_path) + xcp = XcodeProject(build_file, xcodeproj_path, build_file_dict) + xcode_projects[build_file] = xcp + pbxp = xcp.project + + # Set project-level attributes from multiple options + project_attributes = {}; + if parallel_builds: + project_attributes['BuildIndependentTargetsInParallel'] = 'YES' + if upgrade_check_project_version: + project_attributes['LastUpgradeCheck'] = upgrade_check_project_version + project_attributes['LastTestingUpgradeCheck'] = \ + upgrade_check_project_version + project_attributes['LastSwiftUpdateCheck'] = \ + upgrade_check_project_version + pbxp.SetProperty('attributes', project_attributes) + + # Add gyp/gypi files to project + if not generator_flags.get('standalone'): + main_group = pbxp.GetProperty('mainGroup') + build_group = gyp.xcodeproj_file.PBXGroup({'name': 'Build'}) + main_group.AppendChild(build_group) + for included_file in build_file_dict['included_files']: + build_group.AddOrGetFileByPath(included_file, False) + + xcode_targets = {} + xcode_target_to_target_dict = {} + for qualified_target in target_list: + [build_file, target_name, toolset] = \ + gyp.common.ParseQualifiedTarget(qualified_target) + + spec = target_dicts[qualified_target] + if spec['toolset'] != 'target': + raise Exception( + 'Multiple toolsets not supported in xcode build (target %s)' % + qualified_target) + configuration_names = [spec['default_configuration']] + for configuration_name in sorted(spec['configurations'].keys()): + if configuration_name not in configuration_names: + configuration_names.append(configuration_name) + xcp = xcode_projects[build_file] + pbxp = xcp.project + + # Set up the configurations for the target according to the list of names + # supplied. + xccl = CreateXCConfigurationList(configuration_names) + + # Create an XCTarget subclass object for the target. The type with + # "+bundle" appended will be used if the target has "mac_bundle" set. + # loadable_modules not in a mac_bundle are mapped to + # com.googlecode.gyp.xcode.bundle, a pseudo-type that xcode.py interprets + # to create a single-file mh_bundle. + _types = { + 'executable': 'com.apple.product-type.tool', + 'loadable_module': 'com.googlecode.gyp.xcode.bundle', + 'shared_library': 'com.apple.product-type.library.dynamic', + 'static_library': 'com.apple.product-type.library.static', + 'mac_kernel_extension': 'com.apple.product-type.kernel-extension', + 'executable+bundle': 'com.apple.product-type.application', + 'loadable_module+bundle': 'com.apple.product-type.bundle', + 'loadable_module+xctest': 'com.apple.product-type.bundle.unit-test', + 'shared_library+bundle': 'com.apple.product-type.framework', + 'executable+extension+bundle': 'com.apple.product-type.app-extension', + 'executable+watch+extension+bundle': + 'com.apple.product-type.watchkit-extension', + 'executable+watch+bundle': + 'com.apple.product-type.application.watchapp', + 'mac_kernel_extension+bundle': 'com.apple.product-type.kernel-extension', + } + + target_properties = { + 'buildConfigurationList': xccl, + 'name': target_name, + } + + type = spec['type'] + is_xctest = int(spec.get('mac_xctest_bundle', 0)) + is_bundle = int(spec.get('mac_bundle', 0)) or is_xctest + is_app_extension = int(spec.get('ios_app_extension', 0)) + is_watchkit_extension = int(spec.get('ios_watchkit_extension', 0)) + is_watch_app = int(spec.get('ios_watch_app', 0)) + if type != 'none': + type_bundle_key = type + if is_xctest: + type_bundle_key += '+xctest' + assert type == 'loadable_module', ( + 'mac_xctest_bundle targets must have type loadable_module ' + '(target %s)' % target_name) + elif is_app_extension: + assert is_bundle, ('ios_app_extension flag requires mac_bundle ' + '(target %s)' % target_name) + type_bundle_key += '+extension+bundle' + elif is_watchkit_extension: + assert is_bundle, ('ios_watchkit_extension flag requires mac_bundle ' + '(target %s)' % target_name) + type_bundle_key += '+watch+extension+bundle' + elif is_watch_app: + assert is_bundle, ('ios_watch_app flag requires mac_bundle ' + '(target %s)' % target_name) + type_bundle_key += '+watch+bundle' + elif is_bundle: + type_bundle_key += '+bundle' + + xctarget_type = gyp.xcodeproj_file.PBXNativeTarget + try: + target_properties['productType'] = _types[type_bundle_key] + except KeyError, e: + gyp.common.ExceptionAppend(e, "-- unknown product type while " + "writing target %s" % target_name) + raise + else: + xctarget_type = gyp.xcodeproj_file.PBXAggregateTarget + assert not is_bundle, ( + 'mac_bundle targets cannot have type none (target "%s")' % + target_name) + assert not is_xctest, ( + 'mac_xctest_bundle targets cannot have type none (target "%s")' % + target_name) + + target_product_name = spec.get('product_name') + if target_product_name is not None: + target_properties['productName'] = target_product_name + + xct = xctarget_type(target_properties, parent=pbxp, + force_outdir=spec.get('product_dir'), + force_prefix=spec.get('product_prefix'), + force_extension=spec.get('product_extension')) + pbxp.AppendProperty('targets', xct) + xcode_targets[qualified_target] = xct + xcode_target_to_target_dict[xct] = spec + + spec_actions = spec.get('actions', []) + spec_rules = spec.get('rules', []) + + # Xcode has some "issues" with checking dependencies for the "Compile + # sources" step with any source files/headers generated by actions/rules. + # To work around this, if a target is building anything directly (not + # type "none"), then a second target is used to run the GYP actions/rules + # and is made a dependency of this target. This way the work is done + # before the dependency checks for what should be recompiled. + support_xct = None + # The Xcode "issues" don't affect xcode-ninja builds, since the dependency + # logic all happens in ninja. Don't bother creating the extra targets in + # that case. + if type != 'none' and (spec_actions or spec_rules) and not ninja_wrapper: + support_xccl = CreateXCConfigurationList(configuration_names); + support_target_suffix = generator_flags.get( + 'support_target_suffix', ' Support') + support_target_properties = { + 'buildConfigurationList': support_xccl, + 'name': target_name + support_target_suffix, + } + if target_product_name: + support_target_properties['productName'] = \ + target_product_name + ' Support' + support_xct = \ + gyp.xcodeproj_file.PBXAggregateTarget(support_target_properties, + parent=pbxp) + pbxp.AppendProperty('targets', support_xct) + xct.AddDependency(support_xct) + # Hang the support target off the main target so it can be tested/found + # by the generator during Finalize. + xct.support_target = support_xct + + prebuild_index = 0 + + # Add custom shell script phases for "actions" sections. + for action in spec_actions: + # There's no need to write anything into the script to ensure that the + # output directories already exist, because Xcode will look at the + # declared outputs and automatically ensure that they exist for us. + + # Do we have a message to print when this action runs? + message = action.get('message') + if message: + message = 'echo note: ' + gyp.common.EncodePOSIXShellArgument(message) + else: + message = '' + + # Turn the list into a string that can be passed to a shell. + action_string = gyp.common.EncodePOSIXShellList(action['action']) + + # Convert Xcode-type variable references to sh-compatible environment + # variable references. + message_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax(message) + action_string_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax( + action_string) + + script = '' + # Include the optional message + if message_sh: + script += message_sh + '\n' + # Be sure the script runs in exec, and that if exec fails, the script + # exits signalling an error. + script += 'exec ' + action_string_sh + '\nexit 1\n' + ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ + 'inputPaths': action['inputs'], + 'name': 'Action "' + action['action_name'] + '"', + 'outputPaths': action['outputs'], + 'shellScript': script, + 'showEnvVarsInLog': 0, + }) + + if support_xct: + support_xct.AppendProperty('buildPhases', ssbp) + else: + # TODO(mark): this assumes too much knowledge of the internals of + # xcodeproj_file; some of these smarts should move into xcodeproj_file + # itself. + xct._properties['buildPhases'].insert(prebuild_index, ssbp) + prebuild_index = prebuild_index + 1 + + # TODO(mark): Should verify that at most one of these is specified. + if int(action.get('process_outputs_as_sources', False)): + for output in action['outputs']: + AddSourceToTarget(output, type, pbxp, xct) + + if int(action.get('process_outputs_as_mac_bundle_resources', False)): + for output in action['outputs']: + AddResourceToTarget(output, pbxp, xct) + + # tgt_mac_bundle_resources holds the list of bundle resources so + # the rule processing can check against it. + if is_bundle: + tgt_mac_bundle_resources = spec.get('mac_bundle_resources', []) + else: + tgt_mac_bundle_resources = [] + + # Add custom shell script phases driving "make" for "rules" sections. + # + # Xcode's built-in rule support is almost powerful enough to use directly, + # but there are a few significant deficiencies that render them unusable. + # There are workarounds for some of its inadequacies, but in aggregate, + # the workarounds added complexity to the generator, and some workarounds + # actually require input files to be crafted more carefully than I'd like. + # Consequently, until Xcode rules are made more capable, "rules" input + # sections will be handled in Xcode output by shell script build phases + # performed prior to the compilation phase. + # + # The following problems with Xcode rules were found. The numbers are + # Apple radar IDs. I hope that these shortcomings are addressed, I really + # liked having the rules handled directly in Xcode during the period that + # I was prototyping this. + # + # 6588600 Xcode compiles custom script rule outputs too soon, compilation + # fails. This occurs when rule outputs from distinct inputs are + # interdependent. The only workaround is to put rules and their + # inputs in a separate target from the one that compiles the rule + # outputs. This requires input file cooperation and it means that + # process_outputs_as_sources is unusable. + # 6584932 Need to declare that custom rule outputs should be excluded from + # compilation. A possible workaround is to lie to Xcode about a + # rule's output, giving it a dummy file it doesn't know how to + # compile. The rule action script would need to touch the dummy. + # 6584839 I need a way to declare additional inputs to a custom rule. + # A possible workaround is a shell script phase prior to + # compilation that touches a rule's primary input files if any + # would-be additional inputs are newer than the output. Modifying + # the source tree - even just modification times - feels dirty. + # 6564240 Xcode "custom script" build rules always dump all environment + # variables. This is a low-prioroty problem and is not a + # show-stopper. + rules_by_ext = {} + for rule in spec_rules: + rules_by_ext[rule['extension']] = rule + + # First, some definitions: + # + # A "rule source" is a file that was listed in a target's "sources" + # list and will have a rule applied to it on the basis of matching the + # rule's "extensions" attribute. Rule sources are direct inputs to + # rules. + # + # Rule definitions may specify additional inputs in their "inputs" + # attribute. These additional inputs are used for dependency tracking + # purposes. + # + # A "concrete output" is a rule output with input-dependent variables + # resolved. For example, given a rule with: + # 'extension': 'ext', 'outputs': ['$(INPUT_FILE_BASE).cc'], + # if the target's "sources" list contained "one.ext" and "two.ext", + # the "concrete output" for rule input "two.ext" would be "two.cc". If + # a rule specifies multiple outputs, each input file that the rule is + # applied to will have the same number of concrete outputs. + # + # If any concrete outputs are outdated or missing relative to their + # corresponding rule_source or to any specified additional input, the + # rule action must be performed to generate the concrete outputs. + + # concrete_outputs_by_rule_source will have an item at the same index + # as the rule['rule_sources'] that it corresponds to. Each item is a + # list of all of the concrete outputs for the rule_source. + concrete_outputs_by_rule_source = [] + + # concrete_outputs_all is a flat list of all concrete outputs that this + # rule is able to produce, given the known set of input files + # (rule_sources) that apply to it. + concrete_outputs_all = [] + + # messages & actions are keyed by the same indices as rule['rule_sources'] + # and concrete_outputs_by_rule_source. They contain the message and + # action to perform after resolving input-dependent variables. The + # message is optional, in which case None is stored for each rule source. + messages = [] + actions = [] + + for rule_source in rule.get('rule_sources', []): + rule_source_dirname, rule_source_basename = \ + posixpath.split(rule_source) + (rule_source_root, rule_source_ext) = \ + posixpath.splitext(rule_source_basename) + + # These are the same variable names that Xcode uses for its own native + # rule support. Because Xcode's rule engine is not being used, they + # need to be expanded as they are written to the makefile. + rule_input_dict = { + 'INPUT_FILE_BASE': rule_source_root, + 'INPUT_FILE_SUFFIX': rule_source_ext, + 'INPUT_FILE_NAME': rule_source_basename, + 'INPUT_FILE_PATH': rule_source, + 'INPUT_FILE_DIRNAME': rule_source_dirname, + } + + concrete_outputs_for_this_rule_source = [] + for output in rule.get('outputs', []): + # Fortunately, Xcode and make both use $(VAR) format for their + # variables, so the expansion is the only transformation necessary. + # Any remaning $(VAR)-type variables in the string can be given + # directly to make, which will pick up the correct settings from + # what Xcode puts into the environment. + concrete_output = ExpandXcodeVariables(output, rule_input_dict) + concrete_outputs_for_this_rule_source.append(concrete_output) + + # Add all concrete outputs to the project. + pbxp.AddOrGetFileInRootGroup(concrete_output) + + concrete_outputs_by_rule_source.append( \ + concrete_outputs_for_this_rule_source) + concrete_outputs_all.extend(concrete_outputs_for_this_rule_source) + + # TODO(mark): Should verify that at most one of these is specified. + if int(rule.get('process_outputs_as_sources', False)): + for output in concrete_outputs_for_this_rule_source: + AddSourceToTarget(output, type, pbxp, xct) + + # If the file came from the mac_bundle_resources list or if the rule + # is marked to process outputs as bundle resource, do so. + was_mac_bundle_resource = rule_source in tgt_mac_bundle_resources + if was_mac_bundle_resource or \ + int(rule.get('process_outputs_as_mac_bundle_resources', False)): + for output in concrete_outputs_for_this_rule_source: + AddResourceToTarget(output, pbxp, xct) + + # Do we have a message to print when this rule runs? + message = rule.get('message') + if message: + message = gyp.common.EncodePOSIXShellArgument(message) + message = ExpandXcodeVariables(message, rule_input_dict) + messages.append(message) + + # Turn the list into a string that can be passed to a shell. + action_string = gyp.common.EncodePOSIXShellList(rule['action']) + + action = ExpandXcodeVariables(action_string, rule_input_dict) + actions.append(action) + + if len(concrete_outputs_all) > 0: + # TODO(mark): There's a possibilty for collision here. Consider + # target "t" rule "A_r" and target "t_A" rule "r". + makefile_name = '%s.make' % re.sub( + '[^a-zA-Z0-9_]', '_' , '%s_%s' % (target_name, rule['rule_name'])) + makefile_path = os.path.join(xcode_projects[build_file].path, + makefile_name) + # TODO(mark): try/close? Write to a temporary file and swap it only + # if it's got changes? + makefile = open(makefile_path, 'wb') + + # make will build the first target in the makefile by default. By + # convention, it's called "all". List all (or at least one) + # concrete output for each rule source as a prerequisite of the "all" + # target. + makefile.write('all: \\\n') + for concrete_output_index in \ + xrange(0, len(concrete_outputs_by_rule_source)): + # Only list the first (index [0]) concrete output of each input + # in the "all" target. Otherwise, a parallel make (-j > 1) would + # attempt to process each input multiple times simultaneously. + # Otherwise, "all" could just contain the entire list of + # concrete_outputs_all. + concrete_output = \ + concrete_outputs_by_rule_source[concrete_output_index][0] + if concrete_output_index == len(concrete_outputs_by_rule_source) - 1: + eol = '' + else: + eol = ' \\' + makefile.write(' %s%s\n' % (concrete_output, eol)) + + for (rule_source, concrete_outputs, message, action) in \ + zip(rule['rule_sources'], concrete_outputs_by_rule_source, + messages, actions): + makefile.write('\n') + + # Add a rule that declares it can build each concrete output of a + # rule source. Collect the names of the directories that are + # required. + concrete_output_dirs = [] + for concrete_output_index in xrange(0, len(concrete_outputs)): + concrete_output = concrete_outputs[concrete_output_index] + if concrete_output_index == 0: + bol = '' + else: + bol = ' ' + makefile.write('%s%s \\\n' % (bol, concrete_output)) + + concrete_output_dir = posixpath.dirname(concrete_output) + if (concrete_output_dir and + concrete_output_dir not in concrete_output_dirs): + concrete_output_dirs.append(concrete_output_dir) + + makefile.write(' : \\\n') + + # The prerequisites for this rule are the rule source itself and + # the set of additional rule inputs, if any. + prerequisites = [rule_source] + prerequisites.extend(rule.get('inputs', [])) + for prerequisite_index in xrange(0, len(prerequisites)): + prerequisite = prerequisites[prerequisite_index] + if prerequisite_index == len(prerequisites) - 1: + eol = '' + else: + eol = ' \\' + makefile.write(' %s%s\n' % (prerequisite, eol)) + + # Make sure that output directories exist before executing the rule + # action. + if len(concrete_output_dirs) > 0: + makefile.write('\t@mkdir -p "%s"\n' % + '" "'.join(concrete_output_dirs)) + + # The rule message and action have already had the necessary variable + # substitutions performed. + if message: + # Mark it with note: so Xcode picks it up in build output. + makefile.write('\t@echo note: %s\n' % message) + makefile.write('\t%s\n' % action) + + makefile.close() + + # It might be nice to ensure that needed output directories exist + # here rather than in each target in the Makefile, but that wouldn't + # work if there ever was a concrete output that had an input-dependent + # variable anywhere other than in the leaf position. + + # Don't declare any inputPaths or outputPaths. If they're present, + # Xcode will provide a slight optimization by only running the script + # phase if any output is missing or outdated relative to any input. + # Unfortunately, it will also assume that all outputs are touched by + # the script, and if the outputs serve as files in a compilation + # phase, they will be unconditionally rebuilt. Since make might not + # rebuild everything that could be declared here as an output, this + # extra compilation activity is unnecessary. With inputPaths and + # outputPaths not supplied, make will always be called, but it knows + # enough to not do anything when everything is up-to-date. + + # To help speed things up, pass -j COUNT to make so it does some work + # in parallel. Don't use ncpus because Xcode will build ncpus targets + # in parallel and if each target happens to have a rules step, there + # would be ncpus^2 things going. With a machine that has 2 quad-core + # Xeons, a build can quickly run out of processes based on + # scheduling/other tasks, and randomly failing builds are no good. + script = \ +"""JOB_COUNT="$(/usr/sbin/sysctl -n hw.ncpu)" +if [ "${JOB_COUNT}" -gt 4 ]; then + JOB_COUNT=4 +fi +exec xcrun make -f "${PROJECT_FILE_PATH}/%s" -j "${JOB_COUNT}" +exit 1 +""" % makefile_name + ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ + 'name': 'Rule "' + rule['rule_name'] + '"', + 'shellScript': script, + 'showEnvVarsInLog': 0, + }) + + if support_xct: + support_xct.AppendProperty('buildPhases', ssbp) + else: + # TODO(mark): this assumes too much knowledge of the internals of + # xcodeproj_file; some of these smarts should move into xcodeproj_file + # itself. + xct._properties['buildPhases'].insert(prebuild_index, ssbp) + prebuild_index = prebuild_index + 1 + + # Extra rule inputs also go into the project file. Concrete outputs were + # already added when they were computed. + groups = ['inputs', 'inputs_excluded'] + if skip_excluded_files: + groups = [x for x in groups if not x.endswith('_excluded')] + for group in groups: + for item in rule.get(group, []): + pbxp.AddOrGetFileInRootGroup(item) + + # Add "sources". + for source in spec.get('sources', []): + (source_root, source_extension) = posixpath.splitext(source) + if source_extension[1:] not in rules_by_ext: + # AddSourceToTarget will add the file to a root group if it's not + # already there. + AddSourceToTarget(source, type, pbxp, xct) + else: + pbxp.AddOrGetFileInRootGroup(source) + + # Add "mac_bundle_resources" and "mac_framework_private_headers" if + # it's a bundle of any type. + if is_bundle: + for resource in tgt_mac_bundle_resources: + (resource_root, resource_extension) = posixpath.splitext(resource) + if resource_extension[1:] not in rules_by_ext: + AddResourceToTarget(resource, pbxp, xct) + else: + pbxp.AddOrGetFileInRootGroup(resource) + + for header in spec.get('mac_framework_private_headers', []): + AddHeaderToTarget(header, pbxp, xct, False) + + # Add "mac_framework_headers". These can be valid for both frameworks + # and static libraries. + if is_bundle or type == 'static_library': + for header in spec.get('mac_framework_headers', []): + AddHeaderToTarget(header, pbxp, xct, True) + + # Add "copies". + pbxcp_dict = {} + for copy_group in spec.get('copies', []): + dest = copy_group['destination'] + if dest[0] not in ('/', '$'): + # Relative paths are relative to $(SRCROOT). + dest = '$(SRCROOT)/' + dest + + code_sign = int(copy_group.get('xcode_code_sign', 0)) + settings = (None, '{ATTRIBUTES = (CodeSignOnCopy, ); }')[code_sign]; + + # Coalesce multiple "copies" sections in the same target with the same + # "destination" property into the same PBXCopyFilesBuildPhase, otherwise + # they'll wind up with ID collisions. + pbxcp = pbxcp_dict.get(dest, None) + if pbxcp is None: + pbxcp = gyp.xcodeproj_file.PBXCopyFilesBuildPhase({ + 'name': 'Copy to ' + copy_group['destination'] + }, + parent=xct) + pbxcp.SetDestination(dest) + + # TODO(mark): The usual comment about this knowing too much about + # gyp.xcodeproj_file internals applies. + xct._properties['buildPhases'].insert(prebuild_index, pbxcp) + + pbxcp_dict[dest] = pbxcp + + for file in copy_group['files']: + pbxcp.AddFile(file, settings) + + # Excluded files can also go into the project file. + if not skip_excluded_files: + for key in ['sources', 'mac_bundle_resources', 'mac_framework_headers', + 'mac_framework_private_headers']: + excluded_key = key + '_excluded' + for item in spec.get(excluded_key, []): + pbxp.AddOrGetFileInRootGroup(item) + + # So can "inputs" and "outputs" sections of "actions" groups. + groups = ['inputs', 'inputs_excluded', 'outputs', 'outputs_excluded'] + if skip_excluded_files: + groups = [x for x in groups if not x.endswith('_excluded')] + for action in spec.get('actions', []): + for group in groups: + for item in action.get(group, []): + # Exclude anything in BUILT_PRODUCTS_DIR. They're products, not + # sources. + if not item.startswith('$(BUILT_PRODUCTS_DIR)/'): + pbxp.AddOrGetFileInRootGroup(item) + + for postbuild in spec.get('postbuilds', []): + action_string_sh = gyp.common.EncodePOSIXShellList(postbuild['action']) + script = 'exec ' + action_string_sh + '\nexit 1\n' + + # Make the postbuild step depend on the output of ld or ar from this + # target. Apparently putting the script step after the link step isn't + # sufficient to ensure proper ordering in all cases. With an input + # declared but no outputs, the script step should run every time, as + # desired. + ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ + 'inputPaths': ['$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_PATH)'], + 'name': 'Postbuild "' + postbuild['postbuild_name'] + '"', + 'shellScript': script, + 'showEnvVarsInLog': 0, + }) + xct.AppendProperty('buildPhases', ssbp) + + # Add dependencies before libraries, because adding a dependency may imply + # adding a library. It's preferable to keep dependencies listed first + # during a link phase so that they can override symbols that would + # otherwise be provided by libraries, which will usually include system + # libraries. On some systems, ld is finicky and even requires the + # libraries to be ordered in such a way that unresolved symbols in + # earlier-listed libraries may only be resolved by later-listed libraries. + # The Mac linker doesn't work that way, but other platforms do, and so + # their linker invocations need to be constructed in this way. There's + # no compelling reason for Xcode's linker invocations to differ. + + if 'dependencies' in spec: + for dependency in spec['dependencies']: + xct.AddDependency(xcode_targets[dependency]) + # The support project also gets the dependencies (in case they are + # needed for the actions/rules to work). + if support_xct: + support_xct.AddDependency(xcode_targets[dependency]) + + if 'libraries' in spec: + for library in spec['libraries']: + xct.FrameworksPhase().AddFile(library) + # Add the library's directory to LIBRARY_SEARCH_PATHS if necessary. + # I wish Xcode handled this automatically. + library_dir = posixpath.dirname(library) + if library_dir not in xcode_standard_library_dirs and ( + not xct.HasBuildSetting(_library_search_paths_var) or + library_dir not in xct.GetBuildSetting(_library_search_paths_var)): + xct.AppendBuildSetting(_library_search_paths_var, library_dir) + + for configuration_name in configuration_names: + configuration = spec['configurations'][configuration_name] + xcbc = xct.ConfigurationNamed(configuration_name) + for include_dir in configuration.get('mac_framework_dirs', []): + xcbc.AppendBuildSetting('FRAMEWORK_SEARCH_PATHS', include_dir) + for include_dir in configuration.get('include_dirs', []): + xcbc.AppendBuildSetting('HEADER_SEARCH_PATHS', include_dir) + for library_dir in configuration.get('library_dirs', []): + if library_dir not in xcode_standard_library_dirs and ( + not xcbc.HasBuildSetting(_library_search_paths_var) or + library_dir not in xcbc.GetBuildSetting(_library_search_paths_var)): + xcbc.AppendBuildSetting(_library_search_paths_var, library_dir) + + if 'defines' in configuration: + for define in configuration['defines']: + set_define = EscapeXcodeDefine(define) + xcbc.AppendBuildSetting('GCC_PREPROCESSOR_DEFINITIONS', set_define) + if 'xcode_settings' in configuration: + for xck, xcv in configuration['xcode_settings'].iteritems(): + xcbc.SetBuildSetting(xck, xcv) + if 'xcode_config_file' in configuration: + config_ref = pbxp.AddOrGetFileInRootGroup( + configuration['xcode_config_file']) + xcbc.SetBaseConfiguration(config_ref) + + build_files = [] + for build_file, build_file_dict in data.iteritems(): + if build_file.endswith('.gyp'): + build_files.append(build_file) + + for build_file in build_files: + xcode_projects[build_file].Finalize1(xcode_targets, serialize_all_tests) + + for build_file in build_files: + xcode_projects[build_file].Finalize2(xcode_targets, + xcode_target_to_target_dict) + + for build_file in build_files: + xcode_projects[build_file].Write() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py new file mode 100644 index 0000000000000..260324a43f3e2 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py @@ -0,0 +1,23 @@ +#!/usr/bin/env python + +# 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. + +""" Unit tests for the xcode.py file. """ + +import gyp.generator.xcode as xcode +import unittest +import sys + + +class TestEscapeXcodeDefine(unittest.TestCase): + if sys.platform == 'darwin': + def test_InheritedRemainsUnescaped(self): + self.assertEqual(xcode.EscapeXcodeDefine('$(inherited)'), '$(inherited)') + + def test_Escaping(self): + self.assertEqual(xcode.EscapeXcodeDefine('a b"c\\'), 'a\\ b\\"c\\\\') + +if __name__ == '__main__': + unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input.py new file mode 100644 index 0000000000000..10f6e0dba16de --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input.py @@ -0,0 +1,2902 @@ +# Copyright (c) 2012 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. + +from compiler.ast import Const +from compiler.ast import Dict +from compiler.ast import Discard +from compiler.ast import List +from compiler.ast import Module +from compiler.ast import Node +from compiler.ast import Stmt +import compiler +import gyp.common +import gyp.simple_copy +import multiprocessing +import optparse +import os.path +import re +import shlex +import signal +import subprocess +import sys +import threading +import time +import traceback +from gyp.common import GypError +from gyp.common import OrderedSet + + +# A list of types that are treated as linkable. +linkable_types = [ + 'executable', + 'shared_library', + 'loadable_module', + 'mac_kernel_extension', +] + +# A list of sections that contain links to other targets. +dependency_sections = ['dependencies', 'export_dependent_settings'] + +# base_path_sections is a list of sections defined by GYP that contain +# pathnames. The generators can provide more keys, the two lists are merged +# into path_sections, but you should call IsPathSection instead of using either +# list directly. +base_path_sections = [ + 'destination', + 'files', + 'include_dirs', + 'inputs', + 'libraries', + 'outputs', + 'sources', +] +path_sections = set() + +# These per-process dictionaries are used to cache build file data when loading +# in parallel mode. +per_process_data = {} +per_process_aux_data = {} + +def IsPathSection(section): + # If section ends in one of the '=+?!' characters, it's applied to a section + # without the trailing characters. '/' is notably absent from this list, + # because there's no way for a regular expression to be treated as a path. + while section and section[-1:] in '=+?!': + section = section[:-1] + + if section in path_sections: + return True + + # Sections mathing the regexp '_(dir|file|path)s?$' are also + # considered PathSections. Using manual string matching since that + # is much faster than the regexp and this can be called hundreds of + # thousands of times so micro performance matters. + if "_" in section: + tail = section[-6:] + if tail[-1] == 's': + tail = tail[:-1] + if tail[-5:] in ('_file', '_path'): + return True + return tail[-4:] == '_dir' + + return False + +# base_non_configuration_keys is a list of key names that belong in the target +# itself and should not be propagated into its configurations. It is merged +# with a list that can come from the generator to +# create non_configuration_keys. +base_non_configuration_keys = [ + # Sections that must exist inside targets and not configurations. + 'actions', + 'configurations', + 'copies', + 'default_configuration', + 'dependencies', + 'dependencies_original', + 'libraries', + 'postbuilds', + 'product_dir', + 'product_extension', + 'product_name', + 'product_prefix', + 'rules', + 'run_as', + 'sources', + 'standalone_static_library', + 'suppress_wildcard', + 'target_name', + 'toolset', + 'toolsets', + 'type', + + # Sections that can be found inside targets or configurations, but that + # should not be propagated from targets into their configurations. + 'variables', +] +non_configuration_keys = [] + +# Keys that do not belong inside a configuration dictionary. +invalid_configuration_keys = [ + 'actions', + 'all_dependent_settings', + 'configurations', + 'dependencies', + 'direct_dependent_settings', + 'libraries', + 'link_settings', + 'sources', + 'standalone_static_library', + 'target_name', + 'type', +] + +# Controls whether or not the generator supports multiple toolsets. +multiple_toolsets = False + +# Paths for converting filelist paths to output paths: { +# toplevel, +# qualified_output_dir, +# } +generator_filelist_paths = None + +def GetIncludedBuildFiles(build_file_path, aux_data, included=None): + """Return a list of all build files included into build_file_path. + + The returned list will contain build_file_path as well as all other files + that it included, either directly or indirectly. Note that the list may + contain files that were included into a conditional section that evaluated + to false and was not merged into build_file_path's dict. + + aux_data is a dict containing a key for each build file or included build + file. Those keys provide access to dicts whose "included" keys contain + lists of all other files included by the build file. + + included should be left at its default None value by external callers. It + is used for recursion. + + The returned list will not contain any duplicate entries. Each build file + in the list will be relative to the current directory. + """ + + if included == None: + included = [] + + if build_file_path in included: + return included + + included.append(build_file_path) + + for included_build_file in aux_data[build_file_path].get('included', []): + GetIncludedBuildFiles(included_build_file, aux_data, included) + + return included + + +def CheckedEval(file_contents): + """Return the eval of a gyp file. + + The gyp file is restricted to dictionaries and lists only, and + repeated keys are not allowed. + + Note that this is slower than eval() is. + """ + + ast = compiler.parse(file_contents) + assert isinstance(ast, Module) + c1 = ast.getChildren() + assert c1[0] is None + assert isinstance(c1[1], Stmt) + c2 = c1[1].getChildren() + assert isinstance(c2[0], Discard) + c3 = c2[0].getChildren() + assert len(c3) == 1 + return CheckNode(c3[0], []) + + +def CheckNode(node, keypath): + if isinstance(node, Dict): + c = node.getChildren() + dict = {} + for n in range(0, len(c), 2): + assert isinstance(c[n], Const) + key = c[n].getChildren()[0] + if key in dict: + raise GypError("Key '" + key + "' repeated at level " + + repr(len(keypath) + 1) + " with key path '" + + '.'.join(keypath) + "'") + kp = list(keypath) # Make a copy of the list for descending this node. + kp.append(key) + dict[key] = CheckNode(c[n + 1], kp) + return dict + elif isinstance(node, List): + c = node.getChildren() + children = [] + for index, child in enumerate(c): + kp = list(keypath) # Copy list. + kp.append(repr(index)) + children.append(CheckNode(child, kp)) + return children + elif isinstance(node, Const): + return node.getChildren()[0] + else: + raise TypeError("Unknown AST node at key path '" + '.'.join(keypath) + + "': " + repr(node)) + + +def LoadOneBuildFile(build_file_path, data, aux_data, includes, + is_target, check): + if build_file_path in data: + return data[build_file_path] + + if os.path.exists(build_file_path): + # Open the build file for read ('r') with universal-newlines mode ('U') + # to make sure platform specific newlines ('\r\n' or '\r') are converted to '\n' + # which otherwise will fail eval() + if sys.platform == 'zos': + # On z/OS, universal-newlines mode treats the file as an ascii file. But since + # node-gyp produces ebcdic files, do not use that mode. + build_file_contents = open(build_file_path, 'r').read() + else: + build_file_contents = open(build_file_path, 'rU').read() + else: + raise GypError("%s not found (cwd: %s)" % (build_file_path, os.getcwd())) + + build_file_data = None + try: + if check: + build_file_data = CheckedEval(build_file_contents) + else: + build_file_data = eval(build_file_contents, {'__builtins__': None}, + None) + except SyntaxError, e: + e.filename = build_file_path + raise + except Exception, e: + gyp.common.ExceptionAppend(e, 'while reading ' + build_file_path) + raise + + if type(build_file_data) is not dict: + raise GypError("%s does not evaluate to a dictionary." % build_file_path) + + data[build_file_path] = build_file_data + aux_data[build_file_path] = {} + + # Scan for includes and merge them in. + if ('skip_includes' not in build_file_data or + not build_file_data['skip_includes']): + try: + if is_target: + LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data, + aux_data, includes, check) + else: + LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data, + aux_data, None, check) + except Exception, e: + gyp.common.ExceptionAppend(e, + 'while reading includes of ' + build_file_path) + raise + + return build_file_data + + +def LoadBuildFileIncludesIntoDict(subdict, subdict_path, data, aux_data, + includes, check): + includes_list = [] + if includes != None: + includes_list.extend(includes) + if 'includes' in subdict: + for include in subdict['includes']: + # "include" is specified relative to subdict_path, so compute the real + # path to include by appending the provided "include" to the directory + # in which subdict_path resides. + relative_include = \ + os.path.normpath(os.path.join(os.path.dirname(subdict_path), include)) + includes_list.append(relative_include) + # Unhook the includes list, it's no longer needed. + del subdict['includes'] + + # Merge in the included files. + for include in includes_list: + if not 'included' in aux_data[subdict_path]: + aux_data[subdict_path]['included'] = [] + aux_data[subdict_path]['included'].append(include) + + gyp.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Included File: '%s'", include) + + MergeDicts(subdict, + LoadOneBuildFile(include, data, aux_data, None, False, check), + subdict_path, include) + + # Recurse into subdictionaries. + for k, v in subdict.iteritems(): + if type(v) is dict: + LoadBuildFileIncludesIntoDict(v, subdict_path, data, aux_data, + None, check) + elif type(v) is list: + LoadBuildFileIncludesIntoList(v, subdict_path, data, aux_data, + check) + + +# This recurses into lists so that it can look for dicts. +def LoadBuildFileIncludesIntoList(sublist, sublist_path, data, aux_data, check): + for item in sublist: + if type(item) is dict: + LoadBuildFileIncludesIntoDict(item, sublist_path, data, aux_data, + None, check) + elif type(item) is list: + LoadBuildFileIncludesIntoList(item, sublist_path, data, aux_data, check) + +# Processes toolsets in all the targets. This recurses into condition entries +# since they can contain toolsets as well. +def ProcessToolsetsInDict(data): + if 'targets' in data: + target_list = data['targets'] + new_target_list = [] + for target in target_list: + # If this target already has an explicit 'toolset', and no 'toolsets' + # list, don't modify it further. + if 'toolset' in target and 'toolsets' not in target: + new_target_list.append(target) + continue + if multiple_toolsets: + toolsets = target.get('toolsets', ['target']) + else: + toolsets = ['target'] + # Make sure this 'toolsets' definition is only processed once. + if 'toolsets' in target: + del target['toolsets'] + if len(toolsets) > 0: + # Optimization: only do copies if more than one toolset is specified. + for build in toolsets[1:]: + new_target = gyp.simple_copy.deepcopy(target) + new_target['toolset'] = build + new_target_list.append(new_target) + target['toolset'] = toolsets[0] + new_target_list.append(target) + data['targets'] = new_target_list + if 'conditions' in data: + for condition in data['conditions']: + if type(condition) is list: + for condition_dict in condition[1:]: + if type(condition_dict) is dict: + ProcessToolsetsInDict(condition_dict) + + +# TODO(mark): I don't love this name. It just means that it's going to load +# a build file that contains targets and is expected to provide a targets dict +# that contains the targets... +def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, + depth, check, load_dependencies): + # If depth is set, predefine the DEPTH variable to be a relative path from + # this build file's directory to the directory identified by depth. + if depth: + # TODO(dglazkov) The backslash/forward-slash replacement at the end is a + # temporary measure. This should really be addressed by keeping all paths + # in POSIX until actual project generation. + d = gyp.common.RelativePath(depth, os.path.dirname(build_file_path)) + if d == '': + variables['DEPTH'] = '.' + else: + variables['DEPTH'] = d.replace('\\', '/') + + # The 'target_build_files' key is only set when loading target build files in + # the non-parallel code path, where LoadTargetBuildFile is called + # recursively. In the parallel code path, we don't need to check whether the + # |build_file_path| has already been loaded, because the 'scheduled' set in + # ParallelState guarantees that we never load the same |build_file_path| + # twice. + if 'target_build_files' in data: + if build_file_path in data['target_build_files']: + # Already loaded. + return False + data['target_build_files'].add(build_file_path) + + gyp.DebugOutput(gyp.DEBUG_INCLUDES, + "Loading Target Build File '%s'", build_file_path) + + build_file_data = LoadOneBuildFile(build_file_path, data, aux_data, + includes, True, check) + + # Store DEPTH for later use in generators. + build_file_data['_DEPTH'] = depth + + # Set up the included_files key indicating which .gyp files contributed to + # this target dict. + if 'included_files' in build_file_data: + raise GypError(build_file_path + ' must not contain included_files key') + + included = GetIncludedBuildFiles(build_file_path, aux_data) + build_file_data['included_files'] = [] + for included_file in included: + # included_file is relative to the current directory, but it needs to + # be made relative to build_file_path's directory. + included_relative = \ + gyp.common.RelativePath(included_file, + os.path.dirname(build_file_path)) + build_file_data['included_files'].append(included_relative) + + # Do a first round of toolsets expansion so that conditions can be defined + # per toolset. + ProcessToolsetsInDict(build_file_data) + + # Apply "pre"/"early" variable expansions and condition evaluations. + ProcessVariablesAndConditionsInDict( + build_file_data, PHASE_EARLY, variables, build_file_path) + + # Since some toolsets might have been defined conditionally, perform + # a second round of toolsets expansion now. + ProcessToolsetsInDict(build_file_data) + + # Look at each project's target_defaults dict, and merge settings into + # targets. + if 'target_defaults' in build_file_data: + if 'targets' not in build_file_data: + raise GypError("Unable to find targets in build file %s" % + build_file_path) + + index = 0 + while index < len(build_file_data['targets']): + # This procedure needs to give the impression that target_defaults is + # used as defaults, and the individual targets inherit from that. + # The individual targets need to be merged into the defaults. Make + # a deep copy of the defaults for each target, merge the target dict + # as found in the input file into that copy, and then hook up the + # copy with the target-specific data merged into it as the replacement + # target dict. + old_target_dict = build_file_data['targets'][index] + new_target_dict = gyp.simple_copy.deepcopy( + build_file_data['target_defaults']) + MergeDicts(new_target_dict, old_target_dict, + build_file_path, build_file_path) + build_file_data['targets'][index] = new_target_dict + index += 1 + + # No longer needed. + del build_file_data['target_defaults'] + + # Look for dependencies. This means that dependency resolution occurs + # after "pre" conditionals and variable expansion, but before "post" - + # in other words, you can't put a "dependencies" section inside a "post" + # conditional within a target. + + dependencies = [] + if 'targets' in build_file_data: + for target_dict in build_file_data['targets']: + if 'dependencies' not in target_dict: + continue + for dependency in target_dict['dependencies']: + dependencies.append( + gyp.common.ResolveTarget(build_file_path, dependency, None)[0]) + + if load_dependencies: + for dependency in dependencies: + try: + LoadTargetBuildFile(dependency, data, aux_data, variables, + includes, depth, check, load_dependencies) + except Exception, e: + gyp.common.ExceptionAppend( + e, 'while loading dependencies of %s' % build_file_path) + raise + else: + return (build_file_path, dependencies) + +def CallLoadTargetBuildFile(global_flags, + build_file_path, variables, + includes, depth, check, + generator_input_info): + """Wrapper around LoadTargetBuildFile for parallel processing. + + This wrapper is used when LoadTargetBuildFile is executed in + a worker process. + """ + + try: + signal.signal(signal.SIGINT, signal.SIG_IGN) + + # Apply globals so that the worker process behaves the same. + for key, value in global_flags.iteritems(): + globals()[key] = value + + SetGeneratorGlobals(generator_input_info) + result = LoadTargetBuildFile(build_file_path, per_process_data, + per_process_aux_data, variables, + includes, depth, check, False) + if not result: + return result + + (build_file_path, dependencies) = result + + # We can safely pop the build_file_data from per_process_data because it + # will never be referenced by this process again, so we don't need to keep + # it in the cache. + build_file_data = per_process_data.pop(build_file_path) + + # This gets serialized and sent back to the main process via a pipe. + # It's handled in LoadTargetBuildFileCallback. + return (build_file_path, + build_file_data, + dependencies) + except GypError, e: + sys.stderr.write("gyp: %s\n" % e) + return None + except Exception, e: + print >>sys.stderr, 'Exception:', e + print >>sys.stderr, traceback.format_exc() + return None + + +class ParallelProcessingError(Exception): + pass + + +class ParallelState(object): + """Class to keep track of state when processing input files in parallel. + + If build files are loaded in parallel, use this to keep track of + state during farming out and processing parallel jobs. It's stored + in a global so that the callback function can have access to it. + """ + + def __init__(self): + # The multiprocessing pool. + self.pool = None + # The condition variable used to protect this object and notify + # the main loop when there might be more data to process. + self.condition = None + # The "data" dict that was passed to LoadTargetBuildFileParallel + self.data = None + # The number of parallel calls outstanding; decremented when a response + # was received. + self.pending = 0 + # The set of all build files that have been scheduled, so we don't + # schedule the same one twice. + self.scheduled = set() + # A list of dependency build file paths that haven't been scheduled yet. + self.dependencies = [] + # Flag to indicate if there was an error in a child process. + self.error = False + + def LoadTargetBuildFileCallback(self, result): + """Handle the results of running LoadTargetBuildFile in another process. + """ + self.condition.acquire() + if not result: + self.error = True + self.condition.notify() + self.condition.release() + return + (build_file_path0, build_file_data0, dependencies0) = result + self.data[build_file_path0] = build_file_data0 + self.data['target_build_files'].add(build_file_path0) + for new_dependency in dependencies0: + if new_dependency not in self.scheduled: + self.scheduled.add(new_dependency) + self.dependencies.append(new_dependency) + self.pending -= 1 + self.condition.notify() + self.condition.release() + + +def LoadTargetBuildFilesParallel(build_files, data, variables, includes, depth, + check, generator_input_info): + parallel_state = ParallelState() + parallel_state.condition = threading.Condition() + # Make copies of the build_files argument that we can modify while working. + parallel_state.dependencies = list(build_files) + parallel_state.scheduled = set(build_files) + parallel_state.pending = 0 + parallel_state.data = data + + try: + parallel_state.condition.acquire() + while parallel_state.dependencies or parallel_state.pending: + if parallel_state.error: + break + if not parallel_state.dependencies: + parallel_state.condition.wait() + continue + + dependency = parallel_state.dependencies.pop() + + parallel_state.pending += 1 + global_flags = { + 'path_sections': globals()['path_sections'], + 'non_configuration_keys': globals()['non_configuration_keys'], + 'multiple_toolsets': globals()['multiple_toolsets']} + + if not parallel_state.pool: + parallel_state.pool = multiprocessing.Pool(multiprocessing.cpu_count()) + parallel_state.pool.apply_async( + CallLoadTargetBuildFile, + args = (global_flags, dependency, + variables, includes, depth, check, generator_input_info), + callback = parallel_state.LoadTargetBuildFileCallback) + except KeyboardInterrupt, e: + parallel_state.pool.terminate() + raise e + + parallel_state.condition.release() + + parallel_state.pool.close() + parallel_state.pool.join() + parallel_state.pool = None + + if parallel_state.error: + sys.exit(1) + +# Look for the bracket that matches the first bracket seen in a +# string, and return the start and end as a tuple. For example, if +# the input is something like "<(foo <(bar)) blah", then it would +# return (1, 13), indicating the entire string except for the leading +# "<" and trailing " blah". +LBRACKETS= set('{[(') +BRACKETS = {'}': '{', ']': '[', ')': '('} +def FindEnclosingBracketGroup(input_str): + stack = [] + start = -1 + for index, char in enumerate(input_str): + if char in LBRACKETS: + stack.append(char) + if start == -1: + start = index + elif char in BRACKETS: + if not stack: + return (-1, -1) + if stack.pop() != BRACKETS[char]: + return (-1, -1) + if not stack: + return (start, index + 1) + return (-1, -1) + + +def IsStrCanonicalInt(string): + """Returns True if |string| is in its canonical integer form. + + The canonical form is such that str(int(string)) == string. + """ + if type(string) is str: + # This function is called a lot so for maximum performance, avoid + # involving regexps which would otherwise make the code much + # shorter. Regexps would need twice the time of this function. + if string: + if string == "0": + return True + if string[0] == "-": + string = string[1:] + if not string: + return False + if '1' <= string[0] <= '9': + return string.isdigit() + + return False + + +# This matches things like "<(asdf)", "(?P<(?:(?:!?@?)|\|)?)' + r'(?P[-a-zA-Z0-9_.]+)?' + r'\((?P\s*\[?)' + r'(?P.*?)(\]?)\))') + +# This matches the same as early_variable_re, but with '>' instead of '<'. +late_variable_re = re.compile( + r'(?P(?P>(?:(?:!?@?)|\|)?)' + r'(?P[-a-zA-Z0-9_.]+)?' + r'\((?P\s*\[?)' + r'(?P.*?)(\]?)\))') + +# This matches the same as early_variable_re, but with '^' instead of '<'. +latelate_variable_re = re.compile( + r'(?P(?P[\^](?:(?:!?@?)|\|)?)' + r'(?P[-a-zA-Z0-9_.]+)?' + r'\((?P\s*\[?)' + r'(?P.*?)(\]?)\))') + +# Global cache of results from running commands so they don't have to be run +# more then once. +cached_command_results = {} + + +def FixupPlatformCommand(cmd): + if sys.platform == 'win32': + if type(cmd) is list: + cmd = [re.sub('^cat ', 'type ', cmd[0])] + cmd[1:] + else: + cmd = re.sub('^cat ', 'type ', cmd) + return cmd + + +PHASE_EARLY = 0 +PHASE_LATE = 1 +PHASE_LATELATE = 2 + + +def ExpandVariables(input, phase, variables, build_file): + # Look for the pattern that gets expanded into variables + if phase == PHASE_EARLY: + variable_re = early_variable_re + expansion_symbol = '<' + elif phase == PHASE_LATE: + variable_re = late_variable_re + expansion_symbol = '>' + elif phase == PHASE_LATELATE: + variable_re = latelate_variable_re + expansion_symbol = '^' + else: + assert False + + input_str = str(input) + if IsStrCanonicalInt(input_str): + return int(input_str) + + # Do a quick scan to determine if an expensive regex search is warranted. + if expansion_symbol not in input_str: + return input_str + + # Get the entire list of matches as a list of MatchObject instances. + # (using findall here would return strings instead of MatchObjects). + matches = list(variable_re.finditer(input_str)) + if not matches: + return input_str + + output = input_str + # Reverse the list of matches so that replacements are done right-to-left. + # That ensures that earlier replacements won't mess up the string in a + # way that causes later calls to find the earlier substituted text instead + # of what's intended for replacement. + matches.reverse() + for match_group in matches: + match = match_group.groupdict() + gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Matches: %r", match) + # match['replace'] is the substring to look for, match['type'] + # is the character code for the replacement type (< > ! <| >| <@ + # >@ !@), match['is_array'] contains a '[' for command + # arrays, and match['content'] is the name of the variable (< >) + # or command to run (!). match['command_string'] is an optional + # command string. Currently, only 'pymod_do_main' is supported. + + # run_command is true if a ! variant is used. + run_command = '!' in match['type'] + command_string = match['command_string'] + + # file_list is true if a | variant is used. + file_list = '|' in match['type'] + + # Capture these now so we can adjust them later. + replace_start = match_group.start('replace') + replace_end = match_group.end('replace') + + # Find the ending paren, and re-evaluate the contained string. + (c_start, c_end) = FindEnclosingBracketGroup(input_str[replace_start:]) + + # Adjust the replacement range to match the entire command + # found by FindEnclosingBracketGroup (since the variable_re + # probably doesn't match the entire command if it contained + # nested variables). + replace_end = replace_start + c_end + + # Find the "real" replacement, matching the appropriate closing + # paren, and adjust the replacement start and end. + replacement = input_str[replace_start:replace_end] + + # Figure out what the contents of the variable parens are. + contents_start = replace_start + c_start + 1 + contents_end = replace_end - 1 + contents = input_str[contents_start:contents_end] + + # Do filter substitution now for <|(). + # Admittedly, this is different than the evaluation order in other + # contexts. However, since filtration has no chance to run on <|(), + # this seems like the only obvious way to give them access to filters. + if file_list: + processed_variables = gyp.simple_copy.deepcopy(variables) + ProcessListFiltersInDict(contents, processed_variables) + # Recurse to expand variables in the contents + contents = ExpandVariables(contents, phase, + processed_variables, build_file) + else: + # Recurse to expand variables in the contents + contents = ExpandVariables(contents, phase, variables, build_file) + + # Strip off leading/trailing whitespace so that variable matches are + # simpler below (and because they are rarely needed). + contents = contents.strip() + + # expand_to_list is true if an @ variant is used. In that case, + # the expansion should result in a list. Note that the caller + # is to be expecting a list in return, and not all callers do + # because not all are working in list context. Also, for list + # expansions, there can be no other text besides the variable + # expansion in the input string. + expand_to_list = '@' in match['type'] and input_str == replacement + + if run_command or file_list: + # Find the build file's directory, so commands can be run or file lists + # generated relative to it. + build_file_dir = os.path.dirname(build_file) + if build_file_dir == '' and not file_list: + # If build_file is just a leaf filename indicating a file in the + # current directory, build_file_dir might be an empty string. Set + # it to None to signal to subprocess.Popen that it should run the + # command in the current directory. + build_file_dir = None + + # Support <|(listfile.txt ...) which generates a file + # containing items from a gyp list, generated at gyp time. + # This works around actions/rules which have more inputs than will + # fit on the command line. + if file_list: + if type(contents) is list: + contents_list = contents + else: + contents_list = contents.split(' ') + replacement = contents_list[0] + if os.path.isabs(replacement): + raise GypError('| cannot handle absolute paths, got "%s"' % replacement) + + if not generator_filelist_paths: + path = os.path.join(build_file_dir, replacement) + else: + if os.path.isabs(build_file_dir): + toplevel = generator_filelist_paths['toplevel'] + rel_build_file_dir = gyp.common.RelativePath(build_file_dir, toplevel) + else: + 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) + gyp.common.EnsureDirExists(path) + + replacement = gyp.common.RelativePath(path, build_file_dir) + f = gyp.common.WriteOnDiff(path) + for i in contents_list[1:]: + f.write('%s\n' % i) + f.close() + + elif run_command: + use_shell = True + if match['is_array']: + contents = eval(contents) + use_shell = False + + # Check for a cached value to avoid executing commands, or generating + # file lists more than once. The cache key contains the command to be + # run as well as the directory to run it from, to account for commands + # that depend on their current directory. + # TODO(http://code.google.com/p/gyp/issues/detail?id=111): In theory, + # someone could author a set of GYP files where each time the command + # is invoked it produces different output by design. When the need + # arises, the syntax should be extended to support no caching off a + # command's output so it is run every time. + cache_key = (str(contents), build_file_dir) + cached_value = cached_command_results.get(cache_key, None) + if cached_value is None: + gyp.DebugOutput(gyp.DEBUG_VARIABLES, + "Executing command '%s' in directory '%s'", + contents, build_file_dir) + + replacement = '' + + if command_string == 'pymod_do_main': + # (sources/) etc. to resolve to + # and empty list if undefined. This allows actions to: + # 'action!': [ + # '>@(_sources!)', + # ], + # 'action/': [ + # '>@(_sources/)', + # ], + replacement = [] + else: + raise GypError('Undefined variable ' + contents + + ' in ' + build_file) + else: + replacement = variables[contents] + + if type(replacement) is list: + for item in replacement: + if not contents[-1] == '/' and type(item) not in (str, int): + raise GypError('Variable ' + contents + + ' must expand to a string or list of strings; ' + + 'list contains a ' + + item.__class__.__name__) + # Run through the list and handle variable expansions in it. Since + # the list is guaranteed not to contain dicts, this won't do anything + # with conditions sections. + ProcessVariablesAndConditionsInList(replacement, phase, variables, + build_file) + elif type(replacement) not in (str, int): + raise GypError('Variable ' + contents + + ' must expand to a string or list of strings; ' + + 'found a ' + replacement.__class__.__name__) + + if expand_to_list: + # Expanding in list context. It's guaranteed that there's only one + # replacement to do in |input_str| and that it's this replacement. See + # above. + if type(replacement) is list: + # If it's already a list, make a copy. + output = replacement[:] + else: + # Split it the same way sh would split arguments. + output = shlex.split(str(replacement)) + else: + # Expanding in string context. + encoded_replacement = '' + if type(replacement) is list: + # When expanding a list into string context, turn the list items + # into a string in a way that will work with a subprocess call. + # + # TODO(mark): This isn't completely correct. This should + # call a generator-provided function that observes the + # proper list-to-argument quoting rules on a specific + # platform instead of just calling the POSIX encoding + # routine. + encoded_replacement = gyp.common.EncodePOSIXShellList(replacement) + else: + encoded_replacement = replacement + + output = output[:replace_start] + str(encoded_replacement) + \ + output[replace_end:] + # Prepare for the next match iteration. + input_str = output + + if output == input: + gyp.DebugOutput(gyp.DEBUG_VARIABLES, + "Found only identity matches on %r, avoiding infinite " + "recursion.", + output) + else: + # Look for more matches now that we've replaced some, to deal with + # expanding local variables (variables defined in the same + # variables block as this one). + gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Found output %r, recursing.", output) + if type(output) is list: + if output and type(output[0]) is list: + # Leave output alone if it's a list of lists. + # We don't want such lists to be stringified. + pass + else: + new_output = [] + for item in output: + new_output.append( + ExpandVariables(item, phase, variables, build_file)) + output = new_output + else: + output = ExpandVariables(output, phase, variables, build_file) + + # Convert all strings that are canonically-represented integers into integers. + if type(output) is list: + for index in xrange(0, len(output)): + if IsStrCanonicalInt(output[index]): + output[index] = int(output[index]) + elif IsStrCanonicalInt(output): + output = int(output) + + return output + +# The same condition is often evaluated over and over again so it +# makes sense to cache as much as possible between evaluations. +cached_conditions_asts = {} + +def EvalCondition(condition, conditions_key, phase, variables, build_file): + """Returns the dict that should be used or None if the result was + that nothing should be used.""" + if type(condition) is not list: + raise GypError(conditions_key + ' must be a list') + if len(condition) < 2: + # It's possible that condition[0] won't work in which case this + # attempt will raise its own IndexError. That's probably fine. + raise GypError(conditions_key + ' ' + condition[0] + + ' must be at least length 2, not ' + str(len(condition))) + + i = 0 + result = None + while i < len(condition): + cond_expr = condition[i] + true_dict = condition[i + 1] + if type(true_dict) is not dict: + raise GypError('{} {} must be followed by a dictionary, not {}'.format( + conditions_key, cond_expr, type(true_dict))) + if len(condition) > i + 2 and type(condition[i + 2]) is dict: + false_dict = condition[i + 2] + i = i + 3 + if i != len(condition): + raise GypError('{} {} has {} unexpected trailing items'.format( + conditions_key, cond_expr, len(condition) - i)) + else: + false_dict = None + i = i + 2 + if result == None: + result = EvalSingleCondition( + cond_expr, true_dict, false_dict, phase, variables, build_file) + + return result + + +def EvalSingleCondition( + cond_expr, true_dict, false_dict, phase, variables, build_file): + """Returns true_dict if cond_expr evaluates to true, and false_dict + otherwise.""" + # Do expansions on the condition itself. Since the conditon can naturally + # contain variable references without needing to resort to GYP expansion + # syntax, this is of dubious value for variables, but someone might want to + # use a command expansion directly inside a condition. + cond_expr_expanded = ExpandVariables(cond_expr, phase, variables, + build_file) + if type(cond_expr_expanded) not in (str, int): + raise ValueError( + 'Variable expansion in this context permits str and int ' + \ + 'only, found ' + cond_expr_expanded.__class__.__name__) + + try: + if cond_expr_expanded in cached_conditions_asts: + ast_code = cached_conditions_asts[cond_expr_expanded] + else: + ast_code = compile(cond_expr_expanded, '', 'eval') + cached_conditions_asts[cond_expr_expanded] = ast_code + if eval(ast_code, {'__builtins__': None}, variables): + return true_dict + return false_dict + except SyntaxError, e: + syntax_error = SyntaxError('%s while evaluating condition \'%s\' in %s ' + 'at character %d.' % + (str(e.args[0]), e.text, build_file, e.offset), + e.filename, e.lineno, e.offset, e.text) + raise syntax_error + except NameError, e: + gyp.common.ExceptionAppend(e, 'while evaluating condition \'%s\' in %s' % + (cond_expr_expanded, build_file)) + raise GypError(e) + + +def ProcessConditionsInDict(the_dict, phase, variables, build_file): + # Process a 'conditions' or 'target_conditions' section in the_dict, + # depending on phase. + # early -> conditions + # late -> target_conditions + # latelate -> no conditions + # + # Each item in a conditions list consists of cond_expr, a string expression + # evaluated as the condition, and true_dict, a dict that will be merged into + # the_dict if cond_expr evaluates to true. Optionally, a third item, + # false_dict, may be present. false_dict is merged into the_dict if + # cond_expr evaluates to false. + # + # Any dict merged into the_dict will be recursively processed for nested + # conditionals and other expansions, also according to phase, immediately + # prior to being merged. + + if phase == PHASE_EARLY: + conditions_key = 'conditions' + elif phase == PHASE_LATE: + conditions_key = 'target_conditions' + elif phase == PHASE_LATELATE: + return + else: + assert False + + if not conditions_key in the_dict: + return + + conditions_list = the_dict[conditions_key] + # Unhook the conditions list, it's no longer needed. + del the_dict[conditions_key] + + for condition in conditions_list: + merge_dict = EvalCondition(condition, conditions_key, phase, variables, + build_file) + + if merge_dict != None: + # Expand variables and nested conditinals in the merge_dict before + # merging it. + ProcessVariablesAndConditionsInDict(merge_dict, phase, + variables, build_file) + + MergeDicts(the_dict, merge_dict, build_file, build_file) + + +def LoadAutomaticVariablesFromDict(variables, the_dict): + # Any keys with plain string values in the_dict become automatic variables. + # The variable name is the key name with a "_" character prepended. + for key, value in the_dict.iteritems(): + if type(value) in (str, int, list): + variables['_' + key] = value + + +def LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key): + # Any keys in the_dict's "variables" dict, if it has one, becomes a + # variable. The variable name is the key name in the "variables" dict. + # Variables that end with the % character are set only if they are unset in + # the variables dict. the_dict_key is the name of the key that accesses + # the_dict in the_dict's parent dict. If the_dict's parent is not a dict + # (it could be a list or it could be parentless because it is a root dict), + # the_dict_key will be None. + for key, value in the_dict.get('variables', {}).iteritems(): + if type(value) not in (str, int, list): + continue + + if key.endswith('%'): + variable_name = key[:-1] + if variable_name in variables: + # If the variable is already set, don't set it. + continue + if the_dict_key is 'variables' and variable_name in the_dict: + # If the variable is set without a % in the_dict, and the_dict is a + # variables dict (making |variables| a varaibles sub-dict of a + # variables dict), use the_dict's definition. + value = the_dict[variable_name] + else: + variable_name = key + + variables[variable_name] = value + + +def ProcessVariablesAndConditionsInDict(the_dict, phase, variables_in, + build_file, the_dict_key=None): + """Handle all variable and command expansion and conditional evaluation. + + This function is the public entry point for all variable expansions and + conditional evaluations. The variables_in dictionary will not be modified + by this function. + """ + + # Make a copy of the variables_in dict that can be modified during the + # loading of automatics and the loading of the variables dict. + variables = variables_in.copy() + LoadAutomaticVariablesFromDict(variables, the_dict) + + if 'variables' in the_dict: + # Make sure all the local variables are added to the variables + # list before we process them so that you can reference one + # variable from another. They will be fully expanded by recursion + # in ExpandVariables. + for key, value in the_dict['variables'].iteritems(): + variables[key] = value + + # Handle the associated variables dict first, so that any variable + # references within can be resolved prior to using them as variables. + # Pass a copy of the variables dict to avoid having it be tainted. + # Otherwise, it would have extra automatics added for everything that + # should just be an ordinary variable in this scope. + ProcessVariablesAndConditionsInDict(the_dict['variables'], phase, + variables, build_file, 'variables') + + LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key) + + for key, value in the_dict.iteritems(): + # Skip "variables", which was already processed if present. + if key != 'variables' and type(value) is str: + expanded = ExpandVariables(value, phase, variables, build_file) + if type(expanded) not in (str, int): + raise ValueError( + 'Variable expansion in this context permits str and int ' + \ + 'only, found ' + expanded.__class__.__name__ + ' for ' + key) + the_dict[key] = expanded + + # Variable expansion may have resulted in changes to automatics. Reload. + # TODO(mark): Optimization: only reload if no changes were made. + variables = variables_in.copy() + LoadAutomaticVariablesFromDict(variables, the_dict) + LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key) + + # Process conditions in this dict. This is done after variable expansion + # so that conditions may take advantage of expanded variables. For example, + # if the_dict contains: + # {'type': '<(library_type)', + # 'conditions': [['_type=="static_library"', { ... }]]}, + # _type, as used in the condition, will only be set to the value of + # library_type if variable expansion is performed before condition + # processing. However, condition processing should occur prior to recursion + # so that variables (both automatic and "variables" dict type) may be + # adjusted by conditions sections, merged into the_dict, and have the + # intended impact on contained dicts. + # + # This arrangement means that a "conditions" section containing a "variables" + # section will only have those variables effective in subdicts, not in + # the_dict. The workaround is to put a "conditions" section within a + # "variables" section. For example: + # {'conditions': [['os=="mac"', {'variables': {'define': 'IS_MAC'}}]], + # 'defines': ['<(define)'], + # 'my_subdict': {'defines': ['<(define)']}}, + # will not result in "IS_MAC" being appended to the "defines" list in the + # current scope but would result in it being appended to the "defines" list + # within "my_subdict". By comparison: + # {'variables': {'conditions': [['os=="mac"', {'define': 'IS_MAC'}]]}, + # 'defines': ['<(define)'], + # 'my_subdict': {'defines': ['<(define)']}}, + # will append "IS_MAC" to both "defines" lists. + + # Evaluate conditions sections, allowing variable expansions within them + # as well as nested conditionals. This will process a 'conditions' or + # 'target_conditions' section, perform appropriate merging and recursive + # conditional and variable processing, and then remove the conditions section + # from the_dict if it is present. + ProcessConditionsInDict(the_dict, phase, variables, build_file) + + # Conditional processing may have resulted in changes to automatics or the + # variables dict. Reload. + variables = variables_in.copy() + LoadAutomaticVariablesFromDict(variables, the_dict) + LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key) + + # Recurse into child dicts, or process child lists which may result in + # further recursion into descendant dicts. + for key, value in the_dict.iteritems(): + # Skip "variables" and string values, which were already processed if + # present. + if key == 'variables' or type(value) is str: + continue + if type(value) is dict: + # Pass a copy of the variables dict so that subdicts can't influence + # parents. + ProcessVariablesAndConditionsInDict(value, phase, variables, + build_file, key) + elif type(value) is list: + # The list itself can't influence the variables dict, and + # ProcessVariablesAndConditionsInList will make copies of the variables + # dict if it needs to pass it to something that can influence it. No + # copy is necessary here. + ProcessVariablesAndConditionsInList(value, phase, variables, + build_file) + elif type(value) is not int: + raise TypeError('Unknown type ' + value.__class__.__name__ + \ + ' for ' + key) + + +def ProcessVariablesAndConditionsInList(the_list, phase, variables, + build_file): + # Iterate using an index so that new values can be assigned into the_list. + index = 0 + while index < len(the_list): + item = the_list[index] + if type(item) is dict: + # Make a copy of the variables dict so that it won't influence anything + # outside of its own scope. + ProcessVariablesAndConditionsInDict(item, phase, variables, build_file) + elif type(item) is list: + ProcessVariablesAndConditionsInList(item, phase, variables, build_file) + elif type(item) is str: + expanded = ExpandVariables(item, phase, variables, build_file) + if type(expanded) in (str, int): + the_list[index] = expanded + elif type(expanded) is list: + the_list[index:index+1] = expanded + index += len(expanded) + + # index now identifies the next item to examine. Continue right now + # without falling into the index increment below. + continue + else: + raise ValueError( + 'Variable expansion in this context permits strings and ' + \ + 'lists only, found ' + expanded.__class__.__name__ + ' at ' + \ + index) + elif type(item) is not int: + raise TypeError('Unknown type ' + item.__class__.__name__ + \ + ' at index ' + index) + index = index + 1 + + +def BuildTargetsDict(data): + """Builds a dict mapping fully-qualified target names to their target dicts. + + |data| is a dict mapping loaded build files by pathname relative to the + current directory. Values in |data| are build file contents. For each + |data| value with a "targets" key, the value of the "targets" key is taken + as a list containing target dicts. Each target's fully-qualified name is + constructed from the pathname of the build file (|data| key) and its + "target_name" property. These fully-qualified names are used as the keys + in the returned dict. These keys provide access to the target dicts, + the dicts in the "targets" lists. + """ + + targets = {} + for build_file in data['target_build_files']: + for target in data[build_file].get('targets', []): + target_name = gyp.common.QualifiedTarget(build_file, + target['target_name'], + target['toolset']) + if target_name in targets: + raise GypError('Duplicate target definitions for ' + target_name) + targets[target_name] = target + + return targets + + +def QualifyDependencies(targets): + """Make dependency links fully-qualified relative to the current directory. + + |targets| is a dict mapping fully-qualified target names to their target + dicts. For each target in this dict, keys known to contain dependency + links are examined, and any dependencies referenced will be rewritten + so that they are fully-qualified and relative to the current directory. + All rewritten dependencies are suitable for use as keys to |targets| or a + similar dict. + """ + + all_dependency_sections = [dep + op + for dep in dependency_sections + for op in ('', '!', '/')] + + for target, target_dict in targets.iteritems(): + target_build_file = gyp.common.BuildFile(target) + toolset = target_dict['toolset'] + for dependency_key in all_dependency_sections: + dependencies = target_dict.get(dependency_key, []) + for index in xrange(0, len(dependencies)): + dep_file, dep_target, dep_toolset = gyp.common.ResolveTarget( + target_build_file, dependencies[index], toolset) + if not multiple_toolsets: + # Ignore toolset specification in the dependency if it is specified. + dep_toolset = toolset + dependency = gyp.common.QualifiedTarget(dep_file, + dep_target, + dep_toolset) + dependencies[index] = dependency + + # Make sure anything appearing in a list other than "dependencies" also + # appears in the "dependencies" list. + if dependency_key != 'dependencies' and \ + dependency not in target_dict['dependencies']: + raise GypError('Found ' + dependency + ' in ' + dependency_key + + ' of ' + target + ', but not in dependencies') + + +def ExpandWildcardDependencies(targets, data): + """Expands dependencies specified as build_file:*. + + For each target in |targets|, examines sections containing links to other + targets. If any such section contains a link of the form build_file:*, it + is taken as a wildcard link, and is expanded to list each target in + build_file. The |data| dict provides access to build file dicts. + + Any target that does not wish to be included by wildcard can provide an + optional "suppress_wildcard" key in its target dict. When present and + true, a wildcard dependency link will not include such targets. + + All dependency names, including the keys to |targets| and the values in each + dependency list, must be qualified when this function is called. + """ + + for target, target_dict in targets.iteritems(): + toolset = target_dict['toolset'] + target_build_file = gyp.common.BuildFile(target) + for dependency_key in dependency_sections: + dependencies = target_dict.get(dependency_key, []) + + # Loop this way instead of "for dependency in" or "for index in xrange" + # because the dependencies list will be modified within the loop body. + index = 0 + while index < len(dependencies): + (dependency_build_file, dependency_target, dependency_toolset) = \ + gyp.common.ParseQualifiedTarget(dependencies[index]) + if dependency_target != '*' and dependency_toolset != '*': + # Not a wildcard. Keep it moving. + index = index + 1 + continue + + if dependency_build_file == target_build_file: + # It's an error for a target to depend on all other targets in + # the same file, because a target cannot depend on itself. + raise GypError('Found wildcard in ' + dependency_key + ' of ' + + target + ' referring to same build file') + + # Take the wildcard out and adjust the index so that the next + # dependency in the list will be processed the next time through the + # loop. + del dependencies[index] + index = index - 1 + + # Loop through the targets in the other build file, adding them to + # this target's list of dependencies in place of the removed + # wildcard. + dependency_target_dicts = data[dependency_build_file]['targets'] + for dependency_target_dict in dependency_target_dicts: + if int(dependency_target_dict.get('suppress_wildcard', False)): + continue + dependency_target_name = dependency_target_dict['target_name'] + if (dependency_target != '*' and + dependency_target != dependency_target_name): + continue + dependency_target_toolset = dependency_target_dict['toolset'] + if (dependency_toolset != '*' and + dependency_toolset != dependency_target_toolset): + continue + dependency = gyp.common.QualifiedTarget(dependency_build_file, + dependency_target_name, + dependency_target_toolset) + index = index + 1 + dependencies.insert(index, dependency) + + index = index + 1 + + +def Unify(l): + """Removes duplicate elements from l, keeping the first element.""" + seen = {} + return [seen.setdefault(e, e) for e in l if e not in seen] + + +def RemoveDuplicateDependencies(targets): + """Makes sure every dependency appears only once in all targets's dependency + lists.""" + for target_name, target_dict in targets.iteritems(): + for dependency_key in dependency_sections: + dependencies = target_dict.get(dependency_key, []) + if dependencies: + target_dict[dependency_key] = Unify(dependencies) + + +def Filter(l, item): + """Removes item from l.""" + res = {} + return [res.setdefault(e, e) for e in l if e != item] + + +def RemoveSelfDependencies(targets): + """Remove self dependencies from targets that have the prune_self_dependency + variable set.""" + for target_name, target_dict in targets.iteritems(): + for dependency_key in dependency_sections: + dependencies = target_dict.get(dependency_key, []) + if dependencies: + for t in dependencies: + if t == target_name: + if targets[t].get('variables', {}).get('prune_self_dependency', 0): + target_dict[dependency_key] = Filter(dependencies, target_name) + + +def RemoveLinkDependenciesFromNoneTargets(targets): + """Remove dependencies having the 'link_dependency' attribute from the 'none' + targets.""" + for target_name, target_dict in targets.iteritems(): + for dependency_key in dependency_sections: + dependencies = target_dict.get(dependency_key, []) + if dependencies: + for t in dependencies: + if target_dict.get('type', None) == 'none': + if targets[t].get('variables', {}).get('link_dependency', 0): + target_dict[dependency_key] = \ + Filter(target_dict[dependency_key], t) + + +class DependencyGraphNode(object): + """ + + Attributes: + ref: A reference to an object that this DependencyGraphNode represents. + dependencies: List of DependencyGraphNodes on which this one depends. + dependents: List of DependencyGraphNodes that depend on this one. + """ + + class CircularException(GypError): + pass + + def __init__(self, ref): + self.ref = ref + self.dependencies = [] + self.dependents = [] + + def __repr__(self): + return '' % self.ref + + def FlattenToList(self): + # flat_list is the sorted list of dependencies - actually, the list items + # are the "ref" attributes of DependencyGraphNodes. Every target will + # appear in flat_list after all of its dependencies, and before all of its + # dependents. + flat_list = OrderedSet() + + # in_degree_zeros is the list of DependencyGraphNodes that have no + # dependencies not in flat_list. Initially, it is a copy of the children + # of this node, because when the graph was built, nodes with no + # dependencies were made implicit dependents of the root node. + in_degree_zeros = set(self.dependents[:]) + + while in_degree_zeros: + # Nodes in in_degree_zeros have no dependencies not in flat_list, so they + # can be appended to flat_list. Take these nodes out of in_degree_zeros + # as work progresses, so that the next node to process from the list can + # always be accessed at a consistent position. + node = in_degree_zeros.pop() + flat_list.add(node.ref) + + # Look at dependents of the node just added to flat_list. Some of them + # may now belong in in_degree_zeros. + for node_dependent in node.dependents: + is_in_degree_zero = True + # TODO: We want to check through the + # node_dependent.dependencies list but if it's long and we + # always start at the beginning, then we get O(n^2) behaviour. + for node_dependent_dependency in node_dependent.dependencies: + if not node_dependent_dependency.ref in flat_list: + # The dependent one or more dependencies not in flat_list. There + # will be more chances to add it to flat_list when examining + # it again as a dependent of those other dependencies, provided + # that there are no cycles. + is_in_degree_zero = False + break + + if is_in_degree_zero: + # All of the dependent's dependencies are already in flat_list. Add + # it to in_degree_zeros where it will be processed in a future + # iteration of the outer loop. + in_degree_zeros.add(node_dependent) + + return list(flat_list) + + def FindCycles(self): + """ + Returns a list of cycles in the graph, where each cycle is its own list. + """ + results = [] + visited = set() + + def Visit(node, path): + for child in node.dependents: + if child in path: + results.append([child] + path[:path.index(child) + 1]) + elif not child in visited: + visited.add(child) + Visit(child, [child] + path) + + visited.add(self) + Visit(self, [self]) + + return results + + def DirectDependencies(self, dependencies=None): + """Returns a list of just direct dependencies.""" + if dependencies == None: + dependencies = [] + + for dependency in self.dependencies: + # Check for None, corresponding to the root node. + if dependency.ref != None and dependency.ref not in dependencies: + dependencies.append(dependency.ref) + + return dependencies + + def _AddImportedDependencies(self, targets, dependencies=None): + """Given a list of direct dependencies, adds indirect dependencies that + other dependencies have declared to export their settings. + + This method does not operate on self. Rather, it operates on the list + of dependencies in the |dependencies| argument. For each dependency in + that list, if any declares that it exports the settings of one of its + own dependencies, those dependencies whose settings are "passed through" + are added to the list. As new items are added to the list, they too will + be processed, so it is possible to import settings through multiple levels + of dependencies. + + This method is not terribly useful on its own, it depends on being + "primed" with a list of direct dependencies such as one provided by + DirectDependencies. DirectAndImportedDependencies is intended to be the + public entry point. + """ + + if dependencies == None: + dependencies = [] + + index = 0 + while index < len(dependencies): + dependency = dependencies[index] + dependency_dict = targets[dependency] + # Add any dependencies whose settings should be imported to the list + # if not already present. Newly-added items will be checked for + # their own imports when the list iteration reaches them. + # Rather than simply appending new items, insert them after the + # dependency that exported them. This is done to more closely match + # the depth-first method used by DeepDependencies. + add_index = 1 + for imported_dependency in \ + dependency_dict.get('export_dependent_settings', []): + if imported_dependency not in dependencies: + dependencies.insert(index + add_index, imported_dependency) + add_index = add_index + 1 + index = index + 1 + + return dependencies + + def DirectAndImportedDependencies(self, targets, dependencies=None): + """Returns a list of a target's direct dependencies and all indirect + dependencies that a dependency has advertised settings should be exported + through the dependency for. + """ + + dependencies = self.DirectDependencies(dependencies) + return self._AddImportedDependencies(targets, dependencies) + + def DeepDependencies(self, dependencies=None): + """Returns an OrderedSet of all of a target's dependencies, recursively.""" + if dependencies is None: + # Using a list to get ordered output and a set to do fast "is it + # already added" checks. + dependencies = OrderedSet() + + for dependency in self.dependencies: + # Check for None, corresponding to the root node. + if dependency.ref is None: + continue + if dependency.ref not in dependencies: + dependency.DeepDependencies(dependencies) + dependencies.add(dependency.ref) + + return dependencies + + def _LinkDependenciesInternal(self, targets, include_shared_libraries, + dependencies=None, initial=True): + """Returns an OrderedSet of dependency targets that are linked + into this target. + + This function has a split personality, depending on the setting of + |initial|. Outside callers should always leave |initial| at its default + setting. + + When adding a target to the list of dependencies, this function will + recurse into itself with |initial| set to False, to collect dependencies + that are linked into the linkable target for which the list is being built. + + If |include_shared_libraries| is False, the resulting dependencies will not + include shared_library targets that are linked into this target. + """ + if dependencies is None: + # Using a list to get ordered output and a set to do fast "is it + # already added" checks. + dependencies = OrderedSet() + + # Check for None, corresponding to the root node. + if self.ref is None: + return dependencies + + # It's kind of sucky that |targets| has to be passed into this function, + # but that's presently the easiest way to access the target dicts so that + # this function can find target types. + + if 'target_name' not in targets[self.ref]: + raise GypError("Missing 'target_name' field in target.") + + if 'type' not in targets[self.ref]: + raise GypError("Missing 'type' field in target %s" % + targets[self.ref]['target_name']) + + target_type = targets[self.ref]['type'] + + is_linkable = target_type in linkable_types + + if initial and not is_linkable: + # If this is the first target being examined and it's not linkable, + # return an empty list of link dependencies, because the link + # dependencies are intended to apply to the target itself (initial is + # True) and this target won't be linked. + return dependencies + + # Don't traverse 'none' targets if explicitly excluded. + if (target_type == 'none' and + not targets[self.ref].get('dependencies_traverse', True)): + dependencies.add(self.ref) + return dependencies + + # Executables, mac kernel extensions and loadable modules are already fully + # and finally linked. Nothing else can be a link dependency of them, there + # can only be dependencies in the sense that a dependent target might run + # an executable or load the loadable_module. + if not initial and target_type in ('executable', 'loadable_module', + 'mac_kernel_extension'): + return dependencies + + # Shared libraries are already fully linked. They should only be included + # in |dependencies| when adjusting static library dependencies (in order to + # link against the shared_library's import lib), but should not be included + # in |dependencies| when propagating link_settings. + # The |include_shared_libraries| flag controls which of these two cases we + # are handling. + if (not initial and target_type == 'shared_library' and + not include_shared_libraries): + return dependencies + + # The target is linkable, add it to the list of link dependencies. + if self.ref not in dependencies: + dependencies.add(self.ref) + if initial or not is_linkable: + # If this is a subsequent target and it's linkable, don't look any + # further for linkable dependencies, as they'll already be linked into + # this target linkable. Always look at dependencies of the initial + # target, and always look at dependencies of non-linkables. + for dependency in self.dependencies: + dependency._LinkDependenciesInternal(targets, + include_shared_libraries, + dependencies, False) + + return dependencies + + def DependenciesForLinkSettings(self, targets): + """ + Returns a list of dependency targets whose link_settings should be merged + into this target. + """ + + # TODO(sbaig) Currently, chrome depends on the bug that shared libraries' + # link_settings are propagated. So for now, we will allow it, unless the + # 'allow_sharedlib_linksettings_propagation' flag is explicitly set to + # False. Once chrome is fixed, we can remove this flag. + include_shared_libraries = \ + targets[self.ref].get('allow_sharedlib_linksettings_propagation', True) + return self._LinkDependenciesInternal(targets, include_shared_libraries) + + def DependenciesToLinkAgainst(self, targets): + """ + Returns a list of dependency targets that are linked into this target. + """ + return self._LinkDependenciesInternal(targets, True) + + +def BuildDependencyList(targets): + # Create a DependencyGraphNode for each target. Put it into a dict for easy + # access. + dependency_nodes = {} + for target, spec in targets.iteritems(): + if target not in dependency_nodes: + dependency_nodes[target] = DependencyGraphNode(target) + + # Set up the dependency links. Targets that have no dependencies are treated + # as dependent on root_node. + root_node = DependencyGraphNode(None) + for target, spec in targets.iteritems(): + target_node = dependency_nodes[target] + target_build_file = gyp.common.BuildFile(target) + dependencies = spec.get('dependencies') + if not dependencies: + target_node.dependencies = [root_node] + root_node.dependents.append(target_node) + else: + for dependency in dependencies: + dependency_node = dependency_nodes.get(dependency) + if not dependency_node: + raise GypError("Dependency '%s' not found while " + "trying to load target %s" % (dependency, target)) + target_node.dependencies.append(dependency_node) + dependency_node.dependents.append(target_node) + + flat_list = root_node.FlattenToList() + + # If there's anything left unvisited, there must be a circular dependency + # (cycle). + if len(flat_list) != len(targets): + if not root_node.dependents: + # If all targets have dependencies, add the first target as a dependent + # of root_node so that the cycle can be discovered from root_node. + target = targets.keys()[0] + target_node = dependency_nodes[target] + target_node.dependencies.append(root_node) + root_node.dependents.append(target_node) + + cycles = [] + for cycle in root_node.FindCycles(): + paths = [node.ref for node in cycle] + cycles.append('Cycle: %s' % ' -> '.join(paths)) + raise DependencyGraphNode.CircularException( + 'Cycles in dependency graph detected:\n' + '\n'.join(cycles)) + + return [dependency_nodes, flat_list] + + +def VerifyNoGYPFileCircularDependencies(targets): + # Create a DependencyGraphNode for each gyp file containing a target. Put + # it into a dict for easy access. + dependency_nodes = {} + for target in targets.iterkeys(): + build_file = gyp.common.BuildFile(target) + if not build_file in dependency_nodes: + dependency_nodes[build_file] = DependencyGraphNode(build_file) + + # Set up the dependency links. + for target, spec in targets.iteritems(): + build_file = gyp.common.BuildFile(target) + build_file_node = dependency_nodes[build_file] + target_dependencies = spec.get('dependencies', []) + for dependency in target_dependencies: + try: + dependency_build_file = gyp.common.BuildFile(dependency) + except GypError, e: + gyp.common.ExceptionAppend( + e, 'while computing dependencies of .gyp file %s' % build_file) + raise + + if dependency_build_file == build_file: + # A .gyp file is allowed to refer back to itself. + continue + dependency_node = dependency_nodes.get(dependency_build_file) + if not dependency_node: + raise GypError("Dependancy '%s' not found" % dependency_build_file) + if dependency_node not in build_file_node.dependencies: + build_file_node.dependencies.append(dependency_node) + dependency_node.dependents.append(build_file_node) + + + # Files that have no dependencies are treated as dependent on root_node. + root_node = DependencyGraphNode(None) + for build_file_node in dependency_nodes.itervalues(): + if len(build_file_node.dependencies) == 0: + build_file_node.dependencies.append(root_node) + root_node.dependents.append(build_file_node) + + flat_list = root_node.FlattenToList() + + # If there's anything left unvisited, there must be a circular dependency + # (cycle). + if len(flat_list) != len(dependency_nodes): + if not root_node.dependents: + # If all files have dependencies, add the first file as a dependent + # of root_node so that the cycle can be discovered from root_node. + file_node = dependency_nodes.values()[0] + file_node.dependencies.append(root_node) + root_node.dependents.append(file_node) + cycles = [] + for cycle in root_node.FindCycles(): + paths = [node.ref for node in cycle] + cycles.append('Cycle: %s' % ' -> '.join(paths)) + raise DependencyGraphNode.CircularException( + 'Cycles in .gyp file dependency graph detected:\n' + '\n'.join(cycles)) + + +def DoDependentSettings(key, flat_list, targets, dependency_nodes): + # key should be one of all_dependent_settings, direct_dependent_settings, + # or link_settings. + + for target in flat_list: + target_dict = targets[target] + build_file = gyp.common.BuildFile(target) + + if key == 'all_dependent_settings': + dependencies = dependency_nodes[target].DeepDependencies() + elif key == 'direct_dependent_settings': + dependencies = \ + dependency_nodes[target].DirectAndImportedDependencies(targets) + elif key == 'link_settings': + dependencies = \ + dependency_nodes[target].DependenciesForLinkSettings(targets) + else: + raise GypError("DoDependentSettings doesn't know how to determine " + 'dependencies for ' + key) + + for dependency in dependencies: + dependency_dict = targets[dependency] + if not key in dependency_dict: + continue + dependency_build_file = gyp.common.BuildFile(dependency) + MergeDicts(target_dict, dependency_dict[key], + build_file, dependency_build_file) + + +def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, + sort_dependencies): + # Recompute target "dependencies" properties. For each static library + # target, remove "dependencies" entries referring to other static libraries, + # unless the dependency has the "hard_dependency" attribute set. For each + # linkable target, add a "dependencies" entry referring to all of the + # target's computed list of link dependencies (including static libraries + # if no such entry is already present. + for target in flat_list: + target_dict = targets[target] + target_type = target_dict['type'] + + if target_type == 'static_library': + if not 'dependencies' in target_dict: + continue + + target_dict['dependencies_original'] = target_dict.get( + 'dependencies', [])[:] + + # A static library should not depend on another static library unless + # the dependency relationship is "hard," which should only be done when + # a dependent relies on some side effect other than just the build + # product, like a rule or action output. Further, if a target has a + # non-hard dependency, but that dependency exports a hard dependency, + # the non-hard dependency can safely be removed, but the exported hard + # dependency must be added to the target to keep the same dependency + # ordering. + dependencies = \ + dependency_nodes[target].DirectAndImportedDependencies(targets) + index = 0 + while index < len(dependencies): + dependency = dependencies[index] + dependency_dict = targets[dependency] + + # Remove every non-hard static library dependency and remove every + # non-static library dependency that isn't a direct dependency. + if (dependency_dict['type'] == 'static_library' and \ + not dependency_dict.get('hard_dependency', False)) or \ + (dependency_dict['type'] != 'static_library' and \ + not dependency in target_dict['dependencies']): + # Take the dependency out of the list, and don't increment index + # because the next dependency to analyze will shift into the index + # formerly occupied by the one being removed. + del dependencies[index] + else: + index = index + 1 + + # Update the dependencies. If the dependencies list is empty, it's not + # needed, so unhook it. + if len(dependencies) > 0: + target_dict['dependencies'] = dependencies + else: + del target_dict['dependencies'] + + elif target_type in linkable_types: + # Get a list of dependency targets that should be linked into this + # target. Add them to the dependencies list if they're not already + # present. + + link_dependencies = \ + dependency_nodes[target].DependenciesToLinkAgainst(targets) + for dependency in link_dependencies: + if dependency == target: + continue + if not 'dependencies' in target_dict: + target_dict['dependencies'] = [] + if not dependency in target_dict['dependencies']: + target_dict['dependencies'].append(dependency) + # Sort the dependencies list in the order from dependents to dependencies. + # e.g. If A and B depend on C and C depends on D, sort them in A, B, C, D. + # Note: flat_list is already sorted in the order from dependencies to + # dependents. + if sort_dependencies and 'dependencies' in target_dict: + target_dict['dependencies'] = [dep for dep in reversed(flat_list) + if dep in target_dict['dependencies']] + + +# Initialize this here to speed up MakePathRelative. +exception_re = re.compile(r'''["']?[-/$<>^]''') + + +def MakePathRelative(to_file, fro_file, item): + # If item is a relative path, it's relative to the build file dict that it's + # coming from. Fix it up to make it relative to the build file dict that + # it's going into. + # Exception: any |item| that begins with these special characters is + # returned without modification. + # / Used when a path is already absolute (shortcut optimization; + # such paths would be returned as absolute anyway) + # $ Used for build environment variables + # - Used for some build environment flags (such as -lapr-1 in a + # "libraries" section) + # < Used for our own variable and command expansions (see ExpandVariables) + # > Used for our own variable and command expansions (see ExpandVariables) + # ^ Used for our own variable and command expansions (see ExpandVariables) + # + # "/' Used when a value is quoted. If these are present, then we + # check the second character instead. + # + if to_file == fro_file or exception_re.match(item): + return item + else: + # TODO(dglazkov) The backslash/forward-slash replacement at the end is a + # temporary measure. This should really be addressed by keeping all paths + # in POSIX until actual project generation. + ret = os.path.normpath(os.path.join( + gyp.common.RelativePath(os.path.dirname(fro_file), + os.path.dirname(to_file)), + item)).replace('\\', '/') + if item[-1:] == '/': + ret += '/' + return ret + +def MergeLists(to, fro, to_file, fro_file, is_paths=False, append=True): + # Python documentation recommends objects which do not support hash + # set this value to None. Python library objects follow this rule. + is_hashable = lambda val: val.__hash__ + + # If x is hashable, returns whether x is in s. Else returns whether x is in l. + def is_in_set_or_list(x, s, l): + if is_hashable(x): + return x in s + return x in l + + prepend_index = 0 + + # Make membership testing of hashables in |to| (in particular, strings) + # faster. + hashable_to_set = set(x for x in to if is_hashable(x)) + for item in fro: + singleton = False + if type(item) in (str, int): + # The cheap and easy case. + if is_paths: + to_item = MakePathRelative(to_file, fro_file, item) + else: + to_item = item + + if not (type(item) is str and item.startswith('-')): + # Any string that doesn't begin with a "-" is a singleton - it can + # only appear once in a list, to be enforced by the list merge append + # or prepend. + singleton = True + elif type(item) is dict: + # Make a copy of the dictionary, continuing to look for paths to fix. + # The other intelligent aspects of merge processing won't apply because + # item is being merged into an empty dict. + to_item = {} + MergeDicts(to_item, item, to_file, fro_file) + elif type(item) is list: + # Recurse, making a copy of the list. If the list contains any + # descendant dicts, path fixing will occur. Note that here, custom + # values for is_paths and append are dropped; those are only to be + # applied to |to| and |fro|, not sublists of |fro|. append shouldn't + # matter anyway because the new |to_item| list is empty. + to_item = [] + MergeLists(to_item, item, to_file, fro_file) + else: + raise TypeError( + 'Attempt to merge list item of unsupported type ' + \ + item.__class__.__name__) + + if append: + # If appending a singleton that's already in the list, don't append. + # This ensures that the earliest occurrence of the item will stay put. + if not singleton or not is_in_set_or_list(to_item, hashable_to_set, to): + to.append(to_item) + if is_hashable(to_item): + hashable_to_set.add(to_item) + else: + # If prepending a singleton that's already in the list, remove the + # existing instance and proceed with the prepend. This ensures that the + # item appears at the earliest possible position in the list. + while singleton and to_item in to: + to.remove(to_item) + + # Don't just insert everything at index 0. That would prepend the new + # items to the list in reverse order, which would be an unwelcome + # surprise. + to.insert(prepend_index, to_item) + if is_hashable(to_item): + hashable_to_set.add(to_item) + prepend_index = prepend_index + 1 + + +def MergeDicts(to, fro, to_file, fro_file): + # I wanted to name the parameter "from" but it's a Python keyword... + for k, v in fro.iteritems(): + # It would be nice to do "if not k in to: to[k] = v" but that wouldn't give + # copy semantics. Something else may want to merge from the |fro| dict + # later, and having the same dict ref pointed to twice in the tree isn't + # what anyone wants considering that the dicts may subsequently be + # modified. + if k in to: + bad_merge = False + if type(v) in (str, int): + if type(to[k]) not in (str, int): + bad_merge = True + elif type(v) is not type(to[k]): + bad_merge = True + + if bad_merge: + raise TypeError( + 'Attempt to merge dict value of type ' + v.__class__.__name__ + \ + ' into incompatible type ' + to[k].__class__.__name__ + \ + ' for key ' + k) + if type(v) in (str, int): + # Overwrite the existing value, if any. Cheap and easy. + is_path = IsPathSection(k) + if is_path: + to[k] = MakePathRelative(to_file, fro_file, v) + else: + to[k] = v + elif type(v) is dict: + # Recurse, guaranteeing copies will be made of objects that require it. + if not k in to: + to[k] = {} + MergeDicts(to[k], v, to_file, fro_file) + elif type(v) is list: + # Lists in dicts can be merged with different policies, depending on + # how the key in the "from" dict (k, the from-key) is written. + # + # If the from-key has ...the to-list will have this action + # this character appended:... applied when receiving the from-list: + # = replace + # + prepend + # ? set, only if to-list does not yet exist + # (none) append + # + # This logic is list-specific, but since it relies on the associated + # dict key, it's checked in this dict-oriented function. + ext = k[-1] + append = True + if ext == '=': + list_base = k[:-1] + lists_incompatible = [list_base, list_base + '?'] + to[list_base] = [] + elif ext == '+': + list_base = k[:-1] + lists_incompatible = [list_base + '=', list_base + '?'] + append = False + elif ext == '?': + list_base = k[:-1] + lists_incompatible = [list_base, list_base + '=', list_base + '+'] + else: + list_base = k + lists_incompatible = [list_base + '=', list_base + '?'] + + # Some combinations of merge policies appearing together are meaningless. + # It's stupid to replace and append simultaneously, for example. Append + # and prepend are the only policies that can coexist. + for list_incompatible in lists_incompatible: + if list_incompatible in fro: + raise GypError('Incompatible list policies ' + k + ' and ' + + list_incompatible) + + if list_base in to: + if ext == '?': + # If the key ends in "?", the list will only be merged if it doesn't + # already exist. + continue + elif type(to[list_base]) is not list: + # This may not have been checked above if merging in a list with an + # extension character. + raise TypeError( + 'Attempt to merge dict value of type ' + v.__class__.__name__ + \ + ' into incompatible type ' + to[list_base].__class__.__name__ + \ + ' for key ' + list_base + '(' + k + ')') + else: + to[list_base] = [] + + # Call MergeLists, which will make copies of objects that require it. + # MergeLists can recurse back into MergeDicts, although this will be + # to make copies of dicts (with paths fixed), there will be no + # subsequent dict "merging" once entering a list because lists are + # always replaced, appended to, or prepended to. + is_paths = IsPathSection(list_base) + MergeLists(to[list_base], v, to_file, fro_file, is_paths, append) + else: + raise TypeError( + 'Attempt to merge dict value of unsupported type ' + \ + v.__class__.__name__ + ' for key ' + k) + + +def MergeConfigWithInheritance(new_configuration_dict, build_file, + target_dict, configuration, visited): + # Skip if previously visted. + if configuration in visited: + return + + # Look at this configuration. + configuration_dict = target_dict['configurations'][configuration] + + # Merge in parents. + for parent in configuration_dict.get('inherit_from', []): + MergeConfigWithInheritance(new_configuration_dict, build_file, + target_dict, parent, visited + [configuration]) + + # Merge it into the new config. + MergeDicts(new_configuration_dict, configuration_dict, + build_file, build_file) + + # Drop abstract. + if 'abstract' in new_configuration_dict: + del new_configuration_dict['abstract'] + + +def SetUpConfigurations(target, target_dict): + # key_suffixes is a list of key suffixes that might appear on key names. + # These suffixes are handled in conditional evaluations (for =, +, and ?) + # and rules/exclude processing (for ! and /). Keys with these suffixes + # should be treated the same as keys without. + key_suffixes = ['=', '+', '?', '!', '/'] + + build_file = gyp.common.BuildFile(target) + + # Provide a single configuration by default if none exists. + # TODO(mark): Signal an error if default_configurations exists but + # configurations does not. + if not 'configurations' in target_dict: + target_dict['configurations'] = {'Default': {}} + if not 'default_configuration' in target_dict: + concrete = [i for (i, config) in target_dict['configurations'].iteritems() + if not config.get('abstract')] + target_dict['default_configuration'] = sorted(concrete)[0] + + merged_configurations = {} + configs = target_dict['configurations'] + for (configuration, old_configuration_dict) in configs.iteritems(): + # Skip abstract configurations (saves work only). + if old_configuration_dict.get('abstract'): + continue + # Configurations inherit (most) settings from the enclosing target scope. + # Get the inheritance relationship right by making a copy of the target + # dict. + new_configuration_dict = {} + for (key, target_val) in target_dict.iteritems(): + key_ext = key[-1:] + if key_ext in key_suffixes: + key_base = key[:-1] + else: + key_base = key + if not key_base in non_configuration_keys: + new_configuration_dict[key] = gyp.simple_copy.deepcopy(target_val) + + # Merge in configuration (with all its parents first). + MergeConfigWithInheritance(new_configuration_dict, build_file, + target_dict, configuration, []) + + merged_configurations[configuration] = new_configuration_dict + + # Put the new configurations back into the target dict as a configuration. + for configuration in merged_configurations.keys(): + target_dict['configurations'][configuration] = ( + merged_configurations[configuration]) + + # Now drop all the abstract ones. + for configuration in target_dict['configurations'].keys(): + old_configuration_dict = target_dict['configurations'][configuration] + if old_configuration_dict.get('abstract'): + del target_dict['configurations'][configuration] + + # Now that all of the target's configurations have been built, go through + # the target dict's keys and remove everything that's been moved into a + # "configurations" section. + delete_keys = [] + for key in target_dict: + key_ext = key[-1:] + if key_ext in key_suffixes: + key_base = key[:-1] + else: + key_base = key + if not key_base in non_configuration_keys: + delete_keys.append(key) + for key in delete_keys: + del target_dict[key] + + # Check the configurations to see if they contain invalid keys. + for configuration in target_dict['configurations'].keys(): + configuration_dict = target_dict['configurations'][configuration] + for key in configuration_dict.keys(): + if key in invalid_configuration_keys: + raise GypError('%s not allowed in the %s configuration, found in ' + 'target %s' % (key, configuration, target)) + + + +def ProcessListFiltersInDict(name, the_dict): + """Process regular expression and exclusion-based filters on lists. + + An exclusion list is in a dict key named with a trailing "!", like + "sources!". Every item in such a list is removed from the associated + main list, which in this example, would be "sources". Removed items are + placed into a "sources_excluded" list in the dict. + + Regular expression (regex) filters are contained in dict keys named with a + trailing "/", such as "sources/" to operate on the "sources" list. Regex + filters in a dict take the form: + 'sources/': [ ['exclude', '_(linux|mac|win)\\.cc$'], + ['include', '_mac\\.cc$'] ], + The first filter says to exclude all files ending in _linux.cc, _mac.cc, and + _win.cc. The second filter then includes all files ending in _mac.cc that + are now or were once in the "sources" list. Items matching an "exclude" + filter are subject to the same processing as would occur if they were listed + by name in an exclusion list (ending in "!"). Items matching an "include" + filter are brought back into the main list if previously excluded by an + exclusion list or exclusion regex filter. Subsequent matching "exclude" + patterns can still cause items to be excluded after matching an "include". + """ + + # Look through the dictionary for any lists whose keys end in "!" or "/". + # These are lists that will be treated as exclude lists and regular + # expression-based exclude/include lists. Collect the lists that are + # needed first, looking for the lists that they operate on, and assemble + # then into |lists|. This is done in a separate loop up front, because + # the _included and _excluded keys need to be added to the_dict, and that + # can't be done while iterating through it. + + lists = [] + del_lists = [] + for key, value in the_dict.iteritems(): + operation = key[-1] + if operation != '!' and operation != '/': + continue + + if type(value) is not list: + raise ValueError(name + ' key ' + key + ' must be list, not ' + \ + value.__class__.__name__) + + list_key = key[:-1] + if list_key not in the_dict: + # This happens when there's a list like "sources!" but no corresponding + # "sources" list. Since there's nothing for it to operate on, queue up + # the "sources!" list for deletion now. + del_lists.append(key) + continue + + if type(the_dict[list_key]) is not list: + value = the_dict[list_key] + raise ValueError(name + ' key ' + list_key + \ + ' must be list, not ' + \ + value.__class__.__name__ + ' when applying ' + \ + {'!': 'exclusion', '/': 'regex'}[operation]) + + if not list_key in lists: + lists.append(list_key) + + # Delete the lists that are known to be unneeded at this point. + for del_list in del_lists: + del the_dict[del_list] + + for list_key in lists: + the_list = the_dict[list_key] + + # Initialize the list_actions list, which is parallel to the_list. Each + # item in list_actions identifies whether the corresponding item in + # the_list should be excluded, unconditionally preserved (included), or + # whether no exclusion or inclusion has been applied. Items for which + # no exclusion or inclusion has been applied (yet) have value -1, items + # excluded have value 0, and items included have value 1. Includes and + # excludes override previous actions. All items in list_actions are + # initialized to -1 because no excludes or includes have been processed + # yet. + list_actions = list((-1,) * len(the_list)) + + exclude_key = list_key + '!' + if exclude_key in the_dict: + for exclude_item in the_dict[exclude_key]: + for index in xrange(0, len(the_list)): + if exclude_item == the_list[index]: + # This item matches the exclude_item, so set its action to 0 + # (exclude). + list_actions[index] = 0 + + # The "whatever!" list is no longer needed, dump it. + del the_dict[exclude_key] + + regex_key = list_key + '/' + if regex_key in the_dict: + for regex_item in the_dict[regex_key]: + [action, pattern] = regex_item + pattern_re = re.compile(pattern) + + if action == 'exclude': + # This item matches an exclude regex, so set its value to 0 (exclude). + action_value = 0 + elif action == 'include': + # This item matches an include regex, so set its value to 1 (include). + action_value = 1 + else: + # This is an action that doesn't make any sense. + raise ValueError('Unrecognized action ' + action + ' in ' + name + \ + ' key ' + regex_key) + + for index in xrange(0, len(the_list)): + list_item = the_list[index] + if list_actions[index] == action_value: + # Even if the regex matches, nothing will change so continue (regex + # searches are expensive). + continue + if pattern_re.search(list_item): + # Regular expression match. + list_actions[index] = action_value + + # The "whatever/" list is no longer needed, dump it. + del the_dict[regex_key] + + # Add excluded items to the excluded list. + # + # Note that exclude_key ("sources!") is different from excluded_key + # ("sources_excluded"). The exclude_key list is input and it was already + # processed and deleted; the excluded_key list is output and it's about + # to be created. + excluded_key = list_key + '_excluded' + if excluded_key in the_dict: + raise GypError(name + ' key ' + excluded_key + + ' must not be present prior ' + ' to applying exclusion/regex filters for ' + list_key) + + excluded_list = [] + + # Go backwards through the list_actions list so that as items are deleted, + # the indices of items that haven't been seen yet don't shift. That means + # that things need to be prepended to excluded_list to maintain them in the + # same order that they existed in the_list. + for index in xrange(len(list_actions) - 1, -1, -1): + if list_actions[index] == 0: + # Dump anything with action 0 (exclude). Keep anything with action 1 + # (include) or -1 (no include or exclude seen for the item). + excluded_list.insert(0, the_list[index]) + del the_list[index] + + # If anything was excluded, put the excluded list into the_dict at + # excluded_key. + if len(excluded_list) > 0: + the_dict[excluded_key] = excluded_list + + # Now recurse into subdicts and lists that may contain dicts. + for key, value in the_dict.iteritems(): + if type(value) is dict: + ProcessListFiltersInDict(key, value) + elif type(value) is list: + ProcessListFiltersInList(key, value) + + +def ProcessListFiltersInList(name, the_list): + for item in the_list: + if type(item) is dict: + ProcessListFiltersInDict(name, item) + elif type(item) is list: + ProcessListFiltersInList(name, item) + + +def ValidateTargetType(target, target_dict): + """Ensures the 'type' field on the target is one of the known types. + + Arguments: + target: string, name of target. + target_dict: dict, target spec. + + Raises an exception on error. + """ + VALID_TARGET_TYPES = ('executable', 'loadable_module', + 'static_library', 'shared_library', + 'mac_kernel_extension', 'none') + target_type = target_dict.get('type', None) + if target_type not in VALID_TARGET_TYPES: + raise GypError("Target %s has an invalid target type '%s'. " + "Must be one of %s." % + (target, target_type, '/'.join(VALID_TARGET_TYPES))) + if (target_dict.get('standalone_static_library', 0) and + not target_type == 'static_library'): + raise GypError('Target %s has type %s but standalone_static_library flag is' + ' only valid for static_library type.' % (target, + target_type)) + + +def ValidateSourcesInTarget(target, target_dict, build_file, + duplicate_basename_check): + if not duplicate_basename_check: + return + if target_dict.get('type', None) != 'static_library': + return + sources = target_dict.get('sources', []) + basenames = {} + for source in sources: + name, ext = os.path.splitext(source) + is_compiled_file = ext in [ + '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S'] + if not is_compiled_file: + continue + basename = os.path.basename(name) # Don't include extension. + basenames.setdefault(basename, []).append(source) + + error = '' + for basename, files in basenames.iteritems(): + if len(files) > 1: + error += ' %s: %s\n' % (basename, ' '.join(files)) + + if error: + print('static library %s has several files with the same basename:\n' % + target + error + 'libtool on Mac cannot handle that. Use ' + '--no-duplicate-basename-check to disable this validation.') + raise GypError('Duplicate basenames in sources section, see list above') + + +def ValidateRulesInTarget(target, target_dict, extra_sources_for_rules): + """Ensures that the rules sections in target_dict are valid and consistent, + and determines which sources they apply to. + + Arguments: + target: string, name of target. + target_dict: dict, target spec containing "rules" and "sources" lists. + extra_sources_for_rules: a list of keys to scan for rule matches in + addition to 'sources'. + """ + + # Dicts to map between values found in rules' 'rule_name' and 'extension' + # keys and the rule dicts themselves. + rule_names = {} + rule_extensions = {} + + rules = target_dict.get('rules', []) + for rule in rules: + # Make sure that there's no conflict among rule names and extensions. + rule_name = rule['rule_name'] + if rule_name in rule_names: + raise GypError('rule %s exists in duplicate, target %s' % + (rule_name, target)) + rule_names[rule_name] = rule + + rule_extension = rule['extension'] + if rule_extension.startswith('.'): + rule_extension = rule_extension[1:] + if rule_extension in rule_extensions: + raise GypError(('extension %s associated with multiple rules, ' + + 'target %s rules %s and %s') % + (rule_extension, target, + rule_extensions[rule_extension]['rule_name'], + rule_name)) + rule_extensions[rule_extension] = rule + + # Make sure rule_sources isn't already there. It's going to be + # created below if needed. + if 'rule_sources' in rule: + raise GypError( + 'rule_sources must not exist in input, target %s rule %s' % + (target, rule_name)) + + rule_sources = [] + source_keys = ['sources'] + source_keys.extend(extra_sources_for_rules) + for source_key in source_keys: + for source in target_dict.get(source_key, []): + (source_root, source_extension) = os.path.splitext(source) + if source_extension.startswith('.'): + source_extension = source_extension[1:] + if source_extension == rule_extension: + rule_sources.append(source) + + if len(rule_sources) > 0: + rule['rule_sources'] = rule_sources + + +def ValidateRunAsInTarget(target, target_dict, build_file): + target_name = target_dict.get('target_name') + run_as = target_dict.get('run_as') + if not run_as: + return + if type(run_as) is not dict: + raise GypError("The 'run_as' in target %s from file %s should be a " + "dictionary." % + (target_name, build_file)) + action = run_as.get('action') + if not action: + raise GypError("The 'run_as' in target %s from file %s must have an " + "'action' section." % + (target_name, build_file)) + if type(action) is not list: + raise GypError("The 'action' for 'run_as' in target %s from file %s " + "must be a list." % + (target_name, build_file)) + working_directory = run_as.get('working_directory') + if working_directory and type(working_directory) is not str: + raise GypError("The 'working_directory' for 'run_as' in target %s " + "in file %s should be a string." % + (target_name, build_file)) + environment = run_as.get('environment') + if environment and type(environment) is not dict: + raise GypError("The 'environment' for 'run_as' in target %s " + "in file %s should be a dictionary." % + (target_name, build_file)) + + +def ValidateActionsInTarget(target, target_dict, build_file): + '''Validates the inputs to the actions in a target.''' + target_name = target_dict.get('target_name') + actions = target_dict.get('actions', []) + for action in actions: + action_name = action.get('action_name') + if not action_name: + raise GypError("Anonymous action in target %s. " + "An action must have an 'action_name' field." % + target_name) + inputs = action.get('inputs', None) + if inputs is None: + raise GypError('Action in target %s has no inputs.' % target_name) + action_command = action.get('action') + if action_command and not action_command[0]: + raise GypError("Empty action as command in target %s." % target_name) + + +def TurnIntIntoStrInDict(the_dict): + """Given dict the_dict, recursively converts all integers into strings. + """ + # Use items instead of iteritems because there's no need to try to look at + # reinserted keys and their associated values. + for k, v in the_dict.items(): + if type(v) is int: + v = str(v) + the_dict[k] = v + elif type(v) is dict: + TurnIntIntoStrInDict(v) + elif type(v) is list: + TurnIntIntoStrInList(v) + + if type(k) is int: + del the_dict[k] + the_dict[str(k)] = v + + +def TurnIntIntoStrInList(the_list): + """Given list the_list, recursively converts all integers into strings. + """ + for index in xrange(0, len(the_list)): + item = the_list[index] + if type(item) is int: + the_list[index] = str(item) + elif type(item) is dict: + TurnIntIntoStrInDict(item) + elif type(item) is list: + TurnIntIntoStrInList(item) + + +def PruneUnwantedTargets(targets, flat_list, dependency_nodes, root_targets, + data): + """Return only the targets that are deep dependencies of |root_targets|.""" + qualified_root_targets = [] + for target in root_targets: + target = target.strip() + qualified_targets = gyp.common.FindQualifiedTargets(target, flat_list) + if not qualified_targets: + raise GypError("Could not find target %s" % target) + qualified_root_targets.extend(qualified_targets) + + wanted_targets = {} + for target in qualified_root_targets: + wanted_targets[target] = targets[target] + for dependency in dependency_nodes[target].DeepDependencies(): + wanted_targets[dependency] = targets[dependency] + + wanted_flat_list = [t for t in flat_list if t in wanted_targets] + + # Prune unwanted targets from each build_file's data dict. + for build_file in data['target_build_files']: + if not 'targets' in data[build_file]: + continue + new_targets = [] + for target in data[build_file]['targets']: + qualified_name = gyp.common.QualifiedTarget(build_file, + target['target_name'], + target['toolset']) + if qualified_name in wanted_targets: + new_targets.append(target) + data[build_file]['targets'] = new_targets + + return wanted_targets, wanted_flat_list + + +def VerifyNoCollidingTargets(targets): + """Verify that no two targets in the same directory share the same name. + + Arguments: + targets: A list of targets in the form 'path/to/file.gyp:target_name'. + """ + # Keep a dict going from 'subdirectory:target_name' to 'foo.gyp'. + used = {} + for target in targets: + # Separate out 'path/to/file.gyp, 'target_name' from + # 'path/to/file.gyp:target_name'. + path, name = target.rsplit(':', 1) + # Separate out 'path/to', 'file.gyp' from 'path/to/file.gyp'. + subdir, gyp = os.path.split(path) + # Use '.' for the current directory '', so that the error messages make + # more sense. + if not subdir: + subdir = '.' + # Prepare a key like 'path/to:target_name'. + key = subdir + ':' + name + if key in used: + # Complain if this target is already used. + raise GypError('Duplicate target name "%s" in directory "%s" used both ' + 'in "%s" and "%s".' % (name, subdir, gyp, used[key])) + used[key] = gyp + + +def SetGeneratorGlobals(generator_input_info): + # Set up path_sections and non_configuration_keys with the default data plus + # the generator-specific data. + global path_sections + path_sections = set(base_path_sections) + path_sections.update(generator_input_info['path_sections']) + + global non_configuration_keys + non_configuration_keys = base_non_configuration_keys[:] + non_configuration_keys.extend(generator_input_info['non_configuration_keys']) + + global multiple_toolsets + multiple_toolsets = generator_input_info[ + 'generator_supports_multiple_toolsets'] + + global generator_filelist_paths + generator_filelist_paths = generator_input_info['generator_filelist_paths'] + + +def Load(build_files, variables, includes, depth, generator_input_info, check, + circular_check, duplicate_basename_check, parallel, root_targets): + SetGeneratorGlobals(generator_input_info) + # A generator can have other lists (in addition to sources) be processed + # for rules. + extra_sources_for_rules = generator_input_info['extra_sources_for_rules'] + + # Load build files. This loads every target-containing build file into + # the |data| dictionary such that the keys to |data| are build file names, + # and the values are the entire build file contents after "early" or "pre" + # processing has been done and includes have been resolved. + # NOTE: data contains both "target" files (.gyp) and "includes" (.gypi), as + # well as meta-data (e.g. 'included_files' key). 'target_build_files' keeps + # track of the keys corresponding to "target" files. + data = {'target_build_files': set()} + # Normalize paths everywhere. This is important because paths will be + # used as keys to the data dict and for references between input files. + build_files = set(map(os.path.normpath, build_files)) + if parallel: + LoadTargetBuildFilesParallel(build_files, data, variables, includes, depth, + check, generator_input_info) + else: + aux_data = {} + for build_file in build_files: + try: + LoadTargetBuildFile(build_file, data, aux_data, + variables, includes, depth, check, True) + except Exception, e: + gyp.common.ExceptionAppend(e, 'while trying to load %s' % build_file) + raise + + # Build a dict to access each target's subdict by qualified name. + targets = BuildTargetsDict(data) + + # Fully qualify all dependency links. + QualifyDependencies(targets) + + # Remove self-dependencies from targets that have 'prune_self_dependencies' + # set to 1. + RemoveSelfDependencies(targets) + + # Expand dependencies specified as build_file:*. + ExpandWildcardDependencies(targets, data) + + # Remove all dependencies marked as 'link_dependency' from the targets of + # type 'none'. + RemoveLinkDependenciesFromNoneTargets(targets) + + # Apply exclude (!) and regex (/) list filters only for dependency_sections. + for target_name, target_dict in targets.iteritems(): + tmp_dict = {} + for key_base in dependency_sections: + for op in ('', '!', '/'): + key = key_base + op + if key in target_dict: + tmp_dict[key] = target_dict[key] + del target_dict[key] + ProcessListFiltersInDict(target_name, tmp_dict) + # Write the results back to |target_dict|. + for key in tmp_dict: + target_dict[key] = tmp_dict[key] + + # Make sure every dependency appears at most once. + RemoveDuplicateDependencies(targets) + + if circular_check: + # Make sure that any targets in a.gyp don't contain dependencies in other + # .gyp files that further depend on a.gyp. + VerifyNoGYPFileCircularDependencies(targets) + + [dependency_nodes, flat_list] = BuildDependencyList(targets) + + if root_targets: + # Remove, from |targets| and |flat_list|, the targets that are not deep + # dependencies of the targets specified in |root_targets|. + targets, flat_list = PruneUnwantedTargets( + targets, flat_list, dependency_nodes, root_targets, data) + + # Check that no two targets in the same directory have the same name. + VerifyNoCollidingTargets(flat_list) + + # Handle dependent settings of various types. + for settings_type in ['all_dependent_settings', + 'direct_dependent_settings', + 'link_settings']: + DoDependentSettings(settings_type, flat_list, targets, dependency_nodes) + + # Take out the dependent settings now that they've been published to all + # of the targets that require them. + for target in flat_list: + if settings_type in targets[target]: + del targets[target][settings_type] + + # Make sure static libraries don't declare dependencies on other static + # libraries, but that linkables depend on all unlinked static libraries + # that they need so that their link steps will be correct. + gii = generator_input_info + if gii['generator_wants_static_library_dependencies_adjusted']: + AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, + gii['generator_wants_sorted_dependencies']) + + # Apply "post"/"late"/"target" variable expansions and condition evaluations. + for target in flat_list: + target_dict = targets[target] + build_file = gyp.common.BuildFile(target) + ProcessVariablesAndConditionsInDict( + target_dict, PHASE_LATE, variables, build_file) + + # Move everything that can go into a "configurations" section into one. + for target in flat_list: + target_dict = targets[target] + SetUpConfigurations(target, target_dict) + + # Apply exclude (!) and regex (/) list filters. + for target in flat_list: + target_dict = targets[target] + ProcessListFiltersInDict(target, target_dict) + + # Apply "latelate" variable expansions and condition evaluations. + for target in flat_list: + target_dict = targets[target] + build_file = gyp.common.BuildFile(target) + ProcessVariablesAndConditionsInDict( + target_dict, PHASE_LATELATE, variables, build_file) + + # Make sure that the rules make sense, and build up rule_sources lists as + # needed. Not all generators will need to use the rule_sources lists, but + # some may, and it seems best to build the list in a common spot. + # Also validate actions and run_as elements in targets. + for target in flat_list: + target_dict = targets[target] + build_file = gyp.common.BuildFile(target) + ValidateTargetType(target, target_dict) + ValidateSourcesInTarget(target, target_dict, build_file, + duplicate_basename_check) + ValidateRulesInTarget(target, target_dict, extra_sources_for_rules) + ValidateRunAsInTarget(target, target_dict, build_file) + ValidateActionsInTarget(target, target_dict, build_file) + + # Generators might not expect ints. Turn them into strs. + TurnIntIntoStrInDict(data) + + # TODO(mark): Return |data| for now because the generator needs a list of + # build files that came in. In the future, maybe it should just accept + # a list, and not the whole data dict. + return [flat_list, targets, data] diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input_test.py new file mode 100755 index 0000000000000..4234fbb8302eb --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input_test.py @@ -0,0 +1,90 @@ +#!/usr/bin/env python + +# Copyright 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. + +"""Unit tests for the input.py file.""" + +import gyp.input +import unittest +import sys + + +class TestFindCycles(unittest.TestCase): + def setUp(self): + self.nodes = {} + for x in ('a', 'b', 'c', 'd', 'e'): + self.nodes[x] = gyp.input.DependencyGraphNode(x) + + def _create_dependency(self, dependent, dependency): + dependent.dependencies.append(dependency) + dependency.dependents.append(dependent) + + def test_no_cycle_empty_graph(self): + for label, node in self.nodes.iteritems(): + self.assertEquals([], node.FindCycles()) + + def test_no_cycle_line(self): + self._create_dependency(self.nodes['a'], self.nodes['b']) + self._create_dependency(self.nodes['b'], self.nodes['c']) + self._create_dependency(self.nodes['c'], self.nodes['d']) + + for label, node in self.nodes.iteritems(): + self.assertEquals([], node.FindCycles()) + + def test_no_cycle_dag(self): + self._create_dependency(self.nodes['a'], self.nodes['b']) + self._create_dependency(self.nodes['a'], self.nodes['c']) + self._create_dependency(self.nodes['b'], self.nodes['c']) + + for label, node in self.nodes.iteritems(): + self.assertEquals([], node.FindCycles()) + + def test_cycle_self_reference(self): + self._create_dependency(self.nodes['a'], self.nodes['a']) + + self.assertEquals([[self.nodes['a'], self.nodes['a']]], + self.nodes['a'].FindCycles()) + + def test_cycle_two_nodes(self): + self._create_dependency(self.nodes['a'], self.nodes['b']) + self._create_dependency(self.nodes['b'], self.nodes['a']) + + self.assertEquals([[self.nodes['a'], self.nodes['b'], self.nodes['a']]], + self.nodes['a'].FindCycles()) + self.assertEquals([[self.nodes['b'], self.nodes['a'], self.nodes['b']]], + self.nodes['b'].FindCycles()) + + def test_two_cycles(self): + self._create_dependency(self.nodes['a'], self.nodes['b']) + self._create_dependency(self.nodes['b'], self.nodes['a']) + + self._create_dependency(self.nodes['b'], self.nodes['c']) + self._create_dependency(self.nodes['c'], self.nodes['b']) + + cycles = self.nodes['a'].FindCycles() + self.assertTrue( + [self.nodes['a'], self.nodes['b'], self.nodes['a']] in cycles) + self.assertTrue( + [self.nodes['b'], self.nodes['c'], self.nodes['b']] in cycles) + self.assertEquals(2, len(cycles)) + + def test_big_cycle(self): + self._create_dependency(self.nodes['a'], self.nodes['b']) + self._create_dependency(self.nodes['b'], self.nodes['c']) + self._create_dependency(self.nodes['c'], self.nodes['d']) + self._create_dependency(self.nodes['d'], self.nodes['e']) + self._create_dependency(self.nodes['e'], self.nodes['a']) + + self.assertEquals([[self.nodes['a'], + self.nodes['b'], + self.nodes['c'], + self.nodes['d'], + self.nodes['e'], + self.nodes['a']]], + self.nodes['a'].FindCycles()) + + +if __name__ == '__main__': + unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py new file mode 100755 index 0000000000000..eeeaceb0c7aa2 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py @@ -0,0 +1,610 @@ +#!/usr/bin/env python +# Copyright (c) 2012 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. + +"""Utility functions to perform Xcode-style build steps. + +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 +import re +import shutil +import string +import subprocess +import sys +import tempfile + + +def main(args): + executor = MacTool() + exit_code = executor.Dispatch(args) + if exit_code is not None: + sys.exit(exit_code) + + +class MacTool(object): + """This class performs all the Mac tooling steps. The methods can either be + executed directly, or dispatched from an argument list.""" + + def Dispatch(self, args): + """Dispatches a string command to a method.""" + if len(args) < 1: + raise Exception("Not enough arguments") + + method = "Exec%s" % self._CommandifyName(args[0]) + return getattr(self, method)(*args[1:]) + + def _CommandifyName(self, name_string): + """Transforms a tool name like copy-info-plist to CopyInfoPlist""" + return name_string.title().replace('-', '') + + def ExecCopyBundleResource(self, source, dest, convert_to_binary): + """Copies a resource file to the bundle/Resources directory, performing any + necessary compilation on each resource.""" + extension = os.path.splitext(source)[1].lower() + if os.path.isdir(source): + # Copy tree. + # TODO(thakis): This copies file attributes like mtime, while the + # single-file branch below doesn't. This should probably be changed to + # be consistent with the single-file branch. + if os.path.exists(dest): + shutil.rmtree(dest) + shutil.copytree(source, dest) + elif extension == '.xib': + return self._CopyXIBFile(source, dest) + elif extension == '.storyboard': + return self._CopyXIBFile(source, dest) + elif extension == '.strings': + self._CopyStringsFile(source, dest, convert_to_binary) + else: + shutil.copy(source, dest) + + def _CopyXIBFile(self, source, dest): + """Compiles a XIB file with ibtool into a binary plist in the bundle.""" + + # ibtool sometimes crashes with relative paths. See crbug.com/314728. + base = os.path.dirname(os.path.realpath(__file__)) + if os.path.relpath(source): + source = os.path.join(base, source) + if os.path.relpath(dest): + dest = os.path.join(base, dest) + + args = ['xcrun', 'ibtool', '--errors', '--warnings', '--notices', + '--output-format', 'human-readable-text', '--compile', dest, source] + ibtool_section_re = re.compile(r'/\*.*\*/') + ibtool_re = re.compile(r'.*note:.*is clipping its content') + ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE) + current_section_header = None + for line in ibtoolout.stdout: + if ibtool_section_re.match(line): + current_section_header = line + elif not ibtool_re.match(line): + if current_section_header: + sys.stdout.write(current_section_header) + current_section_header = None + sys.stdout.write(line) + return ibtoolout.returncode + + def _ConvertToBinary(self, dest): + subprocess.check_call([ + 'xcrun', 'plutil', '-convert', 'binary1', '-o', dest, dest]) + + def _CopyStringsFile(self, source, dest, convert_to_binary): + """Copies a .strings file using iconv to reconvert the input into UTF-16.""" + input_code = self._DetectInputEncoding(source) or "UTF-8" + + # Xcode's CpyCopyStringsFile / builtin-copyStrings seems to call + # CFPropertyListCreateFromXMLData() behind the scenes; at least it prints + # CFPropertyListCreateFromXMLData(): Old-style plist parser: missing + # semicolon in dictionary. + # on invalid files. Do the same kind of validation. + import CoreFoundation + s = open(source, 'rb').read() + d = CoreFoundation.CFDataCreate(None, s, len(s)) + _, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None) + if error: + return + + fp = open(dest, 'wb') + fp.write(s.decode(input_code).encode('UTF-16')) + fp.close() + + if convert_to_binary == 'True': + self._ConvertToBinary(dest) + + def _DetectInputEncoding(self, file_name): + """Reads the first few bytes from file_name and tries to guess the text + encoding. Returns None as a guess if it can't detect it.""" + fp = open(file_name, 'rb') + try: + header = fp.read(3) + except e: + fp.close() + return None + fp.close() + if header.startswith("\xFE\xFF"): + return "UTF-16" + elif header.startswith("\xFF\xFE"): + return "UTF-16" + elif header.startswith("\xEF\xBB\xBF"): + return "UTF-8" + else: + return None + + def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys): + """Copies the |source| Info.plist to the destination directory |dest|.""" + # Read the source Info.plist into memory. + fd = open(source, 'r') + lines = fd.read() + fd.close() + + # Insert synthesized key/value pairs (e.g. BuildMachineOSBuild). + plist = plistlib.readPlistFromString(lines) + if keys: + plist = dict(plist.items() + json.loads(keys[0]).items()) + lines = plistlib.writePlistToString(plist) + + # Go through all the environment variables and replace them as variables in + # the file. + IDENT_RE = re.compile(r'[/\s]') + for key in os.environ: + if key.startswith('_'): + continue + evar = '${%s}' % key + evalue = os.environ[key] + lines = string.replace(lines, evar, evalue) + + # Xcode supports various suffices on environment variables, which are + # all undocumented. :rfc1034identifier is used in the standard project + # template these days, and :identifier was used earlier. They are used to + # convert non-url characters into things that look like valid urls -- + # except that the replacement character for :identifier, '_' isn't valid + # in a URL either -- oops, hence :rfc1034identifier was born. + evar = '${%s:identifier}' % key + evalue = IDENT_RE.sub('_', os.environ[key]) + lines = string.replace(lines, evar, evalue) + + evar = '${%s:rfc1034identifier}' % key + evalue = IDENT_RE.sub('-', os.environ[key]) + lines = string.replace(lines, evar, evalue) + + # Remove any keys with values that haven't been replaced. + lines = lines.split('\n') + for i in range(len(lines)): + if lines[i].strip().startswith("${"): + lines[i] = None + lines[i - 1] = None + lines = '\n'.join(filter(lambda x: x is not None, lines)) + + # Write out the file with variables replaced. + fd = open(dest, 'w') + fd.write(lines) + fd.close() + + # Now write out PkgInfo file now that the Info.plist file has been + # "compiled". + self._WritePkgInfo(dest) + + if convert_to_binary == 'True': + self._ConvertToBinary(dest) + + def _WritePkgInfo(self, info_plist): + """This writes the PkgInfo file from the data stored in Info.plist.""" + plist = plistlib.readPlist(info_plist) + if not plist: + return + + # Only create PkgInfo for executable types. + package_type = plist['CFBundlePackageType'] + if package_type != 'APPL': + return + + # The format of PkgInfo is eight characters, representing the bundle type + # and bundle signature, each four characters. If that is missing, four + # '?' characters are used instead. + signature_code = plist.get('CFBundleSignature', '????') + if len(signature_code) != 4: # Wrong length resets everything, too. + signature_code = '?' * 4 + + dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo') + fp = open(dest, 'w') + fp.write('%s%s' % (package_type, signature_code)) + fp.close() + + def ExecFlock(self, lockfile, *cmd_list): + """Emulates the most basic behavior of Linux's flock(1).""" + # Rely on exception handling to report errors. + fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666) + fcntl.flock(fd, fcntl.LOCK_EX) + return subprocess.call(cmd_list) + + def ExecFilterLibtool(self, *cmd_list): + """Calls libtool and filters out '/path/to/libtool: file: foo.o has no + symbols'.""" + libtool_re = re.compile(r'^.*libtool: file: .* has no symbols$') + libtool_re5 = re.compile( + r'^.*libtool: warning for library: ' + + r'.* the table of contents is empty ' + + r'\(no object file members in the library define global symbols\)$') + env = os.environ.copy() + # Ref: + # http://www.opensource.apple.com/source/cctools/cctools-809/misc/libtool.c + # The problem with this flag is that it resets the file mtime on the file to + # epoch=0, e.g. 1970-1-1 or 1969-12-31 depending on timezone. + env['ZERO_AR_DATE'] = '1' + libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE, env=env) + _, err = libtoolout.communicate() + for line in err.splitlines(): + if not libtool_re.match(line) and not libtool_re5.match(line): + print >>sys.stderr, line + # Unconditionally touch the output .a file on the command line if present + # and the command succeeded. A bit hacky. + if not libtoolout.returncode: + for i in range(len(cmd_list) - 1): + if cmd_list[i] == "-o" and cmd_list[i+1].endswith('.a'): + os.utime(cmd_list[i+1], None) + break + return libtoolout.returncode + + def ExecPackageFramework(self, framework, version): + """Takes a path to Something.framework and the Current version of that and + sets up all the symlinks.""" + # Find the name of the binary based on the part before the ".framework". + binary = os.path.basename(framework).split('.')[0] + + CURRENT = 'Current' + RESOURCES = 'Resources' + VERSIONS = 'Versions' + + if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)): + # Binary-less frameworks don't seem to contain symlinks (see e.g. + # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle). + return + + # Move into the framework directory to set the symlinks correctly. + pwd = os.getcwd() + os.chdir(framework) + + # Set up the Current version. + self._Relink(version, os.path.join(VERSIONS, CURRENT)) + + # Set up the root symlinks. + self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary) + self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES) + + # Back to where we were before! + os.chdir(pwd) + + def _Relink(self, dest, link): + """Creates a symlink to |dest| named |link|. If |link| already exists, + it is overwritten.""" + if os.path.lexists(link): + os.remove(link) + os.symlink(dest, link) + + def ExecCompileXcassets(self, keys, *inputs): + """Compiles multiple .xcassets files into a single .car file. + + This invokes 'actool' to compile all the inputs .xcassets files. The + |keys| arguments is a json-encoded dictionary of extra arguments to + pass to 'actool' when the asset catalogs contains an application icon + or a launch image. + + Note that 'actool' does not create the Assets.car file if the asset + catalogs does not contains imageset. + """ + command_line = [ + 'xcrun', 'actool', '--output-format', 'human-readable-text', + '--compress-pngs', '--notices', '--warnings', '--errors', + ] + is_iphone_target = 'IPHONEOS_DEPLOYMENT_TARGET' in os.environ + if is_iphone_target: + platform = os.environ['CONFIGURATION'].split('-')[-1] + if platform not in ('iphoneos', 'iphonesimulator'): + platform = 'iphonesimulator' + command_line.extend([ + '--platform', platform, '--target-device', 'iphone', + '--target-device', 'ipad', '--minimum-deployment-target', + os.environ['IPHONEOS_DEPLOYMENT_TARGET'], '--compile', + os.path.abspath(os.environ['CONTENTS_FOLDER_PATH']), + ]) + else: + command_line.extend([ + '--platform', 'macosx', '--target-device', 'mac', + '--minimum-deployment-target', os.environ['MACOSX_DEPLOYMENT_TARGET'], + '--compile', + os.path.abspath(os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']), + ]) + if keys: + keys = json.loads(keys) + for key, value in keys.iteritems(): + arg_name = '--' + key + if isinstance(value, bool): + if value: + command_line.append(arg_name) + elif isinstance(value, list): + for v in value: + command_line.append(arg_name) + command_line.append(str(v)) + else: + command_line.append(arg_name) + command_line.append(str(value)) + # Note: actool crashes if inputs path are relative, so use os.path.abspath + # to get absolute path name for inputs. + command_line.extend(map(os.path.abspath, inputs)) + subprocess.check_call(command_line) + + def ExecMergeInfoPlist(self, output, *inputs): + """Merge multiple .plist files into a single .plist file.""" + merged_plist = {} + for path in inputs: + plist = self._LoadPlistMaybeBinary(path) + self._MergePlist(merged_plist, plist) + plistlib.writePlist(merged_plist, output) + + 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 _MergePlist(self, merged_plist, plist): + """Merge |plist| into |merged_plist|.""" + for key, value in plist.iteritems(): + if isinstance(value, dict): + merged_value = merged_plist.get(key, {}) + if isinstance(merged_value, dict): + self._MergePlist(merged_value, value) + merged_plist[key] = merged_value + else: + merged_plist[key] = value + else: + merged_plist[key] = value + + 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 {k: self._ExpandVariables(data[k], substitutions) for k in data} + return data + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py new file mode 100644 index 0000000000000..ca67b122f0b9b --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py @@ -0,0 +1,1087 @@ +# Copyright (c) 2012 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. + +""" +This module helps emulate Visual Studio 2008 behavior on top of other +build systems, primarily ninja. +""" + +import os +import re +import subprocess +import sys + +from gyp.common import OrderedSet +import gyp.MSVSUtil +import gyp.MSVSVersion + + +windows_quoter_regex = re.compile(r'(\\*)"') + + +def QuoteForRspFile(arg): + """Quote a command line argument so that it appears as one argument when + processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for + Windows programs).""" + # See http://goo.gl/cuFbX and http://goo.gl/dhPnp including the comment + # threads. This is actually the quoting rules for CommandLineToArgvW, not + # for the shell, because the shell doesn't do anything in Windows. This + # works more or less because most programs (including the compiler, etc.) + # use that function to handle command line arguments. + + # For a literal quote, CommandLineToArgvW requires 2n+1 backslashes + # preceding it, and results in n backslashes + the quote. So we substitute + # in 2* what we match, +1 more, plus the quote. + arg = windows_quoter_regex.sub(lambda mo: 2 * mo.group(1) + '\\"', arg) + + # %'s also need to be doubled otherwise they're interpreted as batch + # positional arguments. Also make sure to escape the % so that they're + # passed literally through escaping so they can be singled to just the + # original %. Otherwise, trying to pass the literal representation that + # looks like an environment variable to the shell (e.g. %PATH%) would fail. + arg = arg.replace('%', '%%') + + # These commands are used in rsp files, so no escaping for the shell (via ^) + # is necessary. + + # Finally, wrap the whole thing in quotes so that the above quote rule + # applies and whitespace isn't a word break. + return '"' + arg + '"' + + +def EncodeRspFileList(args): + """Process a list of arguments using QuoteCmdExeArgument.""" + # Note that the first argument is assumed to be the command. Don't add + # quotes around it because then built-ins like 'echo', etc. won't work. + # Take care to normpath only the path in the case of 'call ../x.bat' because + # otherwise the whole thing is incorrectly interpreted as a path and not + # normalized correctly. + if not args: return '' + if args[0].startswith('call '): + call, program = args[0].split(' ', 1) + program = call + ' ' + os.path.normpath(program) + else: + program = os.path.normpath(args[0]) + return program + ' ' + ' '.join(QuoteForRspFile(arg) for arg in args[1:]) + + +def _GenericRetrieve(root, default, path): + """Given a list of dictionary keys |path| and a tree of dicts |root|, find + value at path, or return |default| if any of the path doesn't exist.""" + if not root: + return default + if not path: + return root + return _GenericRetrieve(root.get(path[0]), default, path[1:]) + + +def _AddPrefix(element, prefix): + """Add |prefix| to |element| or each subelement if element is iterable.""" + if element is None: + return element + # Note, not Iterable because we don't want to handle strings like that. + if isinstance(element, list) or isinstance(element, tuple): + return [prefix + e for e in element] + else: + return prefix + element + + +def _DoRemapping(element, map): + """If |element| then remap it through |map|. If |element| is iterable then + each item will be remapped. Any elements not found will be removed.""" + if map is not None and element is not None: + if not callable(map): + map = map.get # Assume it's a dict, otherwise a callable to do the remap. + if isinstance(element, list) or isinstance(element, tuple): + element = filter(None, [map(elem) for elem in element]) + else: + element = map(element) + return element + + +def _AppendOrReturn(append, element): + """If |append| is None, simply return |element|. If |append| is not None, + then add |element| to it, adding each item in |element| if it's a list or + tuple.""" + if append is not None and element is not None: + if isinstance(element, list) or isinstance(element, tuple): + append.extend(element) + else: + append.append(element) + else: + return element + + +def _FindDirectXInstallation(): + """Try to find an installation location for the DirectX SDK. Check for the + standard environment variable, and if that doesn't exist, try to find + via the registry. May return None if not found in either location.""" + # Return previously calculated value, if there is one + if hasattr(_FindDirectXInstallation, 'dxsdk_dir'): + return _FindDirectXInstallation.dxsdk_dir + + dxsdk_dir = os.environ.get('DXSDK_DIR') + if not dxsdk_dir: + # Setup params to pass to and attempt to launch reg.exe. + cmd = ['reg.exe', 'query', r'HKLM\Software\Microsoft\DirectX', '/s'] + p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + for line in p.communicate()[0].splitlines(): + if 'InstallPath' in line: + dxsdk_dir = line.split(' ')[3] + "\\" + + # Cache return value + _FindDirectXInstallation.dxsdk_dir = dxsdk_dir + return dxsdk_dir + + +def GetGlobalVSMacroEnv(vs_version): + """Get a dict of variables mapping internal VS macro names to their gyp + equivalents. Returns all variables that are independent of the target.""" + env = {} + # '$(VSInstallDir)' and '$(VCInstallDir)' are available when and only when + # Visual Studio is actually installed. + if vs_version.Path(): + env['$(VSInstallDir)'] = vs_version.Path() + env['$(VCInstallDir)'] = os.path.join(vs_version.Path(), 'VC') + '\\' + # Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be + # set. This happens when the SDK is sync'd via src-internal, rather than + # by typical end-user installation of the SDK. If it's not set, we don't + # want to leave the unexpanded variable in the path, so simply strip it. + dxsdk_dir = _FindDirectXInstallation() + env['$(DXSDK_DIR)'] = dxsdk_dir if dxsdk_dir else '' + # Try to find an installation location for the Windows DDK by checking + # the WDK_DIR environment variable, may be None. + env['$(WDK_DIR)'] = os.environ.get('WDK_DIR', '') + return env + +def ExtractSharedMSVSSystemIncludes(configs, generator_flags): + """Finds msvs_system_include_dirs that are common to all targets, removes + them from all targets, and returns an OrderedSet containing them.""" + all_system_includes = OrderedSet( + configs[0].get('msvs_system_include_dirs', [])) + for config in configs[1:]: + system_includes = config.get('msvs_system_include_dirs', []) + all_system_includes = all_system_includes & OrderedSet(system_includes) + if not all_system_includes: + return None + # Expand macros in all_system_includes. + env = GetGlobalVSMacroEnv(GetVSVersion(generator_flags)) + expanded_system_includes = OrderedSet([ExpandMacros(include, env) + for include in all_system_includes]) + if any(['$' in include for include in expanded_system_includes]): + # Some path relies on target-specific variables, bail. + return None + + # Remove system includes shared by all targets from the targets. + for config in configs: + includes = config.get('msvs_system_include_dirs', []) + if includes: # Don't insert a msvs_system_include_dirs key if not needed. + # This must check the unexpanded includes list: + new_includes = [i for i in includes if i not in all_system_includes] + config['msvs_system_include_dirs'] = new_includes + return expanded_system_includes + + +class MsvsSettings(object): + """A class that understands the gyp 'msvs_...' values (especially the + msvs_settings field). They largely correpond to the VS2008 IDE DOM. This + class helps map those settings to command line options.""" + + def __init__(self, spec, generator_flags): + self.spec = spec + self.vs_version = GetVSVersion(generator_flags) + + supported_fields = [ + ('msvs_configuration_attributes', dict), + ('msvs_settings', dict), + ('msvs_system_include_dirs', list), + ('msvs_disabled_warnings', list), + ('msvs_precompiled_header', str), + ('msvs_precompiled_source', str), + ('msvs_configuration_platform', str), + ('msvs_target_platform', str), + ] + configs = spec['configurations'] + for field, default in supported_fields: + setattr(self, field, {}) + for configname, config in configs.iteritems(): + getattr(self, field)[configname] = config.get(field, default()) + + self.msvs_cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.']) + + unsupported_fields = [ + 'msvs_prebuild', + 'msvs_postbuild', + ] + unsupported = [] + for field in unsupported_fields: + for config in configs.values(): + if field in config: + unsupported += ["%s not supported (target %s)." % + (field, spec['target_name'])] + if unsupported: + raise Exception('\n'.join(unsupported)) + + def GetExtension(self): + """Returns the extension for the target, with no leading dot. + + Uses 'product_extension' if specified, otherwise uses MSVS defaults based on + the target type. + """ + ext = self.spec.get('product_extension', None) + if ext: + return ext + return gyp.MSVSUtil.TARGET_TYPE_EXT.get(self.spec['type'], '') + + def GetVSMacroEnv(self, base_to_build=None, config=None): + """Get a dict of variables mapping internal VS macro names to their gyp + equivalents.""" + target_platform = 'Win32' if self.GetArch(config) == 'x86' else 'x64' + target_name = self.spec.get('product_prefix', '') + \ + self.spec.get('product_name', self.spec['target_name']) + target_dir = base_to_build + '\\' if base_to_build else '' + target_ext = '.' + self.GetExtension() + target_file_name = target_name + target_ext + + replacements = { + '$(InputName)': '${root}', + '$(InputPath)': '${source}', + '$(IntDir)': '$!INTERMEDIATE_DIR', + '$(OutDir)\\': target_dir, + '$(PlatformName)': target_platform, + '$(ProjectDir)\\': '', + '$(ProjectName)': self.spec['target_name'], + '$(TargetDir)\\': target_dir, + '$(TargetExt)': target_ext, + '$(TargetFileName)': target_file_name, + '$(TargetName)': target_name, + '$(TargetPath)': os.path.join(target_dir, target_file_name), + } + replacements.update(GetGlobalVSMacroEnv(self.vs_version)) + return replacements + + def ConvertVSMacros(self, s, base_to_build=None, config=None): + """Convert from VS macro names to something equivalent.""" + env = self.GetVSMacroEnv(base_to_build, config=config) + return ExpandMacros(s, env) + + def AdjustLibraries(self, libraries): + """Strip -l from library if it's specified with that.""" + libs = [lib[2:] if lib.startswith('-l') else lib for lib in libraries] + return [lib + '.lib' if not lib.endswith('.lib') else lib for lib in libs] + + def _GetAndMunge(self, field, path, default, prefix, append, map): + """Retrieve a value from |field| at |path| or return |default|. If + |append| is specified, and the item is found, it will be appended to that + object instead of returned. If |map| is specified, results will be + remapped through |map| before being returned or appended.""" + result = _GenericRetrieve(field, default, path) + result = _DoRemapping(result, map) + result = _AddPrefix(result, prefix) + return _AppendOrReturn(append, result) + + class _GetWrapper(object): + def __init__(self, parent, field, base_path, append=None): + self.parent = parent + self.field = field + self.base_path = [base_path] + self.append = append + def __call__(self, name, map=None, prefix='', default=None): + return self.parent._GetAndMunge(self.field, self.base_path + [name], + default=default, prefix=prefix, append=self.append, map=map) + + def GetArch(self, config): + """Get architecture based on msvs_configuration_platform and + msvs_target_platform. Returns either 'x86' or 'x64'.""" + configuration_platform = self.msvs_configuration_platform.get(config, '') + platform = self.msvs_target_platform.get(config, '') + if not platform: # If no specific override, use the configuration's. + platform = configuration_platform + # Map from platform to architecture. + return {'Win32': 'x86', 'x64': 'x64'}.get(platform, 'x86') + + def _TargetConfig(self, config): + """Returns the target-specific configuration.""" + # There's two levels of architecture/platform specification in VS. The + # first level is globally for the configuration (this is what we consider + # "the" config at the gyp level, which will be something like 'Debug' or + # 'Release_x64'), and a second target-specific configuration, which is an + # override for the global one. |config| is remapped here to take into + # account the local target-specific overrides to the global configuration. + arch = self.GetArch(config) + if arch == 'x64' and not config.endswith('_x64'): + config += '_x64' + if arch == 'x86' and config.endswith('_x64'): + config = config.rsplit('_', 1)[0] + return config + + def _Setting(self, path, config, + default=None, prefix='', append=None, map=None): + """_GetAndMunge for msvs_settings.""" + return self._GetAndMunge( + self.msvs_settings[config], path, default, prefix, append, map) + + def _ConfigAttrib(self, path, config, + default=None, prefix='', append=None, map=None): + """_GetAndMunge for msvs_configuration_attributes.""" + return self._GetAndMunge( + self.msvs_configuration_attributes[config], + path, default, prefix, append, map) + + def AdjustIncludeDirs(self, include_dirs, config): + """Updates include_dirs to expand VS specific paths, and adds the system + include dirs used for platform SDK and similar.""" + config = self._TargetConfig(config) + includes = include_dirs + self.msvs_system_include_dirs[config] + includes.extend(self._Setting( + ('VCCLCompilerTool', 'AdditionalIncludeDirectories'), config, default=[])) + return [self.ConvertVSMacros(p, config=config) for p in includes] + + def AdjustMidlIncludeDirs(self, midl_include_dirs, config): + """Updates midl_include_dirs to expand VS specific paths, and adds the + system include dirs used for platform SDK and similar.""" + config = self._TargetConfig(config) + includes = midl_include_dirs + self.msvs_system_include_dirs[config] + includes.extend(self._Setting( + ('VCMIDLTool', 'AdditionalIncludeDirectories'), config, default=[])) + return [self.ConvertVSMacros(p, config=config) for p in includes] + + def GetComputedDefines(self, config): + """Returns the set of defines that are injected to the defines list based + on other VS settings.""" + config = self._TargetConfig(config) + defines = [] + if self._ConfigAttrib(['CharacterSet'], config) == '1': + defines.extend(('_UNICODE', 'UNICODE')) + if self._ConfigAttrib(['CharacterSet'], config) == '2': + defines.append('_MBCS') + defines.extend(self._Setting( + ('VCCLCompilerTool', 'PreprocessorDefinitions'), config, default=[])) + return defines + + def GetCompilerPdbName(self, config, expand_special): + """Get the pdb file name that should be used for compiler invocations, or + None if there's no explicit name specified.""" + config = self._TargetConfig(config) + pdbname = self._Setting( + ('VCCLCompilerTool', 'ProgramDataBaseFileName'), config) + if pdbname: + pdbname = expand_special(self.ConvertVSMacros(pdbname)) + return pdbname + + def GetMapFileName(self, config, expand_special): + """Gets the explicitly overriden map file name for a target or returns None + if it's not set.""" + config = self._TargetConfig(config) + map_file = self._Setting(('VCLinkerTool', 'MapFileName'), config) + if map_file: + map_file = expand_special(self.ConvertVSMacros(map_file, config=config)) + return map_file + + def GetOutputName(self, config, expand_special): + """Gets the explicitly overridden output name for a target or returns None + if it's not overridden.""" + config = self._TargetConfig(config) + type = self.spec['type'] + root = 'VCLibrarianTool' if type == 'static_library' else 'VCLinkerTool' + # TODO(scottmg): Handle OutputDirectory without OutputFile. + output_file = self._Setting((root, 'OutputFile'), config) + if output_file: + output_file = expand_special(self.ConvertVSMacros( + output_file, config=config)) + return output_file + + 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) + generate_debug_info = self._Setting( + ('VCLinkerTool', 'GenerateDebugInformation'), config) + if generate_debug_info == 'true': + if output_file: + return expand_special(self.ConvertVSMacros(output_file, config=config)) + else: + return default + else: + return None + + def GetNoImportLibrary(self, config): + """If NoImportLibrary: true, ninja will not expect the output to include + an import library.""" + config = self._TargetConfig(config) + noimplib = self._Setting(('NoImportLibrary',), config) + return noimplib == 'true' + + def GetAsmflags(self, config): + """Returns the flags that need to be added to ml invocations.""" + config = self._TargetConfig(config) + asmflags = [] + safeseh = self._Setting(('MASM', 'UseSafeExceptionHandlers'), config) + if safeseh == 'true': + asmflags.append('/safeseh') + return asmflags + + def GetCflags(self, config): + """Returns the flags that need to be added to .c and .cc compilations.""" + config = self._TargetConfig(config) + cflags = [] + cflags.extend(['/wd' + w for w in self.msvs_disabled_warnings[config]]) + cl = self._GetWrapper(self, self.msvs_settings[config], + 'VCCLCompilerTool', append=cflags) + cl('Optimization', + map={'0': 'd', '1': '1', '2': '2', '3': 'x'}, prefix='/O', default='2') + cl('InlineFunctionExpansion', prefix='/Ob') + cl('DisableSpecificWarnings', prefix='/wd') + cl('StringPooling', map={'true': '/GF'}) + cl('EnableFiberSafeOptimizations', map={'true': '/GT'}) + cl('OmitFramePointers', map={'false': '-', 'true': ''}, prefix='/Oy') + cl('EnableIntrinsicFunctions', map={'false': '-', 'true': ''}, prefix='/Oi') + cl('FavorSizeOrSpeed', map={'1': 't', '2': 's'}, prefix='/O') + cl('FloatingPointModel', + map={'0': 'precise', '1': 'strict', '2': 'fast'}, prefix='/fp:', + default='0') + cl('CompileAsManaged', map={'false': '', 'true': '/clr'}) + cl('WholeProgramOptimization', map={'true': '/GL'}) + cl('WarningLevel', prefix='/W') + cl('WarnAsError', map={'true': '/WX'}) + cl('CallingConvention', + map={'0': 'd', '1': 'r', '2': 'z', '3': 'v'}, prefix='/G') + cl('DebugInformationFormat', + map={'1': '7', '3': 'i', '4': 'I'}, prefix='/Z') + cl('RuntimeTypeInfo', map={'true': '/GR', 'false': '/GR-'}) + cl('EnableFunctionLevelLinking', map={'true': '/Gy', 'false': '/Gy-'}) + cl('MinimalRebuild', map={'true': '/Gm'}) + cl('BufferSecurityCheck', map={'true': '/GS', 'false': '/GS-'}) + cl('BasicRuntimeChecks', map={'1': 's', '2': 'u', '3': '1'}, prefix='/RTC') + cl('RuntimeLibrary', + map={'0': 'T', '1': 'Td', '2': 'D', '3': 'Dd'}, prefix='/M') + cl('ExceptionHandling', map={'1': 'sc','2': 'a'}, prefix='/EH') + cl('DefaultCharIsUnsigned', map={'true': '/J'}) + cl('TreatWChar_tAsBuiltInType', + map={'false': '-', 'true': ''}, prefix='/Zc:wchar_t') + cl('EnablePREfast', map={'true': '/analyze'}) + cl('AdditionalOptions', prefix='') + cl('EnableEnhancedInstructionSet', + map={'1': 'SSE', '2': 'SSE2', '3': 'AVX', '4': 'IA32', '5': 'AVX2'}, + prefix='/arch:') + cflags.extend(['/FI' + f for f in self._Setting( + ('VCCLCompilerTool', 'ForcedIncludeFiles'), config, default=[])]) + if self.vs_version.short_name in ('2013', '2013e', '2015'): + # New flag required in 2013 to maintain previous PDB behavior. + cflags.append('/FS') + # ninja handles parallelism by itself, don't have the compiler do it too. + cflags = filter(lambda x: not x.startswith('/MP'), cflags) + return cflags + + def _GetPchFlags(self, config, extension): + """Get the flags to be added to the cflags for precompiled header support. + """ + config = self._TargetConfig(config) + # The PCH is only built once by a particular source file. Usage of PCH must + # only be for the same language (i.e. C vs. C++), so only include the pch + # flags when the language matches. + if self.msvs_precompiled_header[config]: + source_ext = os.path.splitext(self.msvs_precompiled_source[config])[1] + if _LanguageMatchesForPch(source_ext, extension): + pch = os.path.split(self.msvs_precompiled_header[config])[1] + return ['/Yu' + pch, '/FI' + pch, '/Fp${pchprefix}.' + pch + '.pch'] + return [] + + def GetCflagsC(self, config): + """Returns the flags that need to be added to .c compilations.""" + config = self._TargetConfig(config) + return self._GetPchFlags(config, '.c') + + def GetCflagsCC(self, config): + """Returns the flags that need to be added to .cc compilations.""" + config = self._TargetConfig(config) + return ['/TP'] + self._GetPchFlags(config, '.cc') + + def _GetAdditionalLibraryDirectories(self, root, config, gyp_to_build_path): + """Get and normalize the list of paths in AdditionalLibraryDirectories + setting.""" + config = self._TargetConfig(config) + libpaths = self._Setting((root, 'AdditionalLibraryDirectories'), + config, default=[]) + libpaths = [os.path.normpath( + gyp_to_build_path(self.ConvertVSMacros(p, config=config))) + for p in libpaths] + return ['/LIBPATH:"' + p + '"' for p in libpaths] + + def GetLibFlags(self, config, gyp_to_build_path): + """Returns the flags that need to be added to lib commands.""" + config = self._TargetConfig(config) + libflags = [] + lib = self._GetWrapper(self, self.msvs_settings[config], + 'VCLibrarianTool', append=libflags) + libflags.extend(self._GetAdditionalLibraryDirectories( + 'VCLibrarianTool', config, gyp_to_build_path)) + lib('LinkTimeCodeGeneration', map={'true': '/LTCG'}) + lib('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'}, + prefix='/MACHINE:') + lib('AdditionalOptions') + return libflags + + def GetDefFile(self, gyp_to_build_path): + """Returns the .def file from sources, if any. Otherwise returns None.""" + spec = self.spec + if spec['type'] in ('shared_library', 'loadable_module', 'executable'): + def_files = [s for s in spec.get('sources', []) if s.endswith('.def')] + if len(def_files) == 1: + return gyp_to_build_path(def_files[0]) + elif len(def_files) > 1: + raise Exception("Multiple .def files") + return None + + def _GetDefFileAsLdflags(self, ldflags, gyp_to_build_path): + """.def files get implicitly converted to a ModuleDefinitionFile for the + linker in the VS generator. Emulate that behaviour here.""" + def_file = self.GetDefFile(gyp_to_build_path) + 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, 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) + ldflags = [] + ld = self._GetWrapper(self, self.msvs_settings[config], + 'VCLinkerTool', append=ldflags) + self._GetDefFileAsLdflags(ldflags, gyp_to_build_path) + ld('GenerateDebugInformation', map={'true': '/DEBUG'}) + ld('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'}, + prefix='/MACHINE:') + 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, 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='') + + 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:') + + stack_reserve_size = self._Setting( + ('VCLinkerTool', 'StackReserveSize'), config, default='') + if stack_reserve_size: + stack_commit_size = self._Setting( + ('VCLinkerTool', 'StackCommitSize'), config, default='') + if stack_commit_size: + stack_commit_size = ',' + stack_commit_size + ldflags.append('/STACK:%s%s' % (stack_reserve_size, stack_commit_size)) + + 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': '', '2': ':PGINSTRUMENT', '3': ':PGOPTIMIZE', + '4': ':PGUPDATE'}, + prefix='/LTCG') + ld('IgnoreDefaultLibraryNames', prefix='/NODEFAULTLIB:') + ld('ResourceOnlyDLL', map={'true': '/NOENTRY'}) + ld('EntryPointSymbol', prefix='/ENTRY:') + ld('Profile', map={'true': '/PROFILE'}) + ld('LargeAddressAware', + map={'1': ':NO', '2': ''}, prefix='/LARGEADDRESSAWARE') + # TODO(scottmg): This should sort of be somewhere else (not really a flag). + ld('AdditionalDependencies', prefix='') + + if self.GetArch(config) == 'x86': + safeseh_default = 'true' + else: + safeseh_default = None + ld('ImageHasSafeExceptionHandlers', + map={'false': ':NO', 'true': ''}, prefix='/SAFESEH', + default=safeseh_default) + + # If the base address is not specifically controlled, DYNAMICBASE should + # be on by default. + base_flags = filter(lambda x: 'DYNAMICBASE' in x or x == '/FIXED', + ldflags) + if not base_flags: + ldflags.append('/DYNAMICBASE') + + # If the NXCOMPAT flag has not been specified, default to on. Despite the + # documentation that says this only defaults to on when the subsystem is + # Vista or greater (which applies to the linker), the IDE defaults it on + # unless it's explicitly off. + if not filter(lambda x: 'NXCOMPAT' in x, ldflags): + ldflags.append('/NXCOMPAT') + + have_def_file = filter(lambda x: x.startswith('/DEF:'), ldflags) + 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) + 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'], [], [] + + 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 = \ +"" \ +"%s" \ +"" + if enable_uac == 'true': + execution_level = self._Setting(('VCLinkerTool', 'UACExecutionLevel'), + config, default='0') + execution_level_map = { + '0': 'asInvoker', + '1': 'highestAvailable', + '2': 'requireAdministrator' + } + + ui_access = self._Setting(('VCLinkerTool', 'UACUIAccess'), config, + default='false') + + inner = ''' + + + + + + +''' % (execution_level_map[execution_level], ui_access) + else: + 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') + + 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 + generated by the linker.""" + files = self._Setting(('VCManifestTool', 'AdditionalManifestFiles'), config, + default=[]) + if isinstance(files, str): + files = files.split(';') + return [os.path.normpath( + gyp_to_build_path(self.ConvertVSMacros(f, config=config))) + for f in files] + + def IsUseLibraryDependencyInputs(self, config): + """Returns whether the target should be linked via Use Library Dependency + Inputs (using component .objs of a given .lib).""" + config = self._TargetConfig(config) + uldi = self._Setting(('VCLinkerTool', 'UseLibraryDependencyInputs'), config) + return uldi == 'true' + + def IsEmbedManifest(self, config): + """Returns whether manifest should be linked into binary.""" + config = self._TargetConfig(config) + embed = self._Setting(('VCManifestTool', 'EmbedManifest'), config, + default='true') + return embed == 'true' + + def IsLinkIncremental(self, config): + """Returns whether the target should be linked incrementally.""" + config = self._TargetConfig(config) + link_inc = self._Setting(('VCLinkerTool', 'LinkIncremental'), config) + return link_inc != '1' + + def GetRcflags(self, config, gyp_to_ninja_path): + """Returns the flags that need to be added to invocations of the resource + compiler.""" + config = self._TargetConfig(config) + rcflags = [] + rc = self._GetWrapper(self, self.msvs_settings[config], + 'VCResourceCompilerTool', append=rcflags) + rc('AdditionalIncludeDirectories', map=gyp_to_ninja_path, prefix='/I') + rcflags.append('/I' + gyp_to_ninja_path('.')) + rc('PreprocessorDefinitions', prefix='/d') + # /l arg must be in hex without leading '0x' + rc('Culture', prefix='/l', map=lambda x: hex(int(x))[2:]) + return rcflags + + def BuildCygwinBashCommandLine(self, args, path_to_base): + """Build a command line that runs args via cygwin bash. We assume that all + incoming paths are in Windows normpath'd form, so they need to be + converted to posix style for the part of the command line that's passed to + bash. We also have to do some Visual Studio macro emulation here because + various rules use magic VS names for things. Also note that rules that + contain ninja variables cannot be fixed here (for example ${source}), so + the outer generator needs to make sure that the paths that are written out + are in posix style, if the command line will be used here.""" + cygwin_dir = os.path.normpath( + os.path.join(path_to_base, self.msvs_cygwin_dirs[0])) + cd = ('cd %s' % path_to_base).replace('\\', '/') + args = [a.replace('\\', '/').replace('"', '\\"') for a in args] + args = ["'%s'" % a.replace("'", "'\\''") for a in args] + bash_cmd = ' '.join(args) + cmd = ( + 'call "%s\\setup_env.bat" && set CYGWIN=nontsec && ' % cygwin_dir + + 'bash -c "%s ; %s"' % (cd, bash_cmd)) + return cmd + + def IsRuleRunUnderCygwin(self, rule): + """Determine if an action should be run under cygwin. If the variable is + unset, or set to 1 we use cygwin.""" + return int(rule.get('msvs_cygwin_shell', + self.spec.get('msvs_cygwin_shell', 1))) != 0 + + def _HasExplicitRuleForExtension(self, spec, extension): + """Determine if there's an explicit rule for a particular extension.""" + for rule in spec.get('rules', []): + if rule['extension'] == extension: + return True + return False + + def _HasExplicitIdlActions(self, spec): + """Determine if an action should not run midl for .idl files.""" + return any([action.get('explicit_idl_action', 0) + for action in spec.get('actions', [])]) + + def HasExplicitIdlRulesOrActions(self, spec): + """Determine if there's an explicit rule or action for idl files. When + there isn't we need to generate implicit rules to build MIDL .idl files.""" + return (self._HasExplicitRuleForExtension(spec, 'idl') or + self._HasExplicitIdlActions(spec)) + + def HasExplicitAsmRules(self, spec): + """Determine if there's an explicit rule for asm files. When there isn't we + need to generate implicit rules to assemble .asm files.""" + return self._HasExplicitRuleForExtension(spec, 'asm') + + def GetIdlBuildData(self, source, config): + """Determine the implicit outputs for an idl file. Returns output + directory, outputs, and variables and flags that are required.""" + config = self._TargetConfig(config) + midl_get = self._GetWrapper(self, self.msvs_settings[config], 'VCMIDLTool') + def midl(name, default=None): + return self.ConvertVSMacros(midl_get(name, default=default), + config=config) + tlb = midl('TypeLibraryName', default='${root}.tlb') + header = midl('HeaderFileName', default='${root}.h') + dlldata = midl('DLLDataFileName', default='dlldata.c') + iid = midl('InterfaceIdentifierFileName', default='${root}_i.c') + proxy = midl('ProxyFileName', default='${root}_p.c') + # Note that .tlb is not included in the outputs as it is not always + # generated depending on the content of the input idl file. + outdir = midl('OutputDirectory', default='') + output = [header, dlldata, iid, proxy] + variables = [('tlb', tlb), + ('h', header), + ('dlldata', dlldata), + ('iid', iid), + ('proxy', proxy)] + # TODO(scottmg): Are there configuration settings to set these flags? + target_platform = 'win32' if self.GetArch(config) == 'x86' else 'x64' + flags = ['/char', 'signed', '/env', target_platform, '/Oicf'] + return outdir, output, variables, flags + + +def _LanguageMatchesForPch(source_ext, pch_source_ext): + c_exts = ('.c',) + cc_exts = ('.cc', '.cxx', '.cpp') + return ((source_ext in c_exts and pch_source_ext in c_exts) or + (source_ext in cc_exts and pch_source_ext in cc_exts)) + + +class PrecompiledHeader(object): + """Helper to generate dependencies and build rules to handle generation of + precompiled headers. Interface matches the GCH handler in xcode_emulation.py. + """ + def __init__( + self, settings, config, gyp_to_build_path, gyp_to_unique_output, obj_ext): + self.settings = settings + self.config = config + pch_source = self.settings.msvs_precompiled_source[self.config] + self.pch_source = gyp_to_build_path(pch_source) + filename, _ = os.path.splitext(pch_source) + self.output_obj = gyp_to_unique_output(filename + obj_ext).lower() + + def _PchHeader(self): + """Get the header that will appear in an #include line for all source + files.""" + return os.path.split(self.settings.msvs_precompiled_header[self.config])[1] + + def GetObjDependencies(self, sources, objs, arch): + """Given a list of sources files and the corresponding object files, + returns a list of the pch files that should be depended upon. The + additional wrapping in the return value is for interface compatibility + with make.py on Mac, and xcode_emulation.py.""" + assert arch is None + if not self._PchHeader(): + return [] + pch_ext = os.path.splitext(self.pch_source)[1] + for source in sources: + if _LanguageMatchesForPch(os.path.splitext(source)[1], pch_ext): + return [(None, None, self.output_obj)] + return [] + + def GetPchBuildCommands(self, arch): + """Not used on Windows as there are no additional build steps required + (instead, existing steps are modified in GetFlagsModifications below).""" + return [] + + def GetFlagsModifications(self, input, output, implicit, command, + cflags_c, cflags_cc, expand_special): + """Get the modified cflags and implicit dependencies that should be used + for the pch compilation step.""" + if input == self.pch_source: + pch_output = ['/Yc' + self._PchHeader()] + if command == 'cxx': + return ([('cflags_cc', map(expand_special, cflags_cc + pch_output))], + self.output_obj, []) + elif command == 'cc': + return ([('cflags_c', map(expand_special, cflags_c + pch_output))], + self.output_obj, []) + return [], output, implicit + + +vs_version = None +def GetVSVersion(generator_flags): + global vs_version + if not vs_version: + vs_version = gyp.MSVSVersion.SelectVisualStudioVersion( + generator_flags.get('msvs_version', 'auto'), + allow_fallback=False) + return vs_version + +def _GetVsvarsSetupArgs(generator_flags, arch): + vs = GetVSVersion(generator_flags) + return vs.SetupScript() + +def ExpandMacros(string, expansions): + """Expand $(Variable) per expansions dict. See MsvsSettings.GetVSMacroEnv + for the canonical way to retrieve a suitable dict.""" + if '$' in string: + for old, new in expansions.iteritems(): + assert '$(' not in new, new + string = string.replace(old, new) + return string + +def _ExtractImportantEnvironment(output_of_set): + """Extracts environment variables required for the toolchain to run from + a textual dump output by the cmd.exe 'set' command.""" + envvars_to_save = ( + 'goma_.*', # TODO(scottmg): This is ugly, but needed for goma. + 'include', + 'lib', + 'libpath', + 'path', + 'pathext', + 'systemroot', + 'temp', + 'tmp', + ) + env = {} + for line in output_of_set.splitlines(): + for envvar in envvars_to_save: + if re.match(envvar + '=', line.lower()): + var, setting = line.split('=', 1) + if envvar == 'path': + # Our own rules (for running gyp-win-tool) and other actions in + # Chromium rely on python being in the path. Add the path to this + # python here so that if it's not in the path when ninja is run + # later, python will still be found. + setting = os.path.dirname(sys.executable) + os.pathsep + setting + env[var.upper()] = setting + break + for required in ('SYSTEMROOT', 'TEMP', 'TMP'): + if required not in env: + raise Exception('Environment variable "%s" ' + 'required to be set to valid path' % required) + return env + +def _FormatAsEnvironmentBlock(envvar_dict): + """Format as an 'environment block' directly suitable for CreateProcess. + Briefly this is a list of key=value\0, terminated by an additional \0. See + CreateProcess documentation for more details.""" + block = '' + nul = '\0' + for key, value in envvar_dict.iteritems(): + block += key + '=' + value + nul + block += nul + return block + +def _ExtractCLPath(output_of_where): + """Gets the path to cl.exe based on the output of calling the environment + setup batch file, followed by the equivalent of `where`.""" + # Take the first line, as that's the first found in the PATH. + for line in output_of_where.strip().splitlines(): + if line.startswith('LOC:'): + return line[len('LOC:'):].strip() + +def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, + system_includes, open_out): + """It's not sufficient to have the absolute path to the compiler, linker, + etc. on Windows, as those tools rely on .dlls being in the PATH. We also + need to support both x86 and x64 compilers within the same build (to support + msvs_target_platform hackery). Different architectures require a different + compiler binary, and different supporting environment variables (INCLUDE, + LIB, LIBPATH). So, we extract the environment here, wrap all invocations + of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which + sets up the environment, and then we do not prefix the compiler with + an absolute path, instead preferring something like "cl.exe" in the rule + which will then run whichever the environment setup has put in the path. + When the following procedure to generate environment files does not + meet your requirement (e.g. for custom toolchains), you can pass + "-G ninja_use_custom_environment_files" to the gyp to suppress file + generation and use custom environment files prepared by yourself.""" + archs = ('x86', 'x64') + if generator_flags.get('ninja_use_custom_environment_files', 0): + cl_paths = {} + for arch in archs: + cl_paths[arch] = 'cl.exe' + return cl_paths + vs = GetVSVersion(generator_flags) + cl_paths = {} + for arch in archs: + # Extract environment variables for subprocesses. + args = vs.SetupScript(arch) + args.extend(('&&', 'set')) + popen = subprocess.Popen( + args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + variables, _ = popen.communicate() + env = _ExtractImportantEnvironment(variables) + + # Inject system includes from gyp files into INCLUDE. + if system_includes: + system_includes = system_includes | OrderedSet( + env.get('INCLUDE', '').split(';')) + env['INCLUDE'] = ';'.join(system_includes) + + env_block = _FormatAsEnvironmentBlock(env) + f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb') + f.write(env_block) + f.close() + + # Find cl.exe location for this architecture. + args = vs.SetupScript(arch) + args.extend(('&&', + 'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i')) + popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE) + output, _ = popen.communicate() + cl_paths[arch] = _ExtractCLPath(output) + return cl_paths + +def VerifyMissingSources(sources, build_dir, generator_flags, gyp_to_ninja): + """Emulate behavior of msvs_error_on_missing_sources present in the msvs + generator: Check that all regular source files, i.e. not created at run time, + exist on disk. Missing files cause needless recompilation when building via + VS, and we want this check to match for people/bots that build using ninja, + so they're not surprised when the VS build fails.""" + if int(generator_flags.get('msvs_error_on_missing_sources', 0)): + no_specials = filter(lambda x: '$' not in x, sources) + relative = [os.path.join(build_dir, gyp_to_ninja(s)) for s in no_specials] + missing = filter(lambda x: not os.path.exists(x), relative) + if missing: + # They'll look like out\Release\..\..\stuff\things.cc, so normalize the + # path for a slightly less crazy looking output. + cleaned_up = [os.path.normpath(x) for x in missing] + raise Exception('Missing input files:\n%s' % '\n'.join(cleaned_up)) + +# Sets some values in default_variables, which are required for many +# generators, run on Windows. +def CalculateCommonVariables(default_variables, params): + generator_flags = params.get('generator_flags', {}) + + # Set a variable so conditions can be based on msvs_version. + msvs_version = gyp.msvs_emulation.GetVSVersion(generator_flags) + default_variables['MSVS_VERSION'] = msvs_version.ShortName() + + # To determine processor word size on Windows, in addition to checking + # PROCESSOR_ARCHITECTURE (which reflects the word size of the current + # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which + # contains the actual word size of the system when running thru WOW64). + if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or + '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')): + default_variables['MSVS_OS_BITS'] = 64 + else: + default_variables['MSVS_OS_BITS'] = 32 diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py new file mode 100644 index 0000000000000..d2948f06c08e3 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py @@ -0,0 +1,160 @@ +# This file comes from +# https://github.com/martine/ninja/blob/master/misc/ninja_syntax.py +# Do not edit! Edit the upstream one instead. + +"""Python module for generating .ninja files. + +Note that this is emphatically not a required piece of Ninja; it's +just a helpful utility for build-file-generation systems that already +use Python. +""" + +import textwrap +import re + +def escape_path(word): + return word.replace('$ ','$$ ').replace(' ','$ ').replace(':', '$:') + +class Writer(object): + def __init__(self, output, width=78): + self.output = output + self.width = width + + def newline(self): + self.output.write('\n') + + def comment(self, text): + for line in textwrap.wrap(text, self.width - 2): + self.output.write('# ' + line + '\n') + + def variable(self, key, value, indent=0): + if value is None: + return + if isinstance(value, list): + value = ' '.join(filter(None, value)) # Filter out empty strings. + self._line('%s = %s' % (key, value), indent) + + def pool(self, name, depth): + self._line('pool %s' % name) + self.variable('depth', depth, indent=1) + + def rule(self, name, command, description=None, depfile=None, + generator=False, pool=None, restat=False, rspfile=None, + rspfile_content=None, deps=None): + self._line('rule %s' % name) + self.variable('command', command, indent=1) + if description: + self.variable('description', description, indent=1) + if depfile: + self.variable('depfile', depfile, indent=1) + if generator: + self.variable('generator', '1', indent=1) + if pool: + self.variable('pool', pool, indent=1) + if restat: + self.variable('restat', '1', indent=1) + if rspfile: + self.variable('rspfile', rspfile, indent=1) + if rspfile_content: + self.variable('rspfile_content', rspfile_content, indent=1) + if deps: + self.variable('deps', deps, indent=1) + + def build(self, outputs, rule, inputs=None, implicit=None, order_only=None, + variables=None): + outputs = self._as_list(outputs) + all_inputs = self._as_list(inputs)[:] + out_outputs = list(map(escape_path, outputs)) + all_inputs = list(map(escape_path, all_inputs)) + + if implicit: + implicit = map(escape_path, self._as_list(implicit)) + all_inputs.append('|') + all_inputs.extend(implicit) + if order_only: + order_only = map(escape_path, self._as_list(order_only)) + all_inputs.append('||') + all_inputs.extend(order_only) + + self._line('build %s: %s' % (' '.join(out_outputs), + ' '.join([rule] + all_inputs))) + + if variables: + if isinstance(variables, dict): + iterator = iter(variables.items()) + else: + iterator = iter(variables) + + for key, val in iterator: + self.variable(key, val, indent=1) + + return outputs + + def include(self, path): + self._line('include %s' % path) + + def subninja(self, path): + self._line('subninja %s' % path) + + def default(self, paths): + self._line('default %s' % ' '.join(self._as_list(paths))) + + def _count_dollars_before_index(self, s, i): + """Returns the number of '$' characters right in front of s[i].""" + dollar_count = 0 + dollar_index = i - 1 + while dollar_index > 0 and s[dollar_index] == '$': + dollar_count += 1 + dollar_index -= 1 + return dollar_count + + def _line(self, text, indent=0): + """Write 'text' word-wrapped at self.width characters.""" + leading_space = ' ' * indent + while len(leading_space) + len(text) > self.width: + # The text is too wide; wrap if possible. + + # Find the rightmost space that would obey our width constraint and + # that's not an escaped space. + available_space = self.width - len(leading_space) - len(' $') + space = available_space + while True: + space = text.rfind(' ', 0, space) + if space < 0 or \ + self._count_dollars_before_index(text, space) % 2 == 0: + break + + if space < 0: + # No such space; just use the first unescaped space we can find. + space = available_space - 1 + while True: + space = text.find(' ', space + 1) + if space < 0 or \ + self._count_dollars_before_index(text, space) % 2 == 0: + break + if space < 0: + # Give up on breaking. + break + + self.output.write(leading_space + text[0:space] + ' $\n') + text = text[space+1:] + + # Subsequent lines are continuations, so indent them. + leading_space = ' ' * (indent+2) + + self.output.write(leading_space + text + '\n') + + def _as_list(self, input): + if input is None: + return [] + if isinstance(input, list): + return input + return [input] + + +def escape(string): + """Escape a string such that it can be embedded into a Ninja file without + further interpretation.""" + assert '\n' not in string, 'Ninja syntax does not allow newlines' + # We only have one special metacharacter: '$'. + return string.replace('$', '$$') diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ordered_dict.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ordered_dict.py new file mode 100644 index 0000000000000..a1e89f9199087 --- /dev/null +++ b/node_modules/npm-lifecycle/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/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py new file mode 100644 index 0000000000000..74c98c5a79594 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py @@ -0,0 +1,46 @@ +# Copyright 2014 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. + +"""A clone of the default copy.deepcopy that doesn't handle cyclic +structures or complex types except for dicts and lists. This is +because gyp copies so large structure that small copy overhead ends up +taking seconds in a project the size of Chromium.""" + +class Error(Exception): + pass + +__all__ = ["Error", "deepcopy"] + +def deepcopy(x): + """Deep copy operation on gyp objects such as strings, ints, dicts + and lists. More than twice as fast as copy.deepcopy but much less + generic.""" + + try: + return _deepcopy_dispatch[type(x)](x) + except KeyError: + raise Error('Unsupported type %s for deepcopy. Use copy.deepcopy ' + + 'or expand simple_copy support.' % type(x)) + +_deepcopy_dispatch = d = {} + +def _deepcopy_atomic(x): + return x + +for x in (type(None), int, long, float, + bool, str, unicode, type): + d[x] = _deepcopy_atomic + +def _deepcopy_list(x): + return [deepcopy(a) for a in x] +d[list] = _deepcopy_list + +def _deepcopy_dict(x): + y = {} + for key, value in x.iteritems(): + y[deepcopy(key)] = deepcopy(value) + return y +d[dict] = _deepcopy_dict + +del d diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py new file mode 100755 index 0000000000000..bb6f1ea436f25 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py @@ -0,0 +1,314 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 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. + +"""Utility functions for Windows builds. + +These functions are executed via gyp-win-tool when using the ninja generator. +""" + +import os +import re +import shutil +import subprocess +import stat +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.+)$', re.IGNORECASE) + +def main(args): + executor = WinTool() + exit_code = executor.Dispatch(args) + if exit_code is not None: + sys.exit(exit_code) + + +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 = re.sub(r'\W+', '', + '%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: + raise Exception("Not enough arguments") + + method = "Exec%s" % self._CommandifyName(args[0]) + return getattr(self, method)(*args[1:]) + + def _CommandifyName(self, name_string): + """Transforms a tool name like recursive-mirror to RecursiveMirror.""" + return name_string.title().replace('-', '') + + def _GetEnv(self, arch): + """Gets the saved environment from a file for a given architecture.""" + # The environment is saved as an "environment block" (see CreateProcess + # and msvs_emulation for details). We convert to a dict here. + # Drop last 2 NULs, one for list terminator, one for trailing vs. separator. + pairs = open(arch).read()[:-2].split('\0') + kvs = [item.split('=', 1) for item in pairs] + return dict(kvs) + + def ExecStamp(self, path): + """Simple stamp command.""" + open(path, 'w').close() + + def ExecRecursiveMirror(self, source, dest): + """Emulation of rm -rf out && cp -af in out.""" + if os.path.exists(dest): + if os.path.isdir(dest): + def _on_error(fn, path, excinfo): + # The operation failed, possibly because the file is set to + # read-only. If that's why, make it writable and try the op again. + if not os.access(path, os.W_OK): + os.chmod(path, stat.S_IWRITE) + fn(path) + shutil.rmtree(dest, onerror=_on_error) + else: + if not os.access(dest, os.W_OK): + # Attempt to make the file writable before deleting it. + os.chmod(dest, stat.S_IWRITE) + os.unlink(dest) + + if os.path.isdir(source): + shutil.copytree(source, dest) + else: + shutil.copy2(source, dest) + + 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) + if use_separate_mspdbsrv == 'True': + self._UseSeparateMspdbsrv(env, args) + link = subprocess.Popen([args[0].replace('/', '\\')] + list(args[1:]), + shell=True, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + out, _ = link.communicate() + for line in out.splitlines(): + if (not line.startswith(' Creating library ') and + not line.startswith('Generating code') and + not line.startswith('Finished generating code')): + print line + 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 + (some XML blocks are recognized by the OS loader, but not the manifest + tool).""" + env = self._GetEnv(arch) + popen = subprocess.Popen(args, shell=True, env=env, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + out, _ = popen.communicate() + for line in out.splitlines(): + if line and 'manifest authoring warning 81010002' not in line: + print line + return popen.returncode + + def ExecManifestToRc(self, arch, *args): + """Creates a resource file pointing a SxS assembly manifest. + |args| is tuple containing path to resource file, path to manifest file + and resource name which can be "1" (for executables) or "2" (for DLLs).""" + manifest_path, resource_path, resource_name = args + with open(resource_path, 'wb') as output: + output.write('#include \n%s RT_MANIFEST "%s"' % ( + resource_name, + os.path.abspath(manifest_path).replace('\\', '/'))) + + def ExecMidlWrapper(self, arch, outdir, tlb, h, dlldata, iid, proxy, idl, + *flags): + """Filter noisy filenames output from MIDL compile step that isn't + quietable via command line flags. + """ + args = ['midl', '/nologo'] + list(flags) + [ + '/out', outdir, + '/tlb', tlb, + '/h', h, + '/dlldata', dlldata, + '/iid', iid, + '/proxy', proxy, + idl] + env = self._GetEnv(arch) + popen = subprocess.Popen(args, shell=True, env=env, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + out, _ = popen.communicate() + # Filter junk out of stdout, and write filtered versions. Output we want + # to filter is pairs of lines that look like this: + # Processing C:\Program Files (x86)\Microsoft SDKs\...\include\objidl.idl + # objidl.idl + lines = out.splitlines() + prefixes = ('Processing ', '64 bit Processing ') + processing = set(os.path.basename(x) + for x in lines if x.startswith(prefixes)) + for line in lines: + if not line.startswith(prefixes) and line not in processing: + print line + return popen.returncode + + def ExecAsmWrapper(self, arch, *args): + """Filter logo banner from invocations of asm.exe.""" + env = self._GetEnv(arch) + popen = subprocess.Popen(args, shell=True, env=env, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + out, _ = popen.communicate() + for line in out.splitlines(): + if (not line.startswith('Copyright (C) Microsoft Corporation') and + not line.startswith('Microsoft (R) Macro Assembler') and + not line.startswith(' Assembling: ') and + line): + print line + return popen.returncode + + def ExecRcWrapper(self, arch, *args): + """Filter logo banner from invocations of rc.exe. Older versions of RC + don't support the /nologo flag.""" + env = self._GetEnv(arch) + popen = subprocess.Popen(args, shell=True, env=env, + stdout=subprocess.PIPE, stderr=subprocess.STDOUT) + out, _ = popen.communicate() + for line in out.splitlines(): + if (not line.startswith('Microsoft (R) Windows (R) Resource Compiler') and + not line.startswith('Copyright (C) Microsoft Corporation') and + line): + print line + return popen.returncode + + def ExecActionWrapper(self, arch, rspfile, *dir): + """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 + return subprocess.call(args, shell=True, env=env, cwd=dir) + + def ExecClCompile(self, project_dir, selected_files): + """Executed by msvs-ninja projects when the 'ClCompile' target is used to + build selected C/C++ files.""" + project_dir = os.path.relpath(project_dir, BASE_DIR) + selected_files = selected_files.split(';') + ninja_targets = [os.path.join(project_dir, filename) + '^^' + for filename in selected_files] + cmd = ['ninja.exe'] + cmd.extend(ninja_targets) + return subprocess.call(cmd, shell=True, cwd=BASE_DIR) + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py new file mode 100644 index 0000000000000..69f7d97cfa69a --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py @@ -0,0 +1,1653 @@ +# Copyright (c) 2012 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. + +""" +This module contains classes that help to emulate xcodebuild behavior on top of +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 + +# Populated lazily by XcodeVersion, for efficiency, and to fix an issue when +# "xcodebuild" is called too quickly (it has been found to return incorrect +# version number). +XCODE_VERSION_CACHE = None + +# Populated lazily by GetXcodeArchsDefault, to an |XcodeArchsDefault| instance +# corresponding to the installed version of Xcode. +XCODE_ARCHS_DEFAULT_CACHE = None + + +def XcodeArchsVariableMapping(archs, archs_including_64_bit=None): + """Constructs a dictionary with expansion for $(ARCHS_STANDARD) variable, + and optionally for $(ARCHS_STANDARD_INCLUDING_64_BIT).""" + mapping = {'$(ARCHS_STANDARD)': archs} + if archs_including_64_bit: + mapping['$(ARCHS_STANDARD_INCLUDING_64_BIT)'] = archs_including_64_bit + return mapping + +class XcodeArchsDefault(object): + """A class to resolve ARCHS variable from xcode_settings, resolving Xcode + macros and implementing filtering by VALID_ARCHS. The expansion of macros + depends on the SDKROOT used ("macosx", "iphoneos", "iphonesimulator") and + on the version of Xcode. + """ + + # Match variable like $(ARCHS_STANDARD). + variable_pattern = re.compile(r'\$\([a-zA-Z_][a-zA-Z0-9_]*\)$') + + def __init__(self, default, mac, iphonesimulator, iphoneos): + self._default = (default,) + self._archs = {'mac': mac, 'ios': iphoneos, 'iossim': iphonesimulator} + + def _VariableMapping(self, sdkroot): + """Returns the dictionary of variable mapping depending on the SDKROOT.""" + sdkroot = sdkroot.lower() + if 'iphoneos' in sdkroot: + return self._archs['ios'] + elif 'iphonesimulator' in sdkroot: + return self._archs['iossim'] + else: + return self._archs['mac'] + + def _ExpandArchs(self, archs, sdkroot): + """Expands variables references in ARCHS, and remove duplicates.""" + variable_mapping = self._VariableMapping(sdkroot) + expanded_archs = [] + for arch in archs: + if self.variable_pattern.match(arch): + variable = arch + try: + variable_expansion = variable_mapping[variable] + for arch in variable_expansion: + if arch not in expanded_archs: + expanded_archs.append(arch) + except KeyError as e: + print 'Warning: Ignoring unsupported variable "%s".' % variable + elif arch not in expanded_archs: + expanded_archs.append(arch) + return expanded_archs + + def ActiveArchs(self, archs, valid_archs, sdkroot): + """Expands variables references in ARCHS, and filter by VALID_ARCHS if it + is defined (if not set, Xcode accept any value in ARCHS, otherwise, only + values present in VALID_ARCHS are kept).""" + expanded_archs = self._ExpandArchs(archs or self._default, sdkroot or '') + if valid_archs: + filtered_archs = [] + for arch in expanded_archs: + if arch in valid_archs: + filtered_archs.append(arch) + expanded_archs = filtered_archs + return expanded_archs + + +def GetXcodeArchsDefault(): + """Returns the |XcodeArchsDefault| object to use to expand ARCHS for the + installed version of Xcode. The default values used by Xcode for ARCHS + and the expansion of the variables depends on the version of Xcode used. + + For all version anterior to Xcode 5.0 or posterior to Xcode 5.1 included + uses $(ARCHS_STANDARD) if ARCHS is unset, while Xcode 5.0 to 5.0.2 uses + $(ARCHS_STANDARD_INCLUDING_64_BIT). This variable was added to Xcode 5.0 + and deprecated with Xcode 5.1. + + For "macosx" SDKROOT, all version starting with Xcode 5.0 includes 64-bit + architecture as part of $(ARCHS_STANDARD) and default to only building it. + + For "iphoneos" and "iphonesimulator" SDKROOT, 64-bit architectures are part + of $(ARCHS_STANDARD_INCLUDING_64_BIT) from Xcode 5.0. From Xcode 5.1, they + are also part of $(ARCHS_STANDARD). + + All thoses rules are coded in the construction of the |XcodeArchsDefault| + object to use depending on the version of Xcode detected. The object is + for performance reason.""" + global XCODE_ARCHS_DEFAULT_CACHE + if XCODE_ARCHS_DEFAULT_CACHE: + return XCODE_ARCHS_DEFAULT_CACHE + xcode_version, _ = XcodeVersion() + if xcode_version < '0500': + XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault( + '$(ARCHS_STANDARD)', + XcodeArchsVariableMapping(['i386']), + XcodeArchsVariableMapping(['i386']), + XcodeArchsVariableMapping(['armv7'])) + elif xcode_version < '0510': + XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault( + '$(ARCHS_STANDARD_INCLUDING_64_BIT)', + XcodeArchsVariableMapping(['x86_64'], ['x86_64']), + XcodeArchsVariableMapping(['i386'], ['i386', 'x86_64']), + XcodeArchsVariableMapping( + ['armv7', 'armv7s'], + ['armv7', 'armv7s', 'arm64'])) + else: + XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault( + '$(ARCHS_STANDARD)', + XcodeArchsVariableMapping(['x86_64'], ['x86_64']), + XcodeArchsVariableMapping(['i386', 'x86_64'], ['i386', 'x86_64']), + XcodeArchsVariableMapping( + ['armv7', 'armv7s', 'arm64'], + ['armv7', 'armv7s', 'arm64'])) + return XCODE_ARCHS_DEFAULT_CACHE + + +class XcodeSettings(object): + """A class that understands the gyp 'xcode_settings' 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. + _plist_cache = {} + + # Populated lazily by GetIOSPostbuilds. Shared by all XcodeSettings, so + # cached at class-level for efficiency. + _codesigning_key_cache = {} + + def __init__(self, spec): + self.spec = spec + + self.isIOS = False + + # Per-target 'xcode_settings' are pushed down into configs earlier by gyp. + # This means self.xcode_settings[config] always contains all settings + # for that config -- the per-target settings as well. Settings that are + # the same for all configs are implicitly per-target settings. + self.xcode_settings = {} + configs = spec['configurations'] + for configname, config in configs.iteritems(): + self.xcode_settings[configname] = config.get('xcode_settings', {}) + self._ConvertConditionalKeys(configname) + if self.xcode_settings[configname].get('IPHONEOS_DEPLOYMENT_TARGET', + None): + self.isIOS = True + + # This is only non-None temporarily during the execution of some methods. + self.configname = None + + # Used by _AdjustLibrary to match .a and .dylib entries in libraries. + self.library_re = re.compile(r'^lib([^/]+)\.(a|dylib)$') + + def _ConvertConditionalKeys(self, configname): + """Converts or warns on conditional keys. Xcode supports conditional keys, + such as CODE_SIGN_IDENTITY[sdk=iphoneos*]. This is a partial implementation + with some keys converted while the rest force a warning.""" + settings = self.xcode_settings[configname] + conditional_keys = [key for key in settings if key.endswith(']')] + for key in conditional_keys: + # If you need more, speak up at http://crbug.com/122592 + if key.endswith("[sdk=iphoneos*]"): + if configname.endswith("iphoneos"): + new_key = key.split("[")[0] + settings[new_key] = settings[key] + else: + print 'Warning: Conditional keys not implemented, ignoring:', \ + ' '.join(conditional_keys) + del settings[key] + + def _Settings(self): + assert self.configname + return self.xcode_settings[self.configname] + + def _Test(self, test_key, cond_key, default): + return self._Settings().get(test_key, default) == cond_key + + def _Appendf(self, lst, test_key, format_str, default=None): + if test_key in self._Settings(): + lst.append(format_str % str(self._Settings()[test_key])) + elif default: + lst.append(format_str % str(default)) + + def _WarnUnimplemented(self, test_key): + if test_key in self._Settings(): + print 'Warning: Ignoring not yet implemented key "%s".' % test_key + + def IsBinaryOutputFormat(self, configname): + default = "binary" if self.isIOS else "xml" + format = self.xcode_settings[configname].get('INFOPLIST_OUTPUT_FORMAT', + default) + return format == "binary" + + def _IsBundle(self): + return int(self.spec.get('mac_bundle', 0)) != 0 + + def _IsIosAppExtension(self): + return int(self.spec.get('ios_app_extension', 0)) != 0 + + def _IsIosWatchKitExtension(self): + return int(self.spec.get('ios_watchkit_extension', 0)) != 0 + + def _IsIosWatchApp(self): + return int(self.spec.get('ios_watch_app', 0)) != 0 + + def _IsXCTest(self): + return int(self.spec.get('mac_xctest_bundle', 0)) != 0 + + def GetFrameworkVersion(self): + """Returns the framework version of the current target. Only valid for + bundles.""" + assert self._IsBundle() + return self.GetPerTargetSetting('FRAMEWORK_VERSION', default='A') + + def GetWrapperExtension(self): + """Returns the bundle extension (.app, .framework, .plugin, etc). Only + valid for bundles.""" + assert self._IsBundle() + if self.spec['type'] in ('loadable_module', 'shared_library'): + default_wrapper_extension = { + 'loadable_module': 'bundle', + 'shared_library': 'framework', + }[self.spec['type']] + wrapper_extension = self.GetPerTargetSetting( + 'WRAPPER_EXTENSION', default=default_wrapper_extension) + return '.' + self.spec.get('product_extension', wrapper_extension) + elif self.spec['type'] == 'executable': + if self._IsIosAppExtension() or self._IsIosWatchKitExtension(): + return '.' + self.spec.get('product_extension', 'appex') + else: + return '.' + self.spec.get('product_extension', 'app') + else: + assert False, "Don't know extension for '%s', target '%s'" % ( + self.spec['type'], self.spec['target_name']) + + def GetProductName(self): + """Returns PRODUCT_NAME.""" + return self.spec.get('product_name', self.spec['target_name']) + + def GetFullProductName(self): + """Returns FULL_PRODUCT_NAME.""" + if self._IsBundle(): + return self.GetWrapperName() + else: + return self._GetStandaloneBinaryPath() + + def GetWrapperName(self): + """Returns the directory name of the bundle represented by this target. + Only valid for bundles.""" + assert self._IsBundle() + return self.GetProductName() + self.GetWrapperExtension() + + def GetBundleContentsFolderPath(self): + """Returns the qualified path to the bundle's contents folder. E.g. + Chromium.app/Contents or Foo.bundle/Versions/A. Only valid for bundles.""" + if self.isIOS: + return self.GetWrapperName() + assert self._IsBundle() + if self.spec['type'] == 'shared_library': + return os.path.join( + self.GetWrapperName(), 'Versions', self.GetFrameworkVersion()) + else: + # loadable_modules have a 'Contents' folder like executables. + return os.path.join(self.GetWrapperName(), 'Contents') + + def GetBundleResourceFolder(self): + """Returns the qualified path to the bundle's resource folder. E.g. + Chromium.app/Contents/Resources. Only valid for bundles.""" + assert self._IsBundle() + if self.isIOS: + return self.GetBundleContentsFolderPath() + return os.path.join(self.GetBundleContentsFolderPath(), 'Resources') + + def GetBundlePlistPath(self): + """Returns the qualified path to the bundle's plist file. E.g. + Chromium.app/Contents/Info.plist. Only valid for bundles.""" + assert self._IsBundle() + if self.spec['type'] in ('executable', 'loadable_module'): + return os.path.join(self.GetBundleContentsFolderPath(), 'Info.plist') + else: + return os.path.join(self.GetBundleContentsFolderPath(), + 'Resources', 'Info.plist') + + def GetProductType(self): + """Returns the PRODUCT_TYPE of this target.""" + if self._IsIosAppExtension(): + assert self._IsBundle(), ('ios_app_extension flag requires mac_bundle ' + '(target %s)' % self.spec['target_name']) + return 'com.apple.product-type.app-extension' + if self._IsIosWatchKitExtension(): + assert self._IsBundle(), ('ios_watchkit_extension flag requires ' + 'mac_bundle (target %s)' % self.spec['target_name']) + return 'com.apple.product-type.watchkit-extension' + if self._IsIosWatchApp(): + assert self._IsBundle(), ('ios_watch_app flag requires mac_bundle ' + '(target %s)' % self.spec['target_name']) + return 'com.apple.product-type.application.watchapp' + if self._IsBundle(): + return { + 'executable': 'com.apple.product-type.application', + 'loadable_module': 'com.apple.product-type.bundle', + 'shared_library': 'com.apple.product-type.framework', + }[self.spec['type']] + else: + return { + 'executable': 'com.apple.product-type.tool', + 'loadable_module': 'com.apple.product-type.library.dynamic', + 'shared_library': 'com.apple.product-type.library.dynamic', + 'static_library': 'com.apple.product-type.library.static', + }[self.spec['type']] + + def GetMachOType(self): + """Returns the MACH_O_TYPE of this target.""" + # Weird, but matches Xcode. + if not self._IsBundle() and self.spec['type'] == 'executable': + return '' + return { + 'executable': 'mh_execute', + 'static_library': 'staticlib', + 'shared_library': 'mh_dylib', + 'loadable_module': 'mh_bundle', + }[self.spec['type']] + + def _GetBundleBinaryPath(self): + """Returns the name of the bundle binary of by this target. + E.g. Chromium.app/Contents/MacOS/Chromium. Only valid for bundles.""" + assert self._IsBundle() + if self.spec['type'] in ('shared_library') or self.isIOS: + path = self.GetBundleContentsFolderPath() + elif self.spec['type'] in ('executable', 'loadable_module'): + path = os.path.join(self.GetBundleContentsFolderPath(), 'MacOS') + return os.path.join(path, self.GetExecutableName()) + + def _GetStandaloneExecutableSuffix(self): + if 'product_extension' in self.spec: + return '.' + self.spec['product_extension'] + return { + 'executable': '', + 'static_library': '.a', + 'shared_library': '.dylib', + 'loadable_module': '.so', + }[self.spec['type']] + + def _GetStandaloneExecutablePrefix(self): + return self.spec.get('product_prefix', { + 'executable': '', + 'static_library': 'lib', + 'shared_library': 'lib', + # Non-bundled loadable_modules are called foo.so for some reason + # (that is, .so and no prefix) with the xcode build -- match that. + 'loadable_module': '', + }[self.spec['type']]) + + def _GetStandaloneBinaryPath(self): + """Returns the name of the non-bundle binary represented by this target. + E.g. hello_world. Only valid for non-bundles.""" + assert not self._IsBundle() + assert self.spec['type'] in ( + 'executable', 'shared_library', 'static_library', 'loadable_module'), ( + 'Unexpected type %s' % self.spec['type']) + target = self.spec['target_name'] + if self.spec['type'] == 'static_library': + if target[:3] == 'lib': + target = target[3:] + elif self.spec['type'] in ('loadable_module', 'shared_library'): + if target[:3] == 'lib': + target = target[3:] + + target_prefix = self._GetStandaloneExecutablePrefix() + target = self.spec.get('product_name', target) + target_ext = self._GetStandaloneExecutableSuffix() + return target_prefix + target + target_ext + + def GetExecutableName(self): + """Returns the executable name of the bundle represented by this target. + E.g. Chromium.""" + if self._IsBundle(): + return self.spec.get('product_name', self.spec['target_name']) + else: + return self._GetStandaloneBinaryPath() + + def GetExecutablePath(self): + """Returns the directory name of the bundle represented by this target. E.g. + Chromium.app/Contents/MacOS/Chromium.""" + if self._IsBundle(): + return self._GetBundleBinaryPath() + else: + return self._GetStandaloneBinaryPath() + + def GetActiveArchs(self, configname): + """Returns the architectures this target should be built for.""" + config_settings = self.xcode_settings[configname] + xcode_archs_default = GetXcodeArchsDefault() + return xcode_archs_default.ActiveArchs( + config_settings.get('ARCHS'), + config_settings.get('VALID_ARCHS'), + config_settings.get('SDKROOT')) + + def _GetSdkVersionInfoItem(self, sdk, infoitem): + # xcodebuild requires Xcode and can't run on Command Line Tools-only + # systems from 10.7 onward. + # Since the CLT has no SDK paths anyway, returning None is the + # most sensible route and should still do the right thing. + try: + return GetStdoutQuiet(['xcodebuild', '-version', '-sdk', sdk, infoitem]) + except: + pass + + def _SdkRoot(self, configname): + if configname is None: + configname = self.configname + return self.GetPerConfigSetting('SDKROOT', configname, default='') + + def _SdkPath(self, configname=None): + 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: + 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): + self._Appendf(lst, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s') + if 'IPHONEOS_DEPLOYMENT_TARGET' in self._Settings(): + # TODO: Implement this better? + sdk_path_basename = os.path.basename(self._SdkPath()) + if sdk_path_basename.lower().startswith('iphonesimulator'): + self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET', + '-mios-simulator-version-min=%s') + else: + self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET', + '-miphoneos-version-min=%s') + + def GetCflags(self, configname, arch=None): + """Returns flags that need to be added to .c, .cc, .m, and .mm + compilations.""" + # This functions (and the similar ones below) do not offer complete + # emulation of all xcode_settings keys. They're implemented on demand. + + self.configname = configname + cflags = [] + + sdk_root = self._SdkPath() + if 'SDKROOT' in self._Settings() and sdk_root: + cflags.append('-isysroot %s' % sdk_root) + + if self._Test('CLANG_WARN_CONSTANT_CONVERSION', 'YES', default='NO'): + cflags.append('-Wconstant-conversion') + + if self._Test('GCC_CHAR_IS_UNSIGNED_CHAR', 'YES', default='NO'): + cflags.append('-funsigned-char') + + if self._Test('GCC_CW_ASM_SYNTAX', 'YES', default='YES'): + cflags.append('-fasm-blocks') + + if 'GCC_DYNAMIC_NO_PIC' in self._Settings(): + if self._Settings()['GCC_DYNAMIC_NO_PIC'] == 'YES': + cflags.append('-mdynamic-no-pic') + else: + pass + # TODO: In this case, it depends on the target. xcode passes + # mdynamic-no-pic by default for executable and possibly static lib + # according to mento + + if self._Test('GCC_ENABLE_PASCAL_STRINGS', 'YES', default='YES'): + cflags.append('-mpascal-strings') + + self._Appendf(cflags, 'GCC_OPTIMIZATION_LEVEL', '-O%s', default='s') + + if self._Test('GCC_GENERATE_DEBUGGING_SYMBOLS', 'YES', default='YES'): + dbg_format = self._Settings().get('DEBUG_INFORMATION_FORMAT', 'dwarf') + if dbg_format == 'dwarf': + cflags.append('-gdwarf-2') + elif dbg_format == 'stabs': + raise NotImplementedError('stabs debug format is not supported yet.') + elif dbg_format == 'dwarf-with-dsym': + cflags.append('-gdwarf-2') + else: + raise NotImplementedError('Unknown debug format %s' % dbg_format) + + if self._Settings().get('GCC_STRICT_ALIASING') == 'YES': + cflags.append('-fstrict-aliasing') + elif self._Settings().get('GCC_STRICT_ALIASING') == 'NO': + cflags.append('-fno-strict-aliasing') + + if self._Test('GCC_SYMBOLS_PRIVATE_EXTERN', 'YES', default='NO'): + cflags.append('-fvisibility=hidden') + + if self._Test('GCC_TREAT_WARNINGS_AS_ERRORS', 'YES', default='NO'): + cflags.append('-Werror') + + if self._Test('GCC_WARN_ABOUT_MISSING_NEWLINE', 'YES', default='NO'): + cflags.append('-Wnewline-eof') + + # In Xcode, this is only activated when GCC_COMPILER_VERSION is clang or + # llvm-gcc. It also requires a fairly recent libtool, and + # if the system clang isn't used, DYLD_LIBRARY_PATH needs to contain the + # path to the libLTO.dylib that matches the used clang. + if self._Test('LLVM_LTO', 'YES', default='NO'): + cflags.append('-flto') + + self._AppendPlatformVersionMinFlags(cflags) + + # TODO: + if self._Test('COPY_PHASE_STRIP', 'YES', default='NO'): + self._WarnUnimplemented('COPY_PHASE_STRIP') + self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS') + self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS') + + # TODO: This is exported correctly, but assigning to it is not supported. + self._WarnUnimplemented('MACH_O_TYPE') + self._WarnUnimplemented('PRODUCT_TYPE') + + if arch is not None: + archs = [arch] + else: + assert self.configname + archs = self.GetActiveArchs(self.configname) + if len(archs) != 1: + # TODO: Supporting fat binaries will be annoying. + self._WarnUnimplemented('ARCHS') + archs = ['i386'] + cflags.append('-arch ' + archs[0]) + + if archs[0] in ('i386', 'x86_64'): + if self._Test('GCC_ENABLE_SSE3_EXTENSIONS', 'YES', default='NO'): + cflags.append('-msse3') + if self._Test('GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS', 'YES', + default='NO'): + cflags.append('-mssse3') # Note 3rd 's'. + if self._Test('GCC_ENABLE_SSE41_EXTENSIONS', 'YES', default='NO'): + cflags.append('-msse4.1') + if self._Test('GCC_ENABLE_SSE42_EXTENSIONS', 'YES', default='NO'): + cflags.append('-msse4.2') + + cflags += self._Settings().get('WARNING_CFLAGS', []) + + if self._IsXCTest(): + platform_root = self._XcodePlatformPath(configname) + if platform_root: + cflags.append('-F' + platform_root + '/Developer/Library/Frameworks/') + + 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 + + def GetCflagsC(self, configname): + """Returns flags that need to be added to .c, and .m compilations.""" + self.configname = configname + cflags_c = [] + if self._Settings().get('GCC_C_LANGUAGE_STANDARD', '') == 'ansi': + cflags_c.append('-ansi') + else: + self._Appendf(cflags_c, 'GCC_C_LANGUAGE_STANDARD', '-std=%s') + cflags_c += self._Settings().get('OTHER_CFLAGS', []) + self.configname = None + return cflags_c + + def GetCflagsCC(self, configname): + """Returns flags that need to be added to .cc, and .mm compilations.""" + self.configname = configname + cflags_cc = [] + + clang_cxx_language_standard = self._Settings().get( + 'CLANG_CXX_LANGUAGE_STANDARD') + # Note: Don't make c++0x to c++11 so that c++0x can be used with older + # clangs that don't understand c++11 yet (like Xcode 4.2's). + if clang_cxx_language_standard: + cflags_cc.append('-std=%s' % clang_cxx_language_standard) + + self._Appendf(cflags_cc, 'CLANG_CXX_LIBRARY', '-stdlib=%s') + + if self._Test('GCC_ENABLE_CPP_RTTI', 'NO', default='YES'): + cflags_cc.append('-fno-rtti') + if self._Test('GCC_ENABLE_CPP_EXCEPTIONS', 'NO', default='YES'): + cflags_cc.append('-fno-exceptions') + if self._Test('GCC_INLINES_ARE_PRIVATE_EXTERN', 'YES', default='NO'): + cflags_cc.append('-fvisibility-inlines-hidden') + if self._Test('GCC_THREADSAFE_STATICS', 'NO', default='YES'): + cflags_cc.append('-fno-threadsafe-statics') + # Note: This flag is a no-op for clang, it only has an effect for gcc. + if self._Test('GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO', 'NO', default='YES'): + cflags_cc.append('-Wno-invalid-offsetof') + + other_ccflags = [] + + for flag in self._Settings().get('OTHER_CPLUSPLUSFLAGS', ['$(inherited)']): + # TODO: More general variable expansion. Missing in many other places too. + if flag in ('$inherited', '$(inherited)', '${inherited}'): + flag = '$OTHER_CFLAGS' + if flag in ('$OTHER_CFLAGS', '$(OTHER_CFLAGS)', '${OTHER_CFLAGS}'): + other_ccflags += self._Settings().get('OTHER_CFLAGS', []) + else: + other_ccflags.append(flag) + cflags_cc += other_ccflags + + self.configname = None + return cflags_cc + + def _AddObjectiveCGarbageCollectionFlags(self, flags): + gc_policy = self._Settings().get('GCC_ENABLE_OBJC_GC', 'unsupported') + if gc_policy == 'supported': + flags.append('-fobjc-gc') + elif gc_policy == 'required': + flags.append('-fobjc-gc-only') + + def _AddObjectiveCARCFlags(self, flags): + if self._Test('CLANG_ENABLE_OBJC_ARC', 'YES', default='NO'): + flags.append('-fobjc-arc') + + def _AddObjectiveCMissingPropertySynthesisFlags(self, flags): + if self._Test('CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS', + 'YES', default='NO'): + flags.append('-Wobjc-missing-property-synthesis') + + def GetCflagsObjC(self, configname): + """Returns flags that need to be added to .m compilations.""" + self.configname = configname + cflags_objc = [] + self._AddObjectiveCGarbageCollectionFlags(cflags_objc) + self._AddObjectiveCARCFlags(cflags_objc) + self._AddObjectiveCMissingPropertySynthesisFlags(cflags_objc) + self.configname = None + return cflags_objc + + def GetCflagsObjCC(self, configname): + """Returns flags that need to be added to .mm compilations.""" + self.configname = configname + cflags_objcc = [] + self._AddObjectiveCGarbageCollectionFlags(cflags_objcc) + self._AddObjectiveCARCFlags(cflags_objcc) + self._AddObjectiveCMissingPropertySynthesisFlags(cflags_objcc) + if self._Test('GCC_OBJC_CALL_CXX_CDTORS', 'YES', default='NO'): + cflags_objcc.append('-fobjc-call-cxx-cdtors') + self.configname = None + return cflags_objcc + + def GetInstallNameBase(self): + """Return DYLIB_INSTALL_NAME_BASE for this target.""" + # Xcode sets this for shared_libraries, and for nonbundled loadable_modules. + if (self.spec['type'] != 'shared_library' and + (self.spec['type'] != 'loadable_module' or self._IsBundle())): + return None + install_base = self.GetPerTargetSetting( + 'DYLIB_INSTALL_NAME_BASE', + default='/Library/Frameworks' if self._IsBundle() else '/usr/local/lib') + return install_base + + def _StandardizePath(self, path): + """Do :standardizepath processing for path.""" + # I'm not quite sure what :standardizepath does. Just call normpath(), + # but don't let @executable_path/../foo collapse to foo. + if '/' in path: + prefix, rest = '', path + if path.startswith('@'): + prefix, rest = path.split('/', 1) + rest = os.path.normpath(rest) # :standardizepath + path = os.path.join(prefix, rest) + return path + + def GetInstallName(self): + """Return LD_DYLIB_INSTALL_NAME for this target.""" + # Xcode sets this for shared_libraries, and for nonbundled loadable_modules. + if (self.spec['type'] != 'shared_library' and + (self.spec['type'] != 'loadable_module' or self._IsBundle())): + return None + + default_install_name = \ + '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)' + install_name = self.GetPerTargetSetting( + 'LD_DYLIB_INSTALL_NAME', default=default_install_name) + + # Hardcode support for the variables used in chromium for now, to + # unblock people using the make build. + if '$' in install_name: + assert install_name in ('$(DYLIB_INSTALL_NAME_BASE:standardizepath)/' + '$(WRAPPER_NAME)/$(PRODUCT_NAME)', default_install_name), ( + 'Variables in LD_DYLIB_INSTALL_NAME are not generally supported ' + 'yet in target \'%s\' (got \'%s\')' % + (self.spec['target_name'], install_name)) + + install_name = install_name.replace( + '$(DYLIB_INSTALL_NAME_BASE:standardizepath)', + self._StandardizePath(self.GetInstallNameBase())) + if self._IsBundle(): + # These are only valid for bundles, hence the |if|. + install_name = install_name.replace( + '$(WRAPPER_NAME)', self.GetWrapperName()) + install_name = install_name.replace( + '$(PRODUCT_NAME)', self.GetProductName()) + else: + assert '$(WRAPPER_NAME)' not in install_name + assert '$(PRODUCT_NAME)' not in install_name + + install_name = install_name.replace( + '$(EXECUTABLE_PATH)', self.GetExecutablePath()) + return install_name + + def _MapLinkerFlagFilename(self, ldflag, gyp_to_build_path): + """Checks if ldflag contains a filename and if so remaps it from + gyp-directory-relative to build-directory-relative.""" + # This list is expanded on demand. + # They get matched as: + # -exported_symbols_list file + # -Wl,exported_symbols_list file + # -Wl,exported_symbols_list,file + LINKER_FILE = r'(\S+)' + WORD = r'\S+' + linker_flags = [ + ['-exported_symbols_list', LINKER_FILE], # Needed for NaCl. + ['-unexported_symbols_list', LINKER_FILE], + ['-reexported_symbols_list', LINKER_FILE], + ['-sectcreate', WORD, WORD, LINKER_FILE], # Needed for remoting. + ] + for flag_pattern in linker_flags: + regex = re.compile('(?:-Wl,)?' + '[ ,]'.join(flag_pattern)) + m = regex.match(ldflag) + if m: + ldflag = ldflag[:m.start(1)] + gyp_to_build_path(m.group(1)) + \ + ldflag[m.end(1):] + # Required for ffmpeg (no idea why they don't use LIBRARY_SEARCH_PATHS, + # TODO(thakis): Update ffmpeg.gyp): + if ldflag.startswith('-L'): + ldflag = '-L' + gyp_to_build_path(ldflag[len('-L'):]) + return ldflag + + def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None): + """Returns flags that need to be passed to the linker. + + Args: + configname: The name of the configuration to get ld flags for. + product_dir: The directory where products such static and dynamic + libraries are placed. This is added to the library search path. + gyp_to_build_path: A function that converts paths relative to the + current gyp file to paths relative to the build direcotry. + """ + self.configname = configname + ldflags = [] + + # The xcode build is relative to a gyp file's directory, and OTHER_LDFLAGS + # can contain entries that depend on this. Explicitly absolutify these. + for ldflag in self._Settings().get('OTHER_LDFLAGS', []): + ldflags.append(self._MapLinkerFlagFilename(ldflag, gyp_to_build_path)) + + if self._Test('DEAD_CODE_STRIPPING', 'YES', default='NO'): + ldflags.append('-Wl,-dead_strip') + + if self._Test('PREBINDING', 'YES', default='NO'): + ldflags.append('-Wl,-prebind') + + self._Appendf( + ldflags, 'DYLIB_COMPATIBILITY_VERSION', '-compatibility_version %s') + self._Appendf( + ldflags, 'DYLIB_CURRENT_VERSION', '-current_version %s') + + self._AppendPlatformVersionMinFlags(ldflags) + + if 'SDKROOT' in self._Settings() and self._SdkPath(): + ldflags.append('-isysroot ' + self._SdkPath()) + + for library_path in self._Settings().get('LIBRARY_SEARCH_PATHS', []): + ldflags.append('-L' + gyp_to_build_path(library_path)) + + if 'ORDER_FILE' in self._Settings(): + ldflags.append('-Wl,-order_file ' + + '-Wl,' + gyp_to_build_path( + self._Settings()['ORDER_FILE'])) + + if arch is not None: + archs = [arch] + else: + assert self.configname + archs = self.GetActiveArchs(self.configname) + if len(archs) != 1: + # TODO: Supporting fat binaries will be annoying. + self._WarnUnimplemented('ARCHS') + archs = ['i386'] + ldflags.append('-arch ' + archs[0]) + + # Xcode adds the product directory by default. + ldflags.append('-L' + product_dir) + + install_name = self.GetInstallName() + if install_name and self.spec['type'] != 'loadable_module': + ldflags.append('-install_name ' + install_name.replace(' ', r'\ ')) + + for rpath in self._Settings().get('LD_RUNPATH_SEARCH_PATHS', []): + ldflags.append('-Wl,-rpath,' + rpath) + + 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)) + + if self._IsXCTest(): + platform_root = self._XcodePlatformPath(configname) + if platform_root: + cflags.append('-F' + platform_root + '/Developer/Library/Frameworks/') + + is_extension = self._IsIosAppExtension() or self._IsIosWatchKitExtension() + if sdk_root and is_extension: + # Adds the link flags for extensions. These flags are common for all + # extensions and provide loader and main function. + # These flags reflect the compilation options used by xcode to compile + # extensions. + ldflags.append('-lpkstart') + if XcodeVersion() < '0900': + ldflags.append(sdk_root + + '/System/Library/PrivateFrameworks/PlugInKit.framework/PlugInKit') + ldflags.append('-fapplication-extension') + ldflags.append('-Xlinker -rpath ' + '-Xlinker @executable_path/../../Frameworks') + + self._Appendf(ldflags, 'CLANG_CXX_LIBRARY', '-stdlib=%s') + + self.configname = None + return ldflags + + def GetLibtoolflags(self, configname): + """Returns flags that need to be passed to the static linker. + + Args: + configname: The name of the configuration to get ld flags for. + """ + self.configname = configname + libtoolflags = [] + + for libtoolflag in self._Settings().get('OTHER_LDFLAGS', []): + libtoolflags.append(libtoolflag) + # TODO(thakis): ARCHS? + + self.configname = None + return libtoolflags + + def GetPerTargetSettings(self): + """Gets a list of all the per-target settings. This will only fetch keys + whose values are the same across all configurations.""" + first_pass = True + result = {} + for configname in sorted(self.xcode_settings.keys()): + if first_pass: + result = dict(self.xcode_settings[configname]) + first_pass = False + else: + for key, value in self.xcode_settings[configname].iteritems(): + if key not in result: + continue + elif result[key] != value: + del result[key] + return result + + def GetPerConfigSetting(self, setting, configname, default=None): + if configname in self.xcode_settings: + return self.xcode_settings[configname].get(setting, default) + else: + return self.GetPerTargetSetting(setting, default) + + def GetPerTargetSetting(self, setting, default=None): + """Tries to get xcode_settings.setting from spec. Assumes that the setting + has the same value in all configurations and throws otherwise.""" + is_first_pass = True + result = None + for configname in sorted(self.xcode_settings.keys()): + if is_first_pass: + result = self.xcode_settings[configname].get(setting, None) + is_first_pass = False + else: + assert result == self.xcode_settings[configname].get(setting, None), ( + "Expected per-target setting for '%s', got per-config setting " + "(target %s)" % (setting, self.spec['target_name'])) + if result is None: + return default + return result + + def _GetStripPostbuilds(self, configname, output_binary, quiet): + """Returns a list of shell commands that contain the shell commands + neccessary to strip this target's binary. These should be run as postbuilds + before the actual postbuilds run.""" + self.configname = configname + + result = [] + if (self._Test('DEPLOYMENT_POSTPROCESSING', 'YES', default='NO') and + self._Test('STRIP_INSTALLED_PRODUCT', 'YES', default='NO')): + + default_strip_style = 'debugging' + if self.spec['type'] == 'loadable_module' and self._IsBundle(): + default_strip_style = 'non-global' + elif self.spec['type'] == 'executable': + default_strip_style = 'all' + + strip_style = self._Settings().get('STRIP_STYLE', default_strip_style) + strip_flags = { + 'all': '', + 'non-global': '-x', + 'debugging': '-S', + }[strip_style] + + explicit_strip_flags = self._Settings().get('STRIPFLAGS', '') + if explicit_strip_flags: + strip_flags += ' ' + _NormalizeEnvVarReferences(explicit_strip_flags) + + if not quiet: + result.append('echo STRIP\\(%s\\)' % self.spec['target_name']) + result.append('strip %s %s' % (strip_flags, output_binary)) + + self.configname = None + return result + + def _GetDebugInfoPostbuilds(self, configname, output, output_binary, quiet): + """Returns a list of shell commands that contain the shell commands + neccessary to massage this target's debug information. These should be run + as postbuilds before the actual postbuilds run.""" + self.configname = configname + + # For static libraries, no dSYMs are created. + result = [] + if (self._Test('GCC_GENERATE_DEBUGGING_SYMBOLS', 'YES', default='YES') and + self._Test( + 'DEBUG_INFORMATION_FORMAT', 'dwarf-with-dsym', default='dwarf') and + self.spec['type'] != 'static_library'): + if not quiet: + result.append('echo DSYMUTIL\\(%s\\)' % self.spec['target_name']) + result.append('dsymutil %s -o %s' % (output_binary, output + '.dSYM')) + + self.configname = None + return result + + def _GetTargetPostbuilds(self, configname, output, output_binary, + quiet=False): + """Returns a list of shell commands that contain the shell commands + to run as postbuilds for this target, before the actual postbuilds.""" + # dSYMs need to build before stripping happens. + return ( + self._GetDebugInfoPostbuilds(configname, output, output_binary, quiet) + + self._GetStripPostbuilds(configname, output_binary, quiet)) + + def _GetIOSPostbuilds(self, configname, output_binary): + """Return a shell command to codesign the iOS output binary so it can + be deployed to a device. This should be run as the very last step of the + build.""" + if not (self.isIOS and self.spec['type'] == 'executable'): + return [] + + 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: + 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): + """Returns a list of shell commands that should run before and after + |postbuilds|.""" + assert output_binary is not None + pre = self._GetTargetPostbuilds(configname, output, output_binary, quiet) + post = self._GetIOSPostbuilds(configname, output_binary) + return pre + postbuilds + post + + def _AdjustLibrary(self, library, config_name=None): + if library.endswith('.framework'): + l = '-framework ' + os.path.splitext(os.path.basename(library))[0] + else: + m = self.library_re.match(library) + if m: + l = '-l' + m.group(1) + else: + l = library + + sdk_root = self._SdkPath(config_name) + if not sdk_root: + sdk_root = '' + # Xcode 7 started shipping with ".tbd" (text based stubs) files instead of + # ".dylib" without providing a real support for them. What it does, for + # "/usr/lib" libraries, is do "-L/usr/lib -lname" which is dependent on the + # library order and cause collision when building Chrome. + # + # Instead substitude ".tbd" to ".dylib" in the generated project when the + # following conditions are both true: + # - library is referenced in the gyp file as "$(SDKROOT)/**/*.dylib", + # - the ".dylib" file does not exists but a ".tbd" file do. + library = l.replace('$(SDKROOT)', sdk_root) + if l.startswith('$(SDKROOT)'): + basename, ext = os.path.splitext(library) + if ext == '.dylib' and not os.path.exists(library): + tbd_library = basename + '.tbd' + if os.path.exists(tbd_library): + library = tbd_library + return library + + def AdjustLibraries(self, libraries, config_name=None): + """Transforms entries like 'Cocoa.framework' in libraries into entries like + '-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc. + """ + libraries = [self._AdjustLibrary(library, config_name) + for library in libraries] + return libraries + + def _BuildMachineOSBuild(self): + return GetStdout(['sw_vers', '-buildVersion']) + + def _XcodeIOSDeviceFamily(self, configname): + family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1') + return [int(x) for x in family.split(',')] + + def GetExtraPlistItems(self, configname=None): + """Returns a dictionary with extra items to insert into Info.plist.""" + if configname not in XcodeSettings._plist_cache: + cache = {} + cache['BuildMachineOSBuild'] = self._BuildMachineOSBuild() + + xcode, xcode_build = XcodeVersion() + cache['DTXcode'] = xcode + 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( + sdk_root, 'ProductBuildVersion') + else: + cache['DTSDKBuild'] = cache['BuildMachineOSBuild'] + + if self.isIOS: + cache['DTPlatformName'] = cache['DTSDKName'] + if configname.endswith("iphoneos"): + cache['DTPlatformVersion'] = self._GetSdkVersionInfoItem( + sdk_root, 'ProductVersion') + cache['CFBundleSupportedPlatforms'] = ['iPhoneOS'] + else: + cache['CFBundleSupportedPlatforms'] = ['iPhoneSimulator'] + XcodeSettings._plist_cache[configname] = cache + + # Include extra plist items that are per-target, not per global + # XcodeSettings. + items = dict(XcodeSettings._plist_cache[configname]) + if self.isIOS: + 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. + """ + xcode_version, xcode_build = XcodeVersion() + if xcode_version < '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 = 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 '' + + +class MacPrefixHeader(object): + """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature. + + This feature consists of several pieces: + * If GCC_PREFIX_HEADER is present, all compilations in that project get an + additional |-include path_to_prefix_header| cflag. + * If GCC_PRECOMPILE_PREFIX_HEADER is present too, then the prefix header is + instead compiled, and all other compilations in the project get an + additional |-include path_to_compiled_header| instead. + + Compiled prefix headers have the extension gch. There is one gch file for + every language used in the project (c, cc, m, mm), since gch files for + different languages aren't compatible. + + gch files themselves are built with the target's normal cflags, but they + obviously don't get the |-include| flag. Instead, they need a -x flag that + describes their language. + + All o files in the target need to depend on the gch file, to make sure + it's built before any o file is built. + + This class helps with some of these tasks, but it needs help from the build + system for writing dependencies to the gch files, for writing build commands + for the gch files, and for figuring out the location of the gch files. + """ + def __init__(self, xcode_settings, + gyp_path_to_build_path, gyp_path_to_build_output): + """If xcode_settings is None, all methods on this class are no-ops. + + Args: + gyp_path_to_build_path: A function that takes a gyp-relative path, + and returns a path relative to the build directory. + gyp_path_to_build_output: A function that takes a gyp-relative path and + a language code ('c', 'cc', 'm', or 'mm'), and that returns a path + to where the output of precompiling that path for that language + should be placed (without the trailing '.gch'). + """ + # This doesn't support per-configuration prefix headers. Good enough + # for now. + self.header = None + self.compile_headers = False + if xcode_settings: + self.header = xcode_settings.GetPerTargetSetting('GCC_PREFIX_HEADER') + self.compile_headers = xcode_settings.GetPerTargetSetting( + 'GCC_PRECOMPILE_PREFIX_HEADER', default='NO') != 'NO' + self.compiled_headers = {} + if self.header: + if self.compile_headers: + for lang in ['c', 'cc', 'm', 'mm']: + self.compiled_headers[lang] = gyp_path_to_build_output( + self.header, lang) + self.header = gyp_path_to_build_path(self.header) + + def _CompiledHeader(self, lang, arch): + assert self.compile_headers + h = self.compiled_headers[lang] + if arch: + h += '.' + arch + return h + + def GetInclude(self, lang, arch=None): + """Gets the cflags to include the prefix header for language |lang|.""" + if self.compile_headers and lang in self.compiled_headers: + return '-include %s' % self._CompiledHeader(lang, arch) + elif self.header: + return '-include %s' % self.header + else: + return '' + + def _Gch(self, lang, arch): + """Returns the actual file name of the prefix header for language |lang|.""" + assert self.compile_headers + return self._CompiledHeader(lang, arch) + '.gch' + + def GetObjDependencies(self, sources, objs, arch=None): + """Given a list of source files and the corresponding object files, returns + a list of (source, object, gch) tuples, where |gch| is the build-directory + relative path to the gch file each object file depends on. |compilable[i]| + has to be the source file belonging to |objs[i]|.""" + if not self.header or not self.compile_headers: + return [] + + result = [] + for source, obj in zip(sources, objs): + ext = os.path.splitext(source)[1] + lang = { + '.c': 'c', + '.cpp': 'cc', '.cc': 'cc', '.cxx': 'cc', + '.m': 'm', + '.mm': 'mm', + }.get(ext, None) + if lang: + result.append((source, obj, self._Gch(lang, arch))) + return result + + def GetPchBuildCommands(self, arch=None): + """Returns [(path_to_gch, language_flag, language, header)]. + |path_to_gch| and |header| are relative to the build directory. + """ + if not self.header or not self.compile_headers: + return [] + return [ + (self._Gch('c', arch), '-x c-header', 'c', self.header), + (self._Gch('cc', arch), '-x c++-header', 'cc', self.header), + (self._Gch('m', arch), '-x objective-c-header', 'm', self.header), + (self._Gch('mm', arch), '-x objective-c++-header', 'mm', self.header), + ] + + +def XcodeVersion(): + """Returns a tuple of version and build version of installed Xcode.""" + # `xcodebuild -version` output looks like + # Xcode 4.6.3 + # Build version 4H1503 + # or like + # Xcode 3.2.6 + # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0 + # BuildVersion: 10M2518 + # Convert that to '0463', '4H1503'. + global XCODE_VERSION_CACHE + if XCODE_VERSION_CACHE: + return XCODE_VERSION_CACHE + try: + version_list = GetStdoutQuiet(['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 = CLTVersion() + if version: + version = re.match(r'(\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] + XCODE_VERSION_CACHE = (version, build) + return XCODE_VERSION_CACHE + + +# This function ported from the logic in Homebrew's CLT version check +def CLTVersion(): + """Returns the version of command-line tools from pkgutil.""" + # 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.+)') + for key in [MAVERICKS_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID]: + try: + output = GetStdout(['/usr/sbin/pkgutil', '--pkg-info', key]) + return re.search(regex, output).groupdict()['version'] + except: + continue + + +def GetStdoutQuiet(cmdlist): + """Returns the content of standard output returned by invoking |cmdlist|. + Ignores the stderr. + Raises |GypError| if the command return with a non-zero return code.""" + job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out = job.communicate()[0] + if job.returncode != 0: + raise GypError('Error %d running %s' % (job.returncode, cmdlist[0])) + return out.rstrip('\n') + + +def GetStdout(cmdlist): + """Returns the content of standard output returned by invoking |cmdlist|. + Raises |GypError| if the command return with a non-zero return code.""" + job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE) + out = job.communicate()[0] + if job.returncode != 0: + sys.stderr.write(out + '\n') + raise GypError('Error %d running %s' % (job.returncode, cmdlist[0])) + return out.rstrip('\n') + + +def MergeGlobalXcodeSettingsToSpec(global_dict, spec): + """Merges the global xcode_settings dictionary into each configuration of the + target represented by spec. For keys that are both in the global and the local + xcode_settings dict, the local key gets precendence. + """ + # The xcode generator special-cases global xcode_settings and does something + # that amounts to merging in the global xcode_settings into each local + # xcode_settings dict. + global_xcode_settings = global_dict.get('xcode_settings', {}) + for config in spec['configurations'].values(): + if 'xcode_settings' in config: + new_settings = global_xcode_settings.copy() + new_settings.update(config['xcode_settings']) + config['xcode_settings'] = new_settings + + +def IsMacBundle(flavor, spec): + """Returns if |spec| should be treated as a bundle. + + Bundles are directories with a certain subdirectory structure, instead of + just a single file. Bundle rules do not produce a binary but also package + resources into that directory.""" + is_mac_bundle = (int(spec.get('mac_bundle', 0)) != 0 and flavor == 'mac') + if is_mac_bundle: + assert spec['type'] != 'none', ( + 'mac_bundle targets cannot have type none (target "%s")' % + spec['target_name']) + return is_mac_bundle + + +def GetMacBundleResources(product_dir, xcode_settings, resources): + """Yields (output, resource) pairs for every resource in |resources|. + Only call this for mac bundle targets. + + Args: + product_dir: Path to the directory containing the output bundle, + relative to the build directory. + xcode_settings: The XcodeSettings of the current target. + resources: A list of bundle resources, relative to the build directory. + """ + dest = os.path.join(product_dir, + xcode_settings.GetBundleResourceFolder()) + for res in resources: + output = dest + + # The make generator doesn't support it, so forbid it everywhere + # to keep the generators more interchangable. + assert ' ' not in res, ( + "Spaces in resource filenames not supported (%s)" % res) + + # Split into (path,file). + res_parts = os.path.split(res) + + # Now split the path into (prefix,maybe.lproj). + lproj_parts = os.path.split(res_parts[0]) + # If the resource lives in a .lproj bundle, add that to the destination. + if lproj_parts[1].endswith('.lproj'): + output = os.path.join(output, lproj_parts[1]) + + output = os.path.join(output, res_parts[1]) + # Compiled XIB files are referred to by .nib. + if output.endswith('.xib'): + output = os.path.splitext(output)[0] + '.nib' + # Compiled storyboard files are referred to by .storyboardc. + if output.endswith('.storyboard'): + output = os.path.splitext(output)[0] + '.storyboardc' + + yield output, res + + +def GetMacInfoPlist(product_dir, xcode_settings, gyp_path_to_build_path): + """Returns (info_plist, dest_plist, defines, extra_env), where: + * |info_plist| is the source plist path, relative to the + build directory, + * |dest_plist| is the destination plist path, relative to the + build directory, + * |defines| is a list of preprocessor defines (empty if the plist + shouldn't be preprocessed, + * |extra_env| is a dict of env variables that should be exported when + invoking |mac_tool copy-info-plist|. + + Only call this for mac bundle targets. + + Args: + product_dir: Path to the directory containing the output bundle, + relative to the build directory. + xcode_settings: The XcodeSettings of the current target. + gyp_to_build_path: A function that converts paths relative to the + current gyp file to paths relative to the build direcotry. + """ + info_plist = xcode_settings.GetPerTargetSetting('INFOPLIST_FILE') + if not info_plist: + return None, None, [], {} + + # The make generator doesn't support it, so forbid it everywhere + # to keep the generators more interchangable. + assert ' ' not in info_plist, ( + "Spaces in Info.plist filenames not supported (%s)" % info_plist) + + info_plist = gyp_path_to_build_path(info_plist) + + # If explicitly set to preprocess the plist, invoke the C preprocessor and + # specify any defines as -D flags. + if xcode_settings.GetPerTargetSetting( + 'INFOPLIST_PREPROCESS', default='NO') == 'YES': + # Create an intermediate file based on the path. + defines = shlex.split(xcode_settings.GetPerTargetSetting( + 'INFOPLIST_PREPROCESSOR_DEFINITIONS', default='')) + else: + defines = [] + + dest_plist = os.path.join(product_dir, xcode_settings.GetBundlePlistPath()) + extra_env = xcode_settings.GetPerTargetSettings() + + return info_plist, dest_plist, defines, extra_env + + +def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, + additional_settings=None): + """Return the environment variables that Xcode would set. See + http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW153 + for a full list. + + Args: + xcode_settings: An XcodeSettings object. If this is None, this function + returns an empty dict. + built_products_dir: Absolute path to the built products dir. + srcroot: Absolute path to the source root. + configuration: The build configuration name. + additional_settings: An optional dict with more values to add to the + result. + """ + if not xcode_settings: return {} + + # This function is considered a friend of XcodeSettings, so let it reach into + # its implementation details. + spec = xcode_settings.spec + + # These are filled in on a as-needed basis. + env = { + 'BUILT_FRAMEWORKS_DIR' : built_products_dir, + 'BUILT_PRODUCTS_DIR' : built_products_dir, + 'CONFIGURATION' : configuration, + 'PRODUCT_NAME' : xcode_settings.GetProductName(), + # See /Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX\ Product\ Types.xcspec for FULL_PRODUCT_NAME + 'SRCROOT' : srcroot, + 'SOURCE_ROOT': '${SRCROOT}', + # This is not true for static libraries, but currently the env is only + # written for bundles: + 'TARGET_BUILD_DIR' : built_products_dir, + 'TEMP_DIR' : '${TMPDIR}', + } + if xcode_settings.GetPerConfigSetting('SDKROOT', configuration): + env['SDKROOT'] = xcode_settings._SdkPath(configuration) + else: + env['SDKROOT'] = '' + + if spec['type'] in ( + 'executable', 'static_library', 'shared_library', 'loadable_module'): + env['EXECUTABLE_NAME'] = xcode_settings.GetExecutableName() + env['EXECUTABLE_PATH'] = xcode_settings.GetExecutablePath() + env['FULL_PRODUCT_NAME'] = xcode_settings.GetFullProductName() + mach_o_type = xcode_settings.GetMachOType() + if mach_o_type: + env['MACH_O_TYPE'] = mach_o_type + env['PRODUCT_TYPE'] = xcode_settings.GetProductType() + if xcode_settings._IsBundle(): + env['CONTENTS_FOLDER_PATH'] = \ + xcode_settings.GetBundleContentsFolderPath() + env['UNLOCALIZED_RESOURCES_FOLDER_PATH'] = \ + xcode_settings.GetBundleResourceFolder() + env['INFOPLIST_PATH'] = xcode_settings.GetBundlePlistPath() + env['WRAPPER_NAME'] = xcode_settings.GetWrapperName() + + install_name = xcode_settings.GetInstallName() + if install_name: + env['LD_DYLIB_INSTALL_NAME'] = install_name + install_name_base = xcode_settings.GetInstallNameBase() + if install_name_base: + env['DYLIB_INSTALL_NAME_BASE'] = install_name_base + if XcodeVersion() >= '0500' and not env.get('SDKROOT'): + sdk_root = xcode_settings._SdkRoot(configuration) + if not sdk_root: + sdk_root = xcode_settings._XcodeSdkPath('') + if sdk_root is None: + sdk_root = '' + env['SDKROOT'] = sdk_root + + if not additional_settings: + additional_settings = {} + else: + # Flatten lists to strings. + for k in additional_settings: + if not isinstance(additional_settings[k], str): + additional_settings[k] = ' '.join(additional_settings[k]) + additional_settings.update(env) + + for k in additional_settings: + additional_settings[k] = _NormalizeEnvVarReferences(additional_settings[k]) + + return additional_settings + + +def _NormalizeEnvVarReferences(str): + """Takes a string containing variable references in the form ${FOO}, $(FOO), + or $FOO, and returns a string with all variable references in the form ${FOO}. + """ + # $FOO -> ${FOO} + str = re.sub(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', r'${\1}', str) + + # $(FOO) -> ${FOO} + matches = re.findall(r'(\$\(([a-zA-Z0-9\-_]+)\))', str) + for match in matches: + to_replace, variable = match + assert '$(' not in match, '$($(FOO)) variables not supported: ' + match + str = str.replace(to_replace, '${' + variable + '}') + + return str + + +def ExpandEnvVars(string, expansions): + """Expands ${VARIABLES}, $(VARIABLES), and $VARIABLES in string per the + expansions list. If the variable expands to something that references + another variable, this variable is expanded as well if it's in env -- + until no variables present in env are left.""" + for k, v in reversed(expansions): + string = string.replace('${' + k + '}', v) + string = string.replace('$(' + k + ')', v) + string = string.replace('$' + k, v) + return string + + +def _TopologicallySortedEnvVarKeys(env): + """Takes a dict |env| whose values are strings that can refer to other keys, + for example env['foo'] = '$(bar) and $(baz)'. Returns a list L of all keys of + env such that key2 is after key1 in L if env[key2] refers to env[key1]. + + Throws an Exception in case of dependency cycles. + """ + # Since environment variables can refer to other variables, the evaluation + # order is important. Below is the logic to compute the dependency graph + # and sort it. + regex = re.compile(r'\$\{([a-zA-Z0-9\-_]+)\}') + def GetEdges(node): + # Use a definition of edges such that user_of_variable -> used_varible. + # This happens to be easier in this case, since a variable's + # definition contains all variables it references in a single string. + # We can then reverse the result of the topological sort at the end. + # Since: reverse(topsort(DAG)) = topsort(reverse_edges(DAG)) + matches = set([v for v in regex.findall(env[node]) if v in env]) + for dependee in matches: + assert '${' not in dependee, 'Nested variables not supported: ' + dependee + return matches + + try: + # Topologically sort, and then reverse, because we used an edge definition + # that's inverted from the expected result of this function (see comment + # above). + order = gyp.common.TopologicallySorted(env.keys(), GetEdges) + order.reverse() + return order + except gyp.common.CycleError, e: + raise GypError( + 'Xcode environment variables are cyclically dependent: ' + str(e.nodes)) + + +def GetSortedXcodeEnv(xcode_settings, built_products_dir, srcroot, + configuration, additional_settings=None): + env = _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, + additional_settings) + return [(key, env[key]) for key in _TopologicallySortedEnvVarKeys(env)] + + +def GetSpecPostbuildCommands(spec, quiet=False): + """Returns the list of postbuilds explicitly defined on |spec|, in a form + executable by a shell.""" + postbuilds = [] + for postbuild in spec.get('postbuilds', []): + if not quiet: + postbuilds.append('echo POSTBUILD\\(%s\\) %s' % ( + spec['target_name'], postbuild['postbuild_name'])) + postbuilds.append(gyp.common.EncodePOSIXShellList(postbuild['action'])) + return postbuilds + + +def _HasIOSTarget(targets): + """Returns true if any target contains the iOS specific key + IPHONEOS_DEPLOYMENT_TARGET.""" + for target_dict in targets.values(): + for config in target_dict['configurations'].values(): + if config.get('xcode_settings', {}).get('IPHONEOS_DEPLOYMENT_TARGET'): + return True + return False + + +def _AddIOSDeviceConfigurations(targets): + """Clone all targets and append -iphoneos to the name. Configure these targets + to build for iOS devices and use correct architectures for those builds.""" + for target_dict in targets.itervalues(): + toolset = target_dict['toolset'] + configs = target_dict['configurations'] + for config_name, config_dict in dict(configs).iteritems(): + iphoneos_config_dict = copy.deepcopy(config_dict) + configs[config_name + '-iphoneos'] = iphoneos_config_dict + configs[config_name + '-iphonesimulator'] = config_dict + if toolset == 'target': + iphoneos_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' + return targets + +def CloneConfigurationForDeviceAndEmulator(target_dicts): + """If |target_dicts| contains any iOS targets, automatically create -iphoneos + targets for iOS device builds.""" + if _HasIOSTarget(target_dicts): + return _AddIOSDeviceConfigurations(target_dicts) + return target_dicts diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py new file mode 100644 index 0000000000000..3820d6bf04817 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py @@ -0,0 +1,270 @@ +# Copyright (c) 2014 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. + +"""Xcode-ninja wrapper project file generator. + +This updates the data structures passed to the Xcode gyp generator to build +with ninja instead. The Xcode project itself is transformed into a list of +executable targets, each with a build step to build with ninja, and a target +with every source and resource file. This appears to sidestep some of the +major performance headaches experienced using complex projects and large number +of targets within Xcode. +""" + +import errno +import gyp.generator.ninja +import os +import re +import xml.sax.saxutils + + +def _WriteWorkspace(main_gyp, sources_gyp, params): + """ Create a workspace to wrap main and sources gyp paths. """ + (build_file_root, build_file_ext) = os.path.splitext(main_gyp) + workspace_path = build_file_root + '.xcworkspace' + options = params['options'] + if options.generator_output: + workspace_path = os.path.join(options.generator_output, workspace_path) + try: + os.makedirs(workspace_path) + except OSError, e: + if e.errno != errno.EEXIST: + raise + output_string = '\n' + \ + '\n' + for gyp_name in [main_gyp, sources_gyp]: + name = os.path.splitext(os.path.basename(gyp_name))[0] + '.xcodeproj' + name = xml.sax.saxutils.quoteattr("group:" + name) + output_string += ' \n' % name + output_string += '\n' + + workspace_file = os.path.join(workspace_path, "contents.xcworkspacedata") + + try: + with open(workspace_file, 'r') as input_file: + input_string = input_file.read() + if input_string == output_string: + return + except IOError: + # Ignore errors if the file doesn't exist. + pass + + with open(workspace_file, 'w') as output_file: + output_file.write(output_string) + +def _TargetFromSpec(old_spec, params): + """ Create fake target for xcode-ninja wrapper. """ + # Determine ninja top level build dir (e.g. /path/to/out). + ninja_toplevel = None + jobs = 0 + if params: + options = params['options'] + ninja_toplevel = \ + os.path.join(options.toplevel_dir, + gyp.generator.ninja.ComputeOutputDir(params)) + jobs = params.get('generator_flags', {}).get('xcode_ninja_jobs', 0) + + target_name = old_spec.get('target_name') + product_name = old_spec.get('product_name', target_name) + product_extension = old_spec.get('product_extension') + + ninja_target = {} + ninja_target['target_name'] = target_name + ninja_target['product_name'] = product_name + if product_extension: + ninja_target['product_extension'] = product_extension + ninja_target['toolset'] = old_spec.get('toolset') + ninja_target['default_configuration'] = old_spec.get('default_configuration') + ninja_target['configurations'] = {} + + # Tell Xcode to look in |ninja_toplevel| for build products. + new_xcode_settings = {} + if ninja_toplevel: + new_xcode_settings['CONFIGURATION_BUILD_DIR'] = \ + "%s/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" % ninja_toplevel + + if 'configurations' in old_spec: + for config in old_spec['configurations'].iterkeys(): + old_xcode_settings = \ + old_spec['configurations'][config].get('xcode_settings', {}) + if 'IPHONEOS_DEPLOYMENT_TARGET' in old_xcode_settings: + new_xcode_settings['CODE_SIGNING_REQUIRED'] = "NO" + new_xcode_settings['IPHONEOS_DEPLOYMENT_TARGET'] = \ + old_xcode_settings['IPHONEOS_DEPLOYMENT_TARGET'] + ninja_target['configurations'][config] = {} + ninja_target['configurations'][config]['xcode_settings'] = \ + new_xcode_settings + + ninja_target['mac_bundle'] = old_spec.get('mac_bundle', 0) + ninja_target['ios_app_extension'] = old_spec.get('ios_app_extension', 0) + ninja_target['ios_watchkit_extension'] = \ + old_spec.get('ios_watchkit_extension', 0) + ninja_target['ios_watchkit_app'] = old_spec.get('ios_watchkit_app', 0) + ninja_target['type'] = old_spec['type'] + if ninja_toplevel: + ninja_target['actions'] = [ + { + 'action_name': 'Compile and copy %s via ninja' % target_name, + 'inputs': [], + 'outputs': [], + 'action': [ + 'env', + 'PATH=%s' % os.environ['PATH'], + 'ninja', + '-C', + new_xcode_settings['CONFIGURATION_BUILD_DIR'], + target_name, + ], + 'message': 'Compile and copy %s via ninja' % target_name, + }, + ] + if jobs > 0: + ninja_target['actions'][0]['action'].extend(('-j', jobs)) + return ninja_target + +def IsValidTargetForWrapper(target_extras, executable_target_pattern, spec): + """Limit targets for Xcode wrapper. + + Xcode sometimes performs poorly with too many targets, so only include + proper executable targets, with filters to customize. + Arguments: + target_extras: Regular expression to always add, matching any target. + executable_target_pattern: Regular expression limiting executable targets. + spec: Specifications for target. + """ + target_name = spec.get('target_name') + # Always include targets matching target_extras. + if target_extras is not None and re.search(target_extras, target_name): + return True + + # Otherwise just show executable targets. + if spec.get('type', '') == 'executable' and \ + spec.get('product_extension', '') != 'bundle': + + # If there is a filter and the target does not match, exclude the target. + if executable_target_pattern is not None: + if not re.search(executable_target_pattern, target_name): + return False + return True + return False + +def CreateWrapper(target_list, target_dicts, data, params): + """Initialize targets for the ninja wrapper. + + This sets up the necessary variables in the targets to generate Xcode projects + that use ninja as an external builder. + Arguments: + target_list: List of target pairs: 'base/base.gyp:base'. + target_dicts: Dict of target properties keyed on target pair. + data: Dict of flattened build files keyed on gyp path. + params: Dict of global options for gyp. + """ + orig_gyp = params['build_files'][0] + for gyp_name, gyp_dict in data.iteritems(): + if gyp_name == orig_gyp: + depth = gyp_dict['_DEPTH'] + + # Check for custom main gyp name, otherwise use the default CHROMIUM_GYP_FILE + # and prepend .ninja before the .gyp extension. + generator_flags = params.get('generator_flags', {}) + main_gyp = generator_flags.get('xcode_ninja_main_gyp', None) + if main_gyp is None: + (build_file_root, build_file_ext) = os.path.splitext(orig_gyp) + main_gyp = build_file_root + ".ninja" + build_file_ext + + # Create new |target_list|, |target_dicts| and |data| data structures. + new_target_list = [] + new_target_dicts = {} + new_data = {} + + # Set base keys needed for |data|. + new_data[main_gyp] = {} + new_data[main_gyp]['included_files'] = [] + new_data[main_gyp]['targets'] = [] + new_data[main_gyp]['xcode_settings'] = \ + data[orig_gyp].get('xcode_settings', {}) + + # Normally the xcode-ninja generator includes only valid executable targets. + # If |xcode_ninja_executable_target_pattern| is set, that list is reduced to + # executable targets that match the pattern. (Default all) + executable_target_pattern = \ + generator_flags.get('xcode_ninja_executable_target_pattern', None) + + # For including other non-executable targets, add the matching target name + # to the |xcode_ninja_target_pattern| regular expression. (Default none) + target_extras = generator_flags.get('xcode_ninja_target_pattern', None) + + for old_qualified_target in target_list: + spec = target_dicts[old_qualified_target] + if IsValidTargetForWrapper(target_extras, executable_target_pattern, spec): + # Add to new_target_list. + target_name = spec.get('target_name') + new_target_name = '%s:%s#target' % (main_gyp, target_name) + new_target_list.append(new_target_name) + + # Add to new_target_dicts. + new_target_dicts[new_target_name] = _TargetFromSpec(spec, params) + + # Add to new_data. + for old_target in data[old_qualified_target.split(':')[0]]['targets']: + if old_target['target_name'] == target_name: + new_data_target = {} + new_data_target['target_name'] = old_target['target_name'] + new_data_target['toolset'] = old_target['toolset'] + new_data[main_gyp]['targets'].append(new_data_target) + + # Create sources target. + sources_target_name = 'sources_for_indexing' + sources_target = _TargetFromSpec( + { 'target_name' : sources_target_name, + 'toolset': 'target', + 'default_configuration': 'Default', + 'mac_bundle': '0', + 'type': 'executable' + }, None) + + # Tell Xcode to look everywhere for headers. + sources_target['configurations'] = {'Default': { 'include_dirs': [ depth ] } } + + sources = [] + for target, target_dict in target_dicts.iteritems(): + base = os.path.dirname(target) + files = target_dict.get('sources', []) + \ + target_dict.get('mac_bundle_resources', []) + for action in target_dict.get('actions', []): + files.extend(action.get('inputs', [])) + # Remove files starting with $. These are mostly intermediate files for the + # build system. + files = [ file for file in files if not file.startswith('$')] + + # Make sources relative to root build file. + relative_path = os.path.dirname(main_gyp) + sources += [ os.path.relpath(os.path.join(base, file), relative_path) + for file in files ] + + sources_target['sources'] = sorted(set(sources)) + + # Put sources_to_index in it's own gyp. + sources_gyp = \ + os.path.join(os.path.dirname(main_gyp), sources_target_name + ".gyp") + fully_qualified_target_name = \ + '%s:%s#target' % (sources_gyp, sources_target_name) + + # Add to new_target_list, new_target_dicts and new_data. + new_target_list.append(fully_qualified_target_name) + new_target_dicts[fully_qualified_target_name] = sources_target + new_data_target = {} + new_data_target['target_name'] = sources_target['target_name'] + new_data_target['_DEPTH'] = depth + new_data_target['toolset'] = "target" + new_data[sources_gyp] = {} + new_data[sources_gyp]['targets'] = [] + new_data[sources_gyp]['included_files'] = [] + new_data[sources_gyp]['xcode_settings'] = \ + data[orig_gyp].get('xcode_settings', {}) + new_data[sources_gyp]['targets'].append(new_data_target) + + # Write workspace to file. + _WriteWorkspace(main_gyp, sources_gyp, params) + return (new_target_list, new_target_dicts, new_data) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py new file mode 100644 index 0000000000000..d08b7f777002f --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py @@ -0,0 +1,2927 @@ +# Copyright (c) 2012 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. + +"""Xcode project file generator. + +This module is both an Xcode project file generator and a documentation of the +Xcode project file format. Knowledge of the project file format was gained +based on extensive experience with Xcode, and by making changes to projects in +Xcode.app and observing the resultant changes in the associated project files. + +XCODE PROJECT FILES + +The generator targets the file format as written by Xcode 3.2 (specifically, +3.2.6), but past experience has taught that the format has not changed +significantly in the past several years, and future versions of Xcode are able +to read older project files. + +Xcode project files are "bundled": the project "file" from an end-user's +perspective is actually a directory with an ".xcodeproj" extension. The +project file from this module's perspective is actually a file inside this +directory, always named "project.pbxproj". This file contains a complete +description of the project and is all that is needed to use the xcodeproj. +Other files contained in the xcodeproj directory are simply used to store +per-user settings, such as the state of various UI elements in the Xcode +application. + +The project.pbxproj file is a property list, stored in a format almost +identical to the NeXTstep property list format. The file is able to carry +Unicode data, and is encoded in UTF-8. The root element in the property list +is a dictionary that contains several properties of minimal interest, and two +properties of immense interest. The most important property is a dictionary +named "objects". The entire structure of the project is represented by the +children of this property. The objects dictionary is keyed by unique 96-bit +values represented by 24 uppercase hexadecimal characters. Each value in the +objects dictionary is itself a dictionary, describing an individual object. + +Each object in the dictionary is a member of a class, which is identified by +the "isa" property of each object. A variety of classes are represented in a +project file. Objects can refer to other objects by ID, using the 24-character +hexadecimal object key. A project's objects form a tree, with a root object +of class PBXProject at the root. As an example, the PBXProject object serves +as parent to an XCConfigurationList object defining the build configurations +used in the project, a PBXGroup object serving as a container for all files +referenced in the project, and a list of target objects, each of which defines +a target in the project. There are several different types of target object, +such as PBXNativeTarget and PBXAggregateTarget. In this module, this +relationship is expressed by having each target type derive from an abstract +base named XCTarget. + +The project.pbxproj file's root dictionary also contains a property, sibling to +the "objects" dictionary, named "rootObject". The value of rootObject is a +24-character object key referring to the root PBXProject object in the +objects dictionary. + +In Xcode, every file used as input to a target or produced as a final product +of a target must appear somewhere in the hierarchy rooted at the PBXGroup +object referenced by the PBXProject's mainGroup property. A PBXGroup is +generally represented as a folder in the Xcode application. PBXGroups can +contain other PBXGroups as well as PBXFileReferences, which are pointers to +actual files. + +Each XCTarget contains a list of build phases, represented in this module by +the abstract base XCBuildPhase. Examples of concrete XCBuildPhase derivations +are PBXSourcesBuildPhase and PBXFrameworksBuildPhase, which correspond to the +"Compile Sources" and "Link Binary With Libraries" phases displayed in the +Xcode application. Files used as input to these phases (for example, source +files in the former case and libraries and frameworks in the latter) are +represented by PBXBuildFile objects, referenced by elements of "files" lists +in XCTarget objects. Each PBXBuildFile object refers to a PBXBuildFile +object as a "weak" reference: it does not "own" the PBXBuildFile, which is +owned by the root object's mainGroup or a descendant group. In most cases, the +layer of indirection between an XCBuildPhase and a PBXFileReference via a +PBXBuildFile appears extraneous, but there's actually one reason for this: +file-specific compiler flags are added to the PBXBuildFile object so as to +allow a single file to be a member of multiple targets while having distinct +compiler flags for each. These flags can be modified in the Xcode applciation +in the "Build" tab of a File Info window. + +When a project is open in the Xcode application, Xcode will rewrite it. As +such, this module is careful to adhere to the formatting used by Xcode, to +avoid insignificant changes appearing in the file when it is used in the +Xcode application. This will keep version control repositories happy, and +makes it possible to compare a project file used in Xcode to one generated by +this module to determine if any significant changes were made in the +application. + +Xcode has its own way of assigning 24-character identifiers to each object, +which is not duplicated here. Because the identifier only is only generated +once, when an object is created, and is then left unchanged, there is no need +to attempt to duplicate Xcode's behavior in this area. The generator is free +to select any identifier, even at random, to refer to the objects it creates, +and Xcode will retain those identifiers and use them when subsequently +rewriting the project file. However, the generator would choose new random +identifiers each time the project files are generated, leading to difficulties +comparing "used" project files to "pristine" ones produced by this module, +and causing the appearance of changes as every object identifier is changed +when updated projects are checked in to a version control repository. To +mitigate this problem, this module chooses identifiers in a more deterministic +way, by hashing a description of each object as well as its parent and ancestor +objects. This strategy should result in minimal "shift" in IDs as successive +generations of project files are produced. + +THIS MODULE + +This module introduces several classes, all derived from the XCObject class. +Nearly all of the "brains" are built into the XCObject class, which understands +how to create and modify objects, maintain the proper tree structure, compute +identifiers, and print objects. For the most part, classes derived from +XCObject need only provide a _schema class object, a dictionary that +expresses what properties objects of the class may contain. + +Given this structure, it's possible to build a minimal project file by creating +objects of the appropriate types and making the proper connections: + + config_list = XCConfigurationList() + group = PBXGroup() + project = PBXProject({'buildConfigurationList': config_list, + 'mainGroup': group}) + +With the project object set up, it can be added to an XCProjectFile object. +XCProjectFile is a pseudo-class in the sense that it is a concrete XCObject +subclass that does not actually correspond to a class type found in a project +file. Rather, it is used to represent the project file's root dictionary. +Printing an XCProjectFile will print the entire project file, including the +full "objects" dictionary. + + project_file = XCProjectFile({'rootObject': project}) + project_file.ComputeIDs() + project_file.Print() + +Xcode project files are always encoded in UTF-8. This module will accept +strings of either the str class or the unicode class. Strings of class str +are assumed to already be encoded in UTF-8. Obviously, if you're just using +ASCII, you won't encounter difficulties because ASCII is a UTF-8 subset. +Strings of class unicode are handled properly and encoded in UTF-8 when +a project file is output. +""" + +import gyp.common +import posixpath +import re +import struct +import sys + +# hashlib is supplied as of Python 2.5 as the replacement interface for sha +# and other secure hashes. In 2.6, sha is deprecated. Import hashlib if +# available, avoiding a deprecation warning under 2.6. Import sha otherwise, +# preserving 2.4 compatibility. +try: + import hashlib + _new_sha1 = hashlib.sha1 +except ImportError: + import sha + _new_sha1 = sha.new + + +# See XCObject._EncodeString. This pattern is used to determine when a string +# can be printed unquoted. Strings that match this pattern may be printed +# unquoted. Strings that do not match must be quoted and may be further +# transformed to be properly encoded. Note that this expression matches the +# characters listed with "+", for 1 or more occurrences: if a string is empty, +# it must not match this pattern, because it needs to be encoded as "". +_unquoted = re.compile('^[A-Za-z0-9$./_]+$') + +# Strings that match this pattern are quoted regardless of what _unquoted says. +# Oddly, Xcode will quote any string with a run of three or more underscores. +_quoted = re.compile('___') + +# This pattern should match any character that needs to be escaped by +# XCObject._EncodeString. See that function. +_escaped = re.compile('[\\\\"]|[\x00-\x1f]') + + +# Used by SourceTreeAndPathFromPath +_path_leading_variable = re.compile(r'^\$\((.*?)\)(/(.*))?$') + +def SourceTreeAndPathFromPath(input_path): + """Given input_path, returns a tuple with sourceTree and path values. + + Examples: + input_path (source_tree, output_path) + '$(VAR)/path' ('VAR', 'path') + '$(VAR)' ('VAR', None) + 'path' (None, 'path') + """ + + source_group_match = _path_leading_variable.match(input_path) + if source_group_match: + source_tree = source_group_match.group(1) + output_path = source_group_match.group(3) # This may be None. + else: + source_tree = None + output_path = input_path + + return (source_tree, output_path) + +def ConvertVariablesToShellSyntax(input_string): + return re.sub(r'\$\((.*?)\)', '${\\1}', input_string) + +class XCObject(object): + """The abstract base of all class types used in Xcode project files. + + Class variables: + _schema: A dictionary defining the properties of this class. The keys to + _schema are string property keys as used in project files. Values + are a list of four or five elements: + [ is_list, property_type, is_strong, is_required, default ] + is_list: True if the property described is a list, as opposed + to a single element. + property_type: The type to use as the value of the property, + or if is_list is True, the type to use for each + element of the value's list. property_type must + be an XCObject subclass, or one of the built-in + types str, int, or dict. + is_strong: If property_type is an XCObject subclass, is_strong + is True to assert that this class "owns," or serves + as parent, to the property value (or, if is_list is + True, values). is_strong must be False if + property_type is not an XCObject subclass. + is_required: True if the property is required for the class. + Note that is_required being True does not preclude + an empty string ("", in the case of property_type + str) or list ([], in the case of is_list True) from + being set for the property. + default: Optional. If is_requried is True, default may be set + to provide a default value for objects that do not supply + their own value. If is_required is True and default + is not provided, users of the class must supply their own + value for the property. + Note that although the values of the array are expressed in + boolean terms, subclasses provide values as integers to conserve + horizontal space. + _should_print_single_line: False in XCObject. Subclasses whose objects + should be written to the project file in the + alternate single-line format, such as + PBXFileReference and PBXBuildFile, should + set this to True. + _encode_transforms: Used by _EncodeString to encode unprintable characters. + The index into this list is the ordinal of the + character to transform; each value is a string + used to represent the character in the output. XCObject + provides an _encode_transforms list suitable for most + XCObject subclasses. + _alternate_encode_transforms: Provided for subclasses that wish to use + the alternate encoding rules. Xcode seems + to use these rules when printing objects in + single-line format. Subclasses that desire + this behavior should set _encode_transforms + to _alternate_encode_transforms. + _hashables: A list of XCObject subclasses that can be hashed by ComputeIDs + to construct this object's ID. Most classes that need custom + hashing behavior should do it by overriding Hashables, + but in some cases an object's parent may wish to push a + hashable value into its child, and it can do so by appending + to _hashables. + Attributes: + id: The object's identifier, a 24-character uppercase hexadecimal string. + Usually, objects being created should not set id until the entire + project file structure is built. At that point, UpdateIDs() should + be called on the root object to assign deterministic values for id to + each object in the tree. + parent: The object's parent. This is set by a parent XCObject when a child + object is added to it. + _properties: The object's property dictionary. An object's properties are + described by its class' _schema variable. + """ + + _schema = {} + _should_print_single_line = False + + # See _EncodeString. + _encode_transforms = [] + i = 0 + while i < ord(' '): + _encode_transforms.append('\\U%04x' % i) + i = i + 1 + _encode_transforms[7] = '\\a' + _encode_transforms[8] = '\\b' + _encode_transforms[9] = '\\t' + _encode_transforms[10] = '\\n' + _encode_transforms[11] = '\\v' + _encode_transforms[12] = '\\f' + _encode_transforms[13] = '\\n' + + _alternate_encode_transforms = list(_encode_transforms) + _alternate_encode_transforms[9] = chr(9) + _alternate_encode_transforms[10] = chr(10) + _alternate_encode_transforms[11] = chr(11) + + def __init__(self, properties=None, id=None, parent=None): + self.id = id + self.parent = parent + self._properties = {} + self._hashables = [] + self._SetDefaultsFromSchema() + self.UpdateProperties(properties) + + def __repr__(self): + try: + name = self.Name() + except NotImplementedError: + return '<%s at 0x%x>' % (self.__class__.__name__, id(self)) + return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self)) + + def Copy(self): + """Make a copy of this object. + + The new object will have its own copy of lists and dicts. Any XCObject + objects owned by this object (marked "strong") will be copied in the + new object, even those found in lists. If this object has any weak + references to other XCObjects, the same references are added to the new + object without making a copy. + """ + + that = self.__class__(id=self.id, parent=self.parent) + for key, value in self._properties.iteritems(): + is_strong = self._schema[key][2] + + if isinstance(value, XCObject): + if is_strong: + new_value = value.Copy() + new_value.parent = that + that._properties[key] = new_value + else: + that._properties[key] = value + elif isinstance(value, str) or isinstance(value, unicode) or \ + isinstance(value, int): + that._properties[key] = value + elif isinstance(value, list): + if is_strong: + # If is_strong is True, each element is an XCObject, so it's safe to + # call Copy. + that._properties[key] = [] + for item in value: + new_item = item.Copy() + new_item.parent = that + that._properties[key].append(new_item) + else: + that._properties[key] = value[:] + elif isinstance(value, dict): + # dicts are never strong. + if is_strong: + raise TypeError('Strong dict for key ' + key + ' in ' + \ + self.__class__.__name__) + else: + that._properties[key] = value.copy() + else: + raise TypeError('Unexpected type ' + value.__class__.__name__ + \ + ' for key ' + key + ' in ' + self.__class__.__name__) + + return that + + def Name(self): + """Return the name corresponding to an object. + + Not all objects necessarily need to be nameable, and not all that do have + a "name" property. Override as needed. + """ + + # If the schema indicates that "name" is required, try to access the + # property even if it doesn't exist. This will result in a KeyError + # being raised for the property that should be present, which seems more + # appropriate than NotImplementedError in this case. + if 'name' in self._properties or \ + ('name' in self._schema and self._schema['name'][3]): + return self._properties['name'] + + raise NotImplementedError(self.__class__.__name__ + ' must implement Name') + + def Comment(self): + """Return a comment string for the object. + + Most objects just use their name as the comment, but PBXProject uses + different values. + + The returned comment is not escaped and does not have any comment marker + strings applied to it. + """ + + return self.Name() + + def Hashables(self): + hashables = [self.__class__.__name__] + + name = self.Name() + if name != None: + hashables.append(name) + + hashables.extend(self._hashables) + + return hashables + + def HashablesForChild(self): + return None + + def ComputeIDs(self, recursive=True, overwrite=True, seed_hash=None): + """Set "id" properties deterministically. + + An object's "id" property is set based on a hash of its class type and + name, as well as the class type and name of all ancestor objects. As + such, it is only advisable to call ComputeIDs once an entire project file + tree is built. + + If recursive is True, recurse into all descendant objects and update their + hashes. + + If overwrite is True, any existing value set in the "id" property will be + replaced. + """ + + def _HashUpdate(hash, data): + """Update hash with data's length and contents. + + If the hash were updated only with the value of data, it would be + possible for clowns to induce collisions by manipulating the names of + their objects. By adding the length, it's exceedingly less likely that + ID collisions will be encountered, intentionally or not. + """ + + hash.update(struct.pack('>i', len(data))) + hash.update(data) + + if seed_hash is None: + seed_hash = _new_sha1() + + hash = seed_hash.copy() + + hashables = self.Hashables() + assert len(hashables) > 0 + for hashable in hashables: + _HashUpdate(hash, hashable) + + if recursive: + hashables_for_child = self.HashablesForChild() + if hashables_for_child is None: + child_hash = hash + else: + assert len(hashables_for_child) > 0 + child_hash = seed_hash.copy() + for hashable in hashables_for_child: + _HashUpdate(child_hash, hashable) + + for child in self.Children(): + child.ComputeIDs(recursive, overwrite, child_hash) + + if overwrite or self.id is None: + # Xcode IDs are only 96 bits (24 hex characters), but a SHA-1 digest is + # is 160 bits. Instead of throwing out 64 bits of the digest, xor them + # into the portion that gets used. + assert hash.digest_size % 4 == 0 + digest_int_count = hash.digest_size / 4 + digest_ints = struct.unpack('>' + 'I' * digest_int_count, hash.digest()) + id_ints = [0, 0, 0] + for index in xrange(0, digest_int_count): + id_ints[index % 3] ^= digest_ints[index] + self.id = '%08X%08X%08X' % tuple(id_ints) + + def EnsureNoIDCollisions(self): + """Verifies that no two objects have the same ID. Checks all descendants. + """ + + ids = {} + descendants = self.Descendants() + for descendant in descendants: + if descendant.id in ids: + other = ids[descendant.id] + raise KeyError( + 'Duplicate ID %s, objects "%s" and "%s" in "%s"' % \ + (descendant.id, str(descendant._properties), + str(other._properties), self._properties['rootObject'].Name())) + ids[descendant.id] = descendant + + def Children(self): + """Returns a list of all of this object's owned (strong) children.""" + + children = [] + for property, attributes in self._schema.iteritems(): + (is_list, property_type, is_strong) = attributes[0:3] + if is_strong and property in self._properties: + if not is_list: + children.append(self._properties[property]) + else: + children.extend(self._properties[property]) + return children + + def Descendants(self): + """Returns a list of all of this object's descendants, including this + object. + """ + + children = self.Children() + descendants = [self] + for child in children: + descendants.extend(child.Descendants()) + return descendants + + def PBXProjectAncestor(self): + # The base case for recursion is defined at PBXProject.PBXProjectAncestor. + if self.parent: + return self.parent.PBXProjectAncestor() + return None + + def _EncodeComment(self, comment): + """Encodes a comment to be placed in the project file output, mimicing + Xcode behavior. + """ + + # This mimics Xcode behavior by wrapping the comment in "/*" and "*/". If + # the string already contains a "*/", it is turned into "(*)/". This keeps + # the file writer from outputting something that would be treated as the + # end of a comment in the middle of something intended to be entirely a + # comment. + + return '/* ' + comment.replace('*/', '(*)/') + ' */' + + def _EncodeTransform(self, match): + # This function works closely with _EncodeString. It will only be called + # by re.sub with match.group(0) containing a character matched by the + # the _escaped expression. + char = match.group(0) + + # Backslashes (\) and quotation marks (") are always replaced with a + # backslash-escaped version of the same. Everything else gets its + # replacement from the class' _encode_transforms array. + if char == '\\': + return '\\\\' + if char == '"': + return '\\"' + return self._encode_transforms[ord(char)] + + def _EncodeString(self, value): + """Encodes a string to be placed in the project file output, mimicing + Xcode behavior. + """ + + # Use quotation marks when any character outside of the range A-Z, a-z, 0-9, + # $ (dollar sign), . (period), and _ (underscore) is present. Also use + # quotation marks to represent empty strings. + # + # Escape " (double-quote) and \ (backslash) by preceding them with a + # backslash. + # + # Some characters below the printable ASCII range are encoded specially: + # 7 ^G BEL is encoded as "\a" + # 8 ^H BS is encoded as "\b" + # 11 ^K VT is encoded as "\v" + # 12 ^L NP is encoded as "\f" + # 127 ^? DEL is passed through as-is without escaping + # - In PBXFileReference and PBXBuildFile objects: + # 9 ^I HT is passed through as-is without escaping + # 10 ^J NL is passed through as-is without escaping + # 13 ^M CR is passed through as-is without escaping + # - In other objects: + # 9 ^I HT is encoded as "\t" + # 10 ^J NL is encoded as "\n" + # 13 ^M CR is encoded as "\n" rendering it indistinguishable from + # 10 ^J NL + # All other characters within the ASCII control character range (0 through + # 31 inclusive) are encoded as "\U001f" referring to the Unicode code point + # in hexadecimal. For example, character 14 (^N SO) is encoded as "\U000e". + # Characters above the ASCII range are passed through to the output encoded + # as UTF-8 without any escaping. These mappings are contained in the + # class' _encode_transforms list. + + if _unquoted.search(value) and not _quoted.search(value): + return value + + return '"' + _escaped.sub(self._EncodeTransform, value) + '"' + + def _XCPrint(self, file, tabs, line): + file.write('\t' * tabs + line) + + def _XCPrintableValue(self, tabs, value, flatten_list=False): + """Returns a representation of value that may be printed in a project file, + mimicing Xcode's behavior. + + _XCPrintableValue can handle str and int values, XCObjects (which are + made printable by returning their id property), and list and dict objects + composed of any of the above types. When printing a list or dict, and + _should_print_single_line is False, the tabs parameter is used to determine + how much to indent the lines corresponding to the items in the list or + dict. + + If flatten_list is True, single-element lists will be transformed into + strings. + """ + + printable = '' + comment = None + + if self._should_print_single_line: + sep = ' ' + element_tabs = '' + end_tabs = '' + else: + sep = '\n' + element_tabs = '\t' * (tabs + 1) + end_tabs = '\t' * tabs + + if isinstance(value, XCObject): + printable += value.id + comment = value.Comment() + elif isinstance(value, str): + printable += self._EncodeString(value) + elif isinstance(value, unicode): + printable += self._EncodeString(value.encode('utf-8')) + elif isinstance(value, int): + printable += str(value) + elif isinstance(value, list): + if flatten_list and len(value) <= 1: + if len(value) == 0: + printable += self._EncodeString('') + else: + printable += self._EncodeString(value[0]) + else: + printable = '(' + sep + for item in value: + printable += element_tabs + \ + self._XCPrintableValue(tabs + 1, item, flatten_list) + \ + ',' + sep + printable += end_tabs + ')' + elif isinstance(value, dict): + printable = '{' + sep + for item_key, item_value in sorted(value.iteritems()): + printable += element_tabs + \ + self._XCPrintableValue(tabs + 1, item_key, flatten_list) + ' = ' + \ + self._XCPrintableValue(tabs + 1, item_value, flatten_list) + ';' + \ + sep + printable += end_tabs + '}' + else: + raise TypeError("Can't make " + value.__class__.__name__ + ' printable') + + if comment != None: + printable += ' ' + self._EncodeComment(comment) + + return printable + + def _XCKVPrint(self, file, tabs, key, value): + """Prints a key and value, members of an XCObject's _properties dictionary, + to file. + + tabs is an int identifying the indentation level. If the class' + _should_print_single_line variable is True, tabs is ignored and the + key-value pair will be followed by a space insead of a newline. + """ + + if self._should_print_single_line: + printable = '' + after_kv = ' ' + else: + printable = '\t' * tabs + after_kv = '\n' + + # Xcode usually prints remoteGlobalIDString values in PBXContainerItemProxy + # objects without comments. Sometimes it prints them with comments, but + # the majority of the time, it doesn't. To avoid unnecessary changes to + # the project file after Xcode opens it, don't write comments for + # remoteGlobalIDString. This is a sucky hack and it would certainly be + # cleaner to extend the schema to indicate whether or not a comment should + # be printed, but since this is the only case where the problem occurs and + # Xcode itself can't seem to make up its mind, the hack will suffice. + # + # Also see PBXContainerItemProxy._schema['remoteGlobalIDString']. + if key == 'remoteGlobalIDString' and isinstance(self, + PBXContainerItemProxy): + value_to_print = value.id + else: + value_to_print = value + + # PBXBuildFile's settings property is represented in the output as a dict, + # but a hack here has it represented as a string. Arrange to strip off the + # quotes so that it shows up in the output as expected. + if key == 'settings' and isinstance(self, PBXBuildFile): + strip_value_quotes = True + else: + strip_value_quotes = False + + # In another one-off, let's set flatten_list on buildSettings properties + # of XCBuildConfiguration objects, because that's how Xcode treats them. + if key == 'buildSettings' and isinstance(self, XCBuildConfiguration): + flatten_list = True + else: + flatten_list = False + + try: + printable_key = self._XCPrintableValue(tabs, key, flatten_list) + printable_value = self._XCPrintableValue(tabs, value_to_print, + flatten_list) + if strip_value_quotes and len(printable_value) > 1 and \ + printable_value[0] == '"' and printable_value[-1] == '"': + printable_value = printable_value[1:-1] + printable += printable_key + ' = ' + printable_value + ';' + after_kv + except TypeError, e: + gyp.common.ExceptionAppend(e, + 'while printing key "%s"' % key) + raise + + self._XCPrint(file, 0, printable) + + def Print(self, file=sys.stdout): + """Prints a reprentation of this object to file, adhering to Xcode output + formatting. + """ + + self.VerifyHasRequiredProperties() + + if self._should_print_single_line: + # When printing an object in a single line, Xcode doesn't put any space + # between the beginning of a dictionary (or presumably a list) and the + # first contained item, so you wind up with snippets like + # ...CDEF = {isa = PBXFileReference; fileRef = 0123... + # If it were me, I would have put a space in there after the opening + # curly, but I guess this is just another one of those inconsistencies + # between how Xcode prints PBXFileReference and PBXBuildFile objects as + # compared to other objects. Mimic Xcode's behavior here by using an + # empty string for sep. + sep = '' + end_tabs = 0 + else: + sep = '\n' + end_tabs = 2 + + # Start the object. For example, '\t\tPBXProject = {\n'. + self._XCPrint(file, 2, self._XCPrintableValue(2, self) + ' = {' + sep) + + # "isa" isn't in the _properties dictionary, it's an intrinsic property + # of the class which the object belongs to. Xcode always outputs "isa" + # as the first element of an object dictionary. + self._XCKVPrint(file, 3, 'isa', self.__class__.__name__) + + # The remaining elements of an object dictionary are sorted alphabetically. + for property, value in sorted(self._properties.iteritems()): + self._XCKVPrint(file, 3, property, value) + + # End the object. + self._XCPrint(file, end_tabs, '};\n') + + def UpdateProperties(self, properties, do_copy=False): + """Merge the supplied properties into the _properties dictionary. + + The input properties must adhere to the class schema or a KeyError or + TypeError exception will be raised. If adding an object of an XCObject + subclass and the schema indicates a strong relationship, the object's + parent will be set to this object. + + If do_copy is True, then lists, dicts, strong-owned XCObjects, and + strong-owned XCObjects in lists will be copied instead of having their + references added. + """ + + if properties is None: + return + + for property, value in properties.iteritems(): + # Make sure the property is in the schema. + if not property in self._schema: + raise KeyError(property + ' not in ' + self.__class__.__name__) + + # Make sure the property conforms to the schema. + (is_list, property_type, is_strong) = self._schema[property][0:3] + if is_list: + if value.__class__ != list: + raise TypeError( + property + ' of ' + self.__class__.__name__ + \ + ' must be list, not ' + value.__class__.__name__) + for item in value: + if not isinstance(item, property_type) and \ + not (item.__class__ == unicode and property_type == str): + # Accept unicode where str is specified. str is treated as + # UTF-8-encoded. + raise TypeError( + 'item of ' + property + ' of ' + self.__class__.__name__ + \ + ' must be ' + property_type.__name__ + ', not ' + \ + item.__class__.__name__) + elif not isinstance(value, property_type) and \ + not (value.__class__ == unicode and property_type == str): + # Accept unicode where str is specified. str is treated as + # UTF-8-encoded. + raise TypeError( + property + ' of ' + self.__class__.__name__ + ' must be ' + \ + property_type.__name__ + ', not ' + value.__class__.__name__) + + # Checks passed, perform the assignment. + if do_copy: + if isinstance(value, XCObject): + if is_strong: + self._properties[property] = value.Copy() + else: + self._properties[property] = value + elif isinstance(value, str) or isinstance(value, unicode) or \ + isinstance(value, int): + self._properties[property] = value + elif isinstance(value, list): + if is_strong: + # If is_strong is True, each element is an XCObject, so it's safe + # to call Copy. + self._properties[property] = [] + for item in value: + self._properties[property].append(item.Copy()) + else: + self._properties[property] = value[:] + elif isinstance(value, dict): + self._properties[property] = value.copy() + else: + raise TypeError("Don't know how to copy a " + \ + value.__class__.__name__ + ' object for ' + \ + property + ' in ' + self.__class__.__name__) + else: + self._properties[property] = value + + # Set up the child's back-reference to this object. Don't use |value| + # any more because it may not be right if do_copy is true. + if is_strong: + if not is_list: + self._properties[property].parent = self + else: + for item in self._properties[property]: + item.parent = self + + def HasProperty(self, key): + return key in self._properties + + def GetProperty(self, key): + return self._properties[key] + + def SetProperty(self, key, value): + self.UpdateProperties({key: value}) + + def DelProperty(self, key): + if key in self._properties: + del self._properties[key] + + def AppendProperty(self, key, value): + # TODO(mark): Support ExtendProperty too (and make this call that)? + + # Schema validation. + if not key in self._schema: + raise KeyError(key + ' not in ' + self.__class__.__name__) + + (is_list, property_type, is_strong) = self._schema[key][0:3] + if not is_list: + raise TypeError(key + ' of ' + self.__class__.__name__ + ' must be list') + if not isinstance(value, property_type): + raise TypeError('item of ' + key + ' of ' + self.__class__.__name__ + \ + ' must be ' + property_type.__name__ + ', not ' + \ + value.__class__.__name__) + + # If the property doesn't exist yet, create a new empty list to receive the + # item. + if not key in self._properties: + self._properties[key] = [] + + # Set up the ownership link. + if is_strong: + value.parent = self + + # Store the item. + self._properties[key].append(value) + + def VerifyHasRequiredProperties(self): + """Ensure that all properties identified as required by the schema are + set. + """ + + # TODO(mark): A stronger verification mechanism is needed. Some + # subclasses need to perform validation beyond what the schema can enforce. + for property, attributes in self._schema.iteritems(): + (is_list, property_type, is_strong, is_required) = attributes[0:4] + if is_required and not property in self._properties: + raise KeyError(self.__class__.__name__ + ' requires ' + property) + + def _SetDefaultsFromSchema(self): + """Assign object default values according to the schema. This will not + overwrite properties that have already been set.""" + + defaults = {} + for property, attributes in self._schema.iteritems(): + (is_list, property_type, is_strong, is_required) = attributes[0:4] + if is_required and len(attributes) >= 5 and \ + not property in self._properties: + default = attributes[4] + + defaults[property] = default + + if len(defaults) > 0: + # Use do_copy=True so that each new object gets its own copy of strong + # objects, lists, and dicts. + self.UpdateProperties(defaults, do_copy=True) + + +class XCHierarchicalElement(XCObject): + """Abstract base for PBXGroup and PBXFileReference. Not represented in a + project file.""" + + # TODO(mark): Do name and path belong here? Probably so. + # If path is set and name is not, name may have a default value. Name will + # be set to the basename of path, if the basename of path is different from + # the full value of path. If path is already just a leaf name, name will + # not be set. + _schema = XCObject._schema.copy() + _schema.update({ + 'comments': [0, str, 0, 0], + 'fileEncoding': [0, str, 0, 0], + 'includeInIndex': [0, int, 0, 0], + 'indentWidth': [0, int, 0, 0], + 'lineEnding': [0, int, 0, 0], + 'sourceTree': [0, str, 0, 1, ''], + 'tabWidth': [0, int, 0, 0], + 'usesTabs': [0, int, 0, 0], + 'wrapsLines': [0, int, 0, 0], + }) + + def __init__(self, properties=None, id=None, parent=None): + # super + XCObject.__init__(self, properties, id, parent) + if 'path' in self._properties and not 'name' in self._properties: + path = self._properties['path'] + name = posixpath.basename(path) + if name != '' and path != name: + self.SetProperty('name', name) + + if 'path' in self._properties and \ + (not 'sourceTree' in self._properties or \ + self._properties['sourceTree'] == ''): + # If the pathname begins with an Xcode variable like "$(SDKROOT)/", take + # the variable out and make the path be relative to that variable by + # assigning the variable name as the sourceTree. + (source_tree, path) = SourceTreeAndPathFromPath(self._properties['path']) + if source_tree != None: + self._properties['sourceTree'] = source_tree + if path != None: + self._properties['path'] = path + if source_tree != None and path is None and \ + not 'name' in self._properties: + # The path was of the form "$(SDKROOT)" with no path following it. + # This object is now relative to that variable, so it has no path + # attribute of its own. It does, however, keep a name. + del self._properties['path'] + self._properties['name'] = source_tree + + def Name(self): + if 'name' in self._properties: + return self._properties['name'] + elif 'path' in self._properties: + return self._properties['path'] + else: + # This happens in the case of the root PBXGroup. + return None + + def Hashables(self): + """Custom hashables for XCHierarchicalElements. + + XCHierarchicalElements are special. Generally, their hashes shouldn't + change if the paths don't change. The normal XCObject implementation of + Hashables adds a hashable for each object, which means that if + the hierarchical structure changes (possibly due to changes caused when + TakeOverOnlyChild runs and encounters slight changes in the hierarchy), + the hashes will change. For example, if a project file initially contains + a/b/f1 and a/b becomes collapsed into a/b, f1 will have a single parent + a/b. If someone later adds a/f2 to the project file, a/b can no longer be + collapsed, and f1 winds up with parent b and grandparent a. That would + be sufficient to change f1's hash. + + To counteract this problem, hashables for all XCHierarchicalElements except + for the main group (which has neither a name nor a path) are taken to be + just the set of path components. Because hashables are inherited from + parents, this provides assurance that a/b/f1 has the same set of hashables + whether its parent is b or a/b. + + The main group is a special case. As it is permitted to have no name or + path, it is permitted to use the standard XCObject hash mechanism. This + is not considered a problem because there can be only one main group. + """ + + if self == self.PBXProjectAncestor()._properties['mainGroup']: + # super + return XCObject.Hashables(self) + + hashables = [] + + # Put the name in first, ensuring that if TakeOverOnlyChild collapses + # children into a top-level group like "Source", the name always goes + # into the list of hashables without interfering with path components. + if 'name' in self._properties: + # Make it less likely for people to manipulate hashes by following the + # pattern of always pushing an object type value onto the list first. + hashables.append(self.__class__.__name__ + '.name') + hashables.append(self._properties['name']) + + # NOTE: This still has the problem that if an absolute path is encountered, + # including paths with a sourceTree, they'll still inherit their parents' + # hashables, even though the paths aren't relative to their parents. This + # is not expected to be much of a problem in practice. + path = self.PathFromSourceTreeAndPath() + if path != None: + components = path.split(posixpath.sep) + for component in components: + hashables.append(self.__class__.__name__ + '.path') + hashables.append(component) + + hashables.extend(self._hashables) + + return hashables + + def Compare(self, other): + # Allow comparison of these types. PBXGroup has the highest sort rank; + # PBXVariantGroup is treated as equal to PBXFileReference. + valid_class_types = { + PBXFileReference: 'file', + PBXGroup: 'group', + PBXVariantGroup: 'file', + } + self_type = valid_class_types[self.__class__] + other_type = valid_class_types[other.__class__] + + if self_type == other_type: + # If the two objects are of the same sort rank, compare their names. + return cmp(self.Name(), other.Name()) + + # Otherwise, sort groups before everything else. + if self_type == 'group': + return -1 + return 1 + + def CompareRootGroup(self, other): + # This function should be used only to compare direct children of the + # containing PBXProject's mainGroup. These groups should appear in the + # listed order. + # TODO(mark): "Build" is used by gyp.generator.xcode, perhaps the + # generator should have a way of influencing this list rather than having + # to hardcode for the generator here. + order = ['Source', 'Intermediates', 'Projects', 'Frameworks', 'Products', + 'Build'] + + # If the groups aren't in the listed order, do a name comparison. + # Otherwise, groups in the listed order should come before those that + # aren't. + self_name = self.Name() + other_name = other.Name() + self_in = isinstance(self, PBXGroup) and self_name in order + other_in = isinstance(self, PBXGroup) and other_name in order + if not self_in and not other_in: + return self.Compare(other) + if self_name in order and not other_name in order: + return -1 + if other_name in order and not self_name in order: + return 1 + + # If both groups are in the listed order, go by the defined order. + self_index = order.index(self_name) + other_index = order.index(other_name) + if self_index < other_index: + return -1 + if self_index > other_index: + return 1 + return 0 + + def PathFromSourceTreeAndPath(self): + # Turn the object's sourceTree and path properties into a single flat + # string of a form comparable to the path parameter. If there's a + # sourceTree property other than "", wrap it in $(...) for the + # comparison. + components = [] + if self._properties['sourceTree'] != '': + components.append('$(' + self._properties['sourceTree'] + ')') + if 'path' in self._properties: + components.append(self._properties['path']) + + if len(components) > 0: + return posixpath.join(*components) + + return None + + def FullPath(self): + # Returns a full path to self relative to the project file, or relative + # to some other source tree. Start with self, and walk up the chain of + # parents prepending their paths, if any, until no more parents are + # available (project-relative path) or until a path relative to some + # source tree is found. + xche = self + path = None + while isinstance(xche, XCHierarchicalElement) and \ + (path is None or \ + (not path.startswith('/') and not path.startswith('$'))): + this_path = xche.PathFromSourceTreeAndPath() + if this_path != None and path != None: + path = posixpath.join(this_path, path) + elif this_path != None: + path = this_path + xche = xche.parent + + return path + + +class PBXGroup(XCHierarchicalElement): + """ + Attributes: + _children_by_path: Maps pathnames of children of this PBXGroup to the + actual child XCHierarchicalElement objects. + _variant_children_by_name_and_path: Maps (name, path) tuples of + PBXVariantGroup children to the actual child PBXVariantGroup objects. + """ + + _schema = XCHierarchicalElement._schema.copy() + _schema.update({ + 'children': [1, XCHierarchicalElement, 1, 1, []], + 'name': [0, str, 0, 0], + 'path': [0, str, 0, 0], + }) + + def __init__(self, properties=None, id=None, parent=None): + # super + XCHierarchicalElement.__init__(self, properties, id, parent) + self._children_by_path = {} + self._variant_children_by_name_and_path = {} + for child in self._properties.get('children', []): + self._AddChildToDicts(child) + + def Hashables(self): + # super + hashables = XCHierarchicalElement.Hashables(self) + + # It is not sufficient to just rely on name and parent to build a unique + # hashable : a node could have two child PBXGroup sharing a common name. + # To add entropy the hashable is enhanced with the names of all its + # children. + for child in self._properties.get('children', []): + child_name = child.Name() + if child_name != None: + hashables.append(child_name) + + return hashables + + def HashablesForChild(self): + # To avoid a circular reference the hashables used to compute a child id do + # not include the child names. + return XCHierarchicalElement.Hashables(self) + + def _AddChildToDicts(self, child): + # Sets up this PBXGroup object's dicts to reference the child properly. + child_path = child.PathFromSourceTreeAndPath() + if child_path: + if child_path in self._children_by_path: + raise ValueError('Found multiple children with path ' + child_path) + self._children_by_path[child_path] = child + + if isinstance(child, PBXVariantGroup): + child_name = child._properties.get('name', None) + key = (child_name, child_path) + if key in self._variant_children_by_name_and_path: + raise ValueError('Found multiple PBXVariantGroup children with ' + \ + 'name ' + str(child_name) + ' and path ' + \ + str(child_path)) + self._variant_children_by_name_and_path[key] = child + + def AppendChild(self, child): + # Callers should use this instead of calling + # AppendProperty('children', child) directly because this function + # maintains the group's dicts. + self.AppendProperty('children', child) + self._AddChildToDicts(child) + + def GetChildByName(self, name): + # This is not currently optimized with a dict as GetChildByPath is because + # it has few callers. Most callers probably want GetChildByPath. This + # function is only useful to get children that have names but no paths, + # which is rare. The children of the main group ("Source", "Products", + # etc.) is pretty much the only case where this likely to come up. + # + # TODO(mark): Maybe this should raise an error if more than one child is + # present with the same name. + if not 'children' in self._properties: + return None + + for child in self._properties['children']: + if child.Name() == name: + return child + + return None + + def GetChildByPath(self, path): + if not path: + return None + + if path in self._children_by_path: + return self._children_by_path[path] + + return None + + def GetChildByRemoteObject(self, remote_object): + # This method is a little bit esoteric. Given a remote_object, which + # should be a PBXFileReference in another project file, this method will + # return this group's PBXReferenceProxy object serving as a local proxy + # for the remote PBXFileReference. + # + # This function might benefit from a dict optimization as GetChildByPath + # for some workloads, but profiling shows that it's not currently a + # problem. + if not 'children' in self._properties: + return None + + for child in self._properties['children']: + if not isinstance(child, PBXReferenceProxy): + continue + + container_proxy = child._properties['remoteRef'] + if container_proxy._properties['remoteGlobalIDString'] == remote_object: + return child + + return None + + def AddOrGetFileByPath(self, path, hierarchical): + """Returns an existing or new file reference corresponding to path. + + If hierarchical is True, this method will create or use the necessary + hierarchical group structure corresponding to path. Otherwise, it will + look in and create an item in the current group only. + + If an existing matching reference is found, it is returned, otherwise, a + new one will be created, added to the correct group, and returned. + + If path identifies a directory by virtue of carrying a trailing slash, + this method returns a PBXFileReference of "folder" type. If path + identifies a variant, by virtue of it identifying a file inside a directory + with an ".lproj" extension, this method returns a PBXVariantGroup + containing the variant named by path, and possibly other variants. For + all other paths, a "normal" PBXFileReference will be returned. + """ + + # Adding or getting a directory? Directories end with a trailing slash. + is_dir = False + if path.endswith('/'): + is_dir = True + path = posixpath.normpath(path) + if is_dir: + path = path + '/' + + # Adding or getting a variant? Variants are files inside directories + # with an ".lproj" extension. Xcode uses variants for localization. For + # a variant path/to/Language.lproj/MainMenu.nib, put a variant group named + # MainMenu.nib inside path/to, and give it a variant named Language. In + # this example, grandparent would be set to path/to and parent_root would + # be set to Language. + variant_name = None + parent = posixpath.dirname(path) + grandparent = posixpath.dirname(parent) + parent_basename = posixpath.basename(parent) + (parent_root, parent_ext) = posixpath.splitext(parent_basename) + if parent_ext == '.lproj': + variant_name = parent_root + if grandparent == '': + grandparent = None + + # Putting a directory inside a variant group is not currently supported. + assert not is_dir or variant_name is None + + path_split = path.split(posixpath.sep) + if len(path_split) == 1 or \ + ((is_dir or variant_name != None) and len(path_split) == 2) or \ + not hierarchical: + # The PBXFileReference or PBXVariantGroup will be added to or gotten from + # this PBXGroup, no recursion necessary. + if variant_name is None: + # Add or get a PBXFileReference. + file_ref = self.GetChildByPath(path) + if file_ref != None: + assert file_ref.__class__ == PBXFileReference + else: + file_ref = PBXFileReference({'path': path}) + self.AppendChild(file_ref) + else: + # Add or get a PBXVariantGroup. The variant group name is the same + # as the basename (MainMenu.nib in the example above). grandparent + # specifies the path to the variant group itself, and path_split[-2:] + # is the path of the specific variant relative to its group. + variant_group_name = posixpath.basename(path) + variant_group_ref = self.AddOrGetVariantGroupByNameAndPath( + variant_group_name, grandparent) + variant_path = posixpath.sep.join(path_split[-2:]) + variant_ref = variant_group_ref.GetChildByPath(variant_path) + if variant_ref != None: + assert variant_ref.__class__ == PBXFileReference + else: + variant_ref = PBXFileReference({'name': variant_name, + 'path': variant_path}) + variant_group_ref.AppendChild(variant_ref) + # The caller is interested in the variant group, not the specific + # variant file. + file_ref = variant_group_ref + return file_ref + else: + # Hierarchical recursion. Add or get a PBXGroup corresponding to the + # outermost path component, and then recurse into it, chopping off that + # path component. + next_dir = path_split[0] + group_ref = self.GetChildByPath(next_dir) + if group_ref != None: + assert group_ref.__class__ == PBXGroup + else: + group_ref = PBXGroup({'path': next_dir}) + self.AppendChild(group_ref) + return group_ref.AddOrGetFileByPath(posixpath.sep.join(path_split[1:]), + hierarchical) + + def AddOrGetVariantGroupByNameAndPath(self, name, path): + """Returns an existing or new PBXVariantGroup for name and path. + + If a PBXVariantGroup identified by the name and path arguments is already + present as a child of this object, it is returned. Otherwise, a new + PBXVariantGroup with the correct properties is created, added as a child, + and returned. + + This method will generally be called by AddOrGetFileByPath, which knows + when to create a variant group based on the structure of the pathnames + passed to it. + """ + + key = (name, path) + if key in self._variant_children_by_name_and_path: + variant_group_ref = self._variant_children_by_name_and_path[key] + assert variant_group_ref.__class__ == PBXVariantGroup + return variant_group_ref + + variant_group_properties = {'name': name} + if path != None: + variant_group_properties['path'] = path + variant_group_ref = PBXVariantGroup(variant_group_properties) + self.AppendChild(variant_group_ref) + + return variant_group_ref + + def TakeOverOnlyChild(self, recurse=False): + """If this PBXGroup has only one child and it's also a PBXGroup, take + it over by making all of its children this object's children. + + This function will continue to take over only children when those children + are groups. If there are three PBXGroups representing a, b, and c, with + c inside b and b inside a, and a and b have no other children, this will + result in a taking over both b and c, forming a PBXGroup for a/b/c. + + If recurse is True, this function will recurse into children and ask them + to collapse themselves by taking over only children as well. Assuming + an example hierarchy with files at a/b/c/d1, a/b/c/d2, and a/b/c/d3/e/f + (d1, d2, and f are files, the rest are groups), recursion will result in + a group for a/b/c containing a group for d3/e. + """ + + # At this stage, check that child class types are PBXGroup exactly, + # instead of using isinstance. The only subclass of PBXGroup, + # PBXVariantGroup, should not participate in reparenting in the same way: + # reparenting by merging different object types would be wrong. + while len(self._properties['children']) == 1 and \ + self._properties['children'][0].__class__ == PBXGroup: + # Loop to take over the innermost only-child group possible. + + child = self._properties['children'][0] + + # Assume the child's properties, including its children. Save a copy + # of this object's old properties, because they'll still be needed. + # This object retains its existing id and parent attributes. + old_properties = self._properties + self._properties = child._properties + self._children_by_path = child._children_by_path + + if not 'sourceTree' in self._properties or \ + self._properties['sourceTree'] == '': + # The child was relative to its parent. Fix up the path. Note that + # children with a sourceTree other than "" are not relative to + # their parents, so no path fix-up is needed in that case. + if 'path' in old_properties: + if 'path' in self._properties: + # Both the original parent and child have paths set. + self._properties['path'] = posixpath.join(old_properties['path'], + self._properties['path']) + else: + # Only the original parent has a path, use it. + self._properties['path'] = old_properties['path'] + if 'sourceTree' in old_properties: + # The original parent had a sourceTree set, use it. + self._properties['sourceTree'] = old_properties['sourceTree'] + + # If the original parent had a name set, keep using it. If the original + # parent didn't have a name but the child did, let the child's name + # live on. If the name attribute seems unnecessary now, get rid of it. + if 'name' in old_properties and old_properties['name'] != None and \ + old_properties['name'] != self.Name(): + self._properties['name'] = old_properties['name'] + if 'name' in self._properties and 'path' in self._properties and \ + self._properties['name'] == self._properties['path']: + del self._properties['name'] + + # Notify all children of their new parent. + for child in self._properties['children']: + child.parent = self + + # If asked to recurse, recurse. + if recurse: + for child in self._properties['children']: + if child.__class__ == PBXGroup: + child.TakeOverOnlyChild(recurse) + + def SortGroup(self): + self._properties['children'] = \ + sorted(self._properties['children'], cmp=lambda x,y: x.Compare(y)) + + # Recurse. + for child in self._properties['children']: + if isinstance(child, PBXGroup): + child.SortGroup() + + +class XCFileLikeElement(XCHierarchicalElement): + # Abstract base for objects that can be used as the fileRef property of + # PBXBuildFile. + + def PathHashables(self): + # A PBXBuildFile that refers to this object will call this method to + # obtain additional hashables specific to this XCFileLikeElement. Don't + # just use this object's hashables, they're not specific and unique enough + # on their own (without access to the parent hashables.) Instead, provide + # hashables that identify this object by path by getting its hashables as + # well as the hashables of ancestor XCHierarchicalElement objects. + + hashables = [] + xche = self + while xche != None and isinstance(xche, XCHierarchicalElement): + xche_hashables = xche.Hashables() + for index in xrange(0, len(xche_hashables)): + hashables.insert(index, xche_hashables[index]) + xche = xche.parent + return hashables + + +class XCContainerPortal(XCObject): + # Abstract base for objects that can be used as the containerPortal property + # of PBXContainerItemProxy. + pass + + +class XCRemoteObject(XCObject): + # Abstract base for objects that can be used as the remoteGlobalIDString + # property of PBXContainerItemProxy. + pass + + +class PBXFileReference(XCFileLikeElement, XCContainerPortal, XCRemoteObject): + _schema = XCFileLikeElement._schema.copy() + _schema.update({ + 'explicitFileType': [0, str, 0, 0], + 'lastKnownFileType': [0, str, 0, 0], + 'name': [0, str, 0, 0], + 'path': [0, str, 0, 1], + }) + + # Weird output rules for PBXFileReference. + _should_print_single_line = True + # super + _encode_transforms = XCFileLikeElement._alternate_encode_transforms + + def __init__(self, properties=None, id=None, parent=None): + # super + XCFileLikeElement.__init__(self, properties, id, parent) + if 'path' in self._properties and self._properties['path'].endswith('/'): + self._properties['path'] = self._properties['path'][:-1] + is_dir = True + else: + is_dir = False + + if 'path' in self._properties and \ + not 'lastKnownFileType' in self._properties and \ + not 'explicitFileType' in self._properties: + # TODO(mark): This is the replacement for a replacement for a quick hack. + # It is no longer incredibly sucky, but this list needs to be extended. + extension_map = { + 'a': 'archive.ar', + 'app': 'wrapper.application', + 'bdic': 'file', + 'bundle': 'wrapper.cfbundle', + 'c': 'sourcecode.c.c', + 'cc': 'sourcecode.cpp.cpp', + 'cpp': 'sourcecode.cpp.cpp', + 'css': 'text.css', + 'cxx': 'sourcecode.cpp.cpp', + 'dart': 'sourcecode', + 'dylib': 'compiled.mach-o.dylib', + 'framework': 'wrapper.framework', + 'gyp': 'sourcecode', + 'gypi': 'sourcecode', + 'h': 'sourcecode.c.h', + 'hxx': 'sourcecode.cpp.h', + 'icns': 'image.icns', + 'java': 'sourcecode.java', + 'js': 'sourcecode.javascript', + 'kext': 'wrapper.kext', + 'm': 'sourcecode.c.objc', + 'mm': 'sourcecode.cpp.objcpp', + 'nib': 'wrapper.nib', + 'o': 'compiled.mach-o.objfile', + 'pdf': 'image.pdf', + 'pl': 'text.script.perl', + 'plist': 'text.plist.xml', + 'pm': 'text.script.perl', + 'png': 'image.png', + 'py': 'text.script.python', + 'r': 'sourcecode.rez', + 'rez': 'sourcecode.rez', + 's': 'sourcecode.asm', + 'storyboard': 'file.storyboard', + 'strings': 'text.plist.strings', + 'swift': 'sourcecode.swift', + 'ttf': 'file', + 'xcassets': 'folder.assetcatalog', + 'xcconfig': 'text.xcconfig', + 'xcdatamodel': 'wrapper.xcdatamodel', + 'xcdatamodeld':'wrapper.xcdatamodeld', + 'xib': 'file.xib', + 'y': 'sourcecode.yacc', + } + + prop_map = { + 'dart': 'explicitFileType', + 'gyp': 'explicitFileType', + 'gypi': 'explicitFileType', + } + + if is_dir: + file_type = 'folder' + prop_name = 'lastKnownFileType' + else: + basename = posixpath.basename(self._properties['path']) + (root, ext) = posixpath.splitext(basename) + # Check the map using a lowercase extension. + # TODO(mark): Maybe it should try with the original case first and fall + # back to lowercase, in case there are any instances where case + # matters. There currently aren't. + if ext != '': + ext = ext[1:].lower() + + # TODO(mark): "text" is the default value, but "file" is appropriate + # for unrecognized files not containing text. Xcode seems to choose + # based on content. + file_type = extension_map.get(ext, 'text') + prop_name = prop_map.get(ext, 'lastKnownFileType') + + self._properties[prop_name] = file_type + + +class PBXVariantGroup(PBXGroup, XCFileLikeElement): + """PBXVariantGroup is used by Xcode to represent localizations.""" + # No additions to the schema relative to PBXGroup. + pass + + +# PBXReferenceProxy is also an XCFileLikeElement subclass. It is defined below +# because it uses PBXContainerItemProxy, defined below. + + +class XCBuildConfiguration(XCObject): + _schema = XCObject._schema.copy() + _schema.update({ + 'baseConfigurationReference': [0, PBXFileReference, 0, 0], + 'buildSettings': [0, dict, 0, 1, {}], + 'name': [0, str, 0, 1], + }) + + def HasBuildSetting(self, key): + return key in self._properties['buildSettings'] + + def GetBuildSetting(self, key): + return self._properties['buildSettings'][key] + + def SetBuildSetting(self, key, value): + # TODO(mark): If a list, copy? + self._properties['buildSettings'][key] = value + + def AppendBuildSetting(self, key, value): + if not key in self._properties['buildSettings']: + self._properties['buildSettings'][key] = [] + self._properties['buildSettings'][key].append(value) + + def DelBuildSetting(self, key): + if key in self._properties['buildSettings']: + del self._properties['buildSettings'][key] + + def SetBaseConfiguration(self, value): + self._properties['baseConfigurationReference'] = value + +class XCConfigurationList(XCObject): + # _configs is the default list of configurations. + _configs = [ XCBuildConfiguration({'name': 'Debug'}), + XCBuildConfiguration({'name': 'Release'}) ] + + _schema = XCObject._schema.copy() + _schema.update({ + 'buildConfigurations': [1, XCBuildConfiguration, 1, 1, _configs], + 'defaultConfigurationIsVisible': [0, int, 0, 1, 1], + 'defaultConfigurationName': [0, str, 0, 1, 'Release'], + }) + + def Name(self): + return 'Build configuration list for ' + \ + self.parent.__class__.__name__ + ' "' + self.parent.Name() + '"' + + def ConfigurationNamed(self, name): + """Convenience accessor to obtain an XCBuildConfiguration by name.""" + for configuration in self._properties['buildConfigurations']: + if configuration._properties['name'] == name: + return configuration + + raise KeyError(name) + + def DefaultConfiguration(self): + """Convenience accessor to obtain the default XCBuildConfiguration.""" + return self.ConfigurationNamed(self._properties['defaultConfigurationName']) + + def HasBuildSetting(self, key): + """Determines the state of a build setting in all XCBuildConfiguration + child objects. + + If all child objects have key in their build settings, and the value is the + same in all child objects, returns 1. + + If no child objects have the key in their build settings, returns 0. + + If some, but not all, child objects have the key in their build settings, + or if any children have different values for the key, returns -1. + """ + + has = None + value = None + for configuration in self._properties['buildConfigurations']: + configuration_has = configuration.HasBuildSetting(key) + if has is None: + has = configuration_has + elif has != configuration_has: + return -1 + + if configuration_has: + configuration_value = configuration.GetBuildSetting(key) + if value is None: + value = configuration_value + elif value != configuration_value: + return -1 + + if not has: + return 0 + + return 1 + + def GetBuildSetting(self, key): + """Gets the build setting for key. + + All child XCConfiguration objects must have the same value set for the + setting, or a ValueError will be raised. + """ + + # TODO(mark): This is wrong for build settings that are lists. The list + # contents should be compared (and a list copy returned?) + + value = None + for configuration in self._properties['buildConfigurations']: + configuration_value = configuration.GetBuildSetting(key) + if value is None: + value = configuration_value + else: + if value != configuration_value: + raise ValueError('Variant values for ' + key) + + return value + + def SetBuildSetting(self, key, value): + """Sets the build setting for key to value in all child + XCBuildConfiguration objects. + """ + + for configuration in self._properties['buildConfigurations']: + configuration.SetBuildSetting(key, value) + + def AppendBuildSetting(self, key, value): + """Appends value to the build setting for key, which is treated as a list, + in all child XCBuildConfiguration objects. + """ + + for configuration in self._properties['buildConfigurations']: + configuration.AppendBuildSetting(key, value) + + def DelBuildSetting(self, key): + """Deletes the build setting key from all child XCBuildConfiguration + objects. + """ + + for configuration in self._properties['buildConfigurations']: + configuration.DelBuildSetting(key) + + def SetBaseConfiguration(self, value): + """Sets the build configuration in all child XCBuildConfiguration objects. + """ + + for configuration in self._properties['buildConfigurations']: + configuration.SetBaseConfiguration(value) + + +class PBXBuildFile(XCObject): + _schema = XCObject._schema.copy() + _schema.update({ + 'fileRef': [0, XCFileLikeElement, 0, 1], + 'settings': [0, str, 0, 0], # hack, it's a dict + }) + + # Weird output rules for PBXBuildFile. + _should_print_single_line = True + _encode_transforms = XCObject._alternate_encode_transforms + + def Name(self): + # Example: "main.cc in Sources" + return self._properties['fileRef'].Name() + ' in ' + self.parent.Name() + + def Hashables(self): + # super + hashables = XCObject.Hashables(self) + + # It is not sufficient to just rely on Name() to get the + # XCFileLikeElement's name, because that is not a complete pathname. + # PathHashables returns hashables unique enough that no two + # PBXBuildFiles should wind up with the same set of hashables, unless + # someone adds the same file multiple times to the same target. That + # would be considered invalid anyway. + hashables.extend(self._properties['fileRef'].PathHashables()) + + return hashables + + +class XCBuildPhase(XCObject): + """Abstract base for build phase classes. Not represented in a project + file. + + Attributes: + _files_by_path: A dict mapping each path of a child in the files list by + path (keys) to the corresponding PBXBuildFile children (values). + _files_by_xcfilelikeelement: A dict mapping each XCFileLikeElement (keys) + to the corresponding PBXBuildFile children (values). + """ + + # TODO(mark): Some build phase types, like PBXShellScriptBuildPhase, don't + # actually have a "files" list. XCBuildPhase should not have "files" but + # another abstract subclass of it should provide this, and concrete build + # phase types that do have "files" lists should be derived from that new + # abstract subclass. XCBuildPhase should only provide buildActionMask and + # runOnlyForDeploymentPostprocessing, and not files or the various + # file-related methods and attributes. + + _schema = XCObject._schema.copy() + _schema.update({ + 'buildActionMask': [0, int, 0, 1, 0x7fffffff], + 'files': [1, PBXBuildFile, 1, 1, []], + 'runOnlyForDeploymentPostprocessing': [0, int, 0, 1, 0], + }) + + def __init__(self, properties=None, id=None, parent=None): + # super + XCObject.__init__(self, properties, id, parent) + + self._files_by_path = {} + self._files_by_xcfilelikeelement = {} + for pbxbuildfile in self._properties.get('files', []): + self._AddBuildFileToDicts(pbxbuildfile) + + def FileGroup(self, path): + # Subclasses must override this by returning a two-element tuple. The + # first item in the tuple should be the PBXGroup to which "path" should be + # added, either as a child or deeper descendant. The second item should + # be a boolean indicating whether files should be added into hierarchical + # groups or one single flat group. + raise NotImplementedError( + self.__class__.__name__ + ' must implement FileGroup') + + def _AddPathToDict(self, pbxbuildfile, path): + """Adds path to the dict tracking paths belonging to this build phase. + + If the path is already a member of this build phase, raises an exception. + """ + + if path in self._files_by_path: + raise ValueError('Found multiple build files with path ' + path) + self._files_by_path[path] = pbxbuildfile + + def _AddBuildFileToDicts(self, pbxbuildfile, path=None): + """Maintains the _files_by_path and _files_by_xcfilelikeelement dicts. + + If path is specified, then it is the path that is being added to the + phase, and pbxbuildfile must contain either a PBXFileReference directly + referencing that path, or it must contain a PBXVariantGroup that itself + contains a PBXFileReference referencing the path. + + If path is not specified, either the PBXFileReference's path or the paths + of all children of the PBXVariantGroup are taken as being added to the + phase. + + If the path is already present in the phase, raises an exception. + + If the PBXFileReference or PBXVariantGroup referenced by pbxbuildfile + are already present in the phase, referenced by a different PBXBuildFile + object, raises an exception. This does not raise an exception when + a PBXFileReference or PBXVariantGroup reappear and are referenced by the + same PBXBuildFile that has already introduced them, because in the case + of PBXVariantGroup objects, they may correspond to multiple paths that are + not all added simultaneously. When this situation occurs, the path needs + to be added to _files_by_path, but nothing needs to change in + _files_by_xcfilelikeelement, and the caller should have avoided adding + the PBXBuildFile if it is already present in the list of children. + """ + + xcfilelikeelement = pbxbuildfile._properties['fileRef'] + + paths = [] + if path != None: + # It's best when the caller provides the path. + if isinstance(xcfilelikeelement, PBXVariantGroup): + paths.append(path) + else: + # If the caller didn't provide a path, there can be either multiple + # paths (PBXVariantGroup) or one. + if isinstance(xcfilelikeelement, PBXVariantGroup): + for variant in xcfilelikeelement._properties['children']: + paths.append(variant.FullPath()) + else: + paths.append(xcfilelikeelement.FullPath()) + + # Add the paths first, because if something's going to raise, the + # messages provided by _AddPathToDict are more useful owing to its + # having access to a real pathname and not just an object's Name(). + for a_path in paths: + self._AddPathToDict(pbxbuildfile, a_path) + + # If another PBXBuildFile references this XCFileLikeElement, there's a + # problem. + if xcfilelikeelement in self._files_by_xcfilelikeelement and \ + self._files_by_xcfilelikeelement[xcfilelikeelement] != pbxbuildfile: + raise ValueError('Found multiple build files for ' + \ + xcfilelikeelement.Name()) + self._files_by_xcfilelikeelement[xcfilelikeelement] = pbxbuildfile + + def AppendBuildFile(self, pbxbuildfile, path=None): + # Callers should use this instead of calling + # AppendProperty('files', pbxbuildfile) directly because this function + # maintains the object's dicts. Better yet, callers can just call AddFile + # with a pathname and not worry about building their own PBXBuildFile + # objects. + self.AppendProperty('files', pbxbuildfile) + self._AddBuildFileToDicts(pbxbuildfile, path) + + def AddFile(self, path, settings=None): + (file_group, hierarchical) = self.FileGroup(path) + file_ref = file_group.AddOrGetFileByPath(path, hierarchical) + + if file_ref in self._files_by_xcfilelikeelement and \ + isinstance(file_ref, PBXVariantGroup): + # There's already a PBXBuildFile in this phase corresponding to the + # PBXVariantGroup. path just provides a new variant that belongs to + # the group. Add the path to the dict. + pbxbuildfile = self._files_by_xcfilelikeelement[file_ref] + self._AddBuildFileToDicts(pbxbuildfile, path) + else: + # Add a new PBXBuildFile to get file_ref into the phase. + if settings is None: + pbxbuildfile = PBXBuildFile({'fileRef': file_ref}) + else: + pbxbuildfile = PBXBuildFile({'fileRef': file_ref, 'settings': settings}) + self.AppendBuildFile(pbxbuildfile, path) + + +class PBXHeadersBuildPhase(XCBuildPhase): + # No additions to the schema relative to XCBuildPhase. + + def Name(self): + return 'Headers' + + def FileGroup(self, path): + return self.PBXProjectAncestor().RootGroupForPath(path) + + +class PBXResourcesBuildPhase(XCBuildPhase): + # No additions to the schema relative to XCBuildPhase. + + def Name(self): + return 'Resources' + + def FileGroup(self, path): + return self.PBXProjectAncestor().RootGroupForPath(path) + + +class PBXSourcesBuildPhase(XCBuildPhase): + # No additions to the schema relative to XCBuildPhase. + + def Name(self): + return 'Sources' + + def FileGroup(self, path): + return self.PBXProjectAncestor().RootGroupForPath(path) + + +class PBXFrameworksBuildPhase(XCBuildPhase): + # No additions to the schema relative to XCBuildPhase. + + def Name(self): + return 'Frameworks' + + def FileGroup(self, path): + (root, ext) = posixpath.splitext(path) + if ext != '': + ext = ext[1:].lower() + if ext == 'o': + # .o files are added to Xcode Frameworks phases, but conceptually aren't + # frameworks, they're more like sources or intermediates. Redirect them + # to show up in one of those other groups. + return self.PBXProjectAncestor().RootGroupForPath(path) + else: + return (self.PBXProjectAncestor().FrameworksGroup(), False) + + +class PBXShellScriptBuildPhase(XCBuildPhase): + _schema = XCBuildPhase._schema.copy() + _schema.update({ + 'inputPaths': [1, str, 0, 1, []], + 'name': [0, str, 0, 0], + 'outputPaths': [1, str, 0, 1, []], + 'shellPath': [0, str, 0, 1, '/bin/sh'], + 'shellScript': [0, str, 0, 1], + 'showEnvVarsInLog': [0, int, 0, 0], + }) + + def Name(self): + if 'name' in self._properties: + return self._properties['name'] + + return 'ShellScript' + + +class PBXCopyFilesBuildPhase(XCBuildPhase): + _schema = XCBuildPhase._schema.copy() + _schema.update({ + 'dstPath': [0, str, 0, 1], + 'dstSubfolderSpec': [0, int, 0, 1], + 'name': [0, str, 0, 0], + }) + + # path_tree_re matches "$(DIR)/path" or just "$(DIR)". Match group 1 is + # "DIR", match group 3 is "path" or None. + path_tree_re = re.compile('^\\$\\((.*)\\)(/(.*)|)$') + + # path_tree_to_subfolder maps names of Xcode variables to the associated + # dstSubfolderSpec property value used in a PBXCopyFilesBuildPhase object. + path_tree_to_subfolder = { + 'BUILT_FRAMEWORKS_DIR': 10, # Frameworks Directory + 'BUILT_PRODUCTS_DIR': 16, # Products Directory + # Other types that can be chosen via the Xcode UI. + # TODO(mark): Map Xcode variable names to these. + # : 1, # Wrapper + # : 6, # Executables: 6 + # : 7, # Resources + # : 15, # Java Resources + # : 11, # Shared Frameworks + # : 12, # Shared Support + # : 13, # PlugIns + } + + def Name(self): + if 'name' in self._properties: + return self._properties['name'] + + return 'CopyFiles' + + def FileGroup(self, path): + return self.PBXProjectAncestor().RootGroupForPath(path) + + def SetDestination(self, path): + """Set the dstSubfolderSpec and dstPath properties from path. + + path may be specified in the same notation used for XCHierarchicalElements, + specifically, "$(DIR)/path". + """ + + path_tree_match = self.path_tree_re.search(path) + if path_tree_match: + # Everything else needs to be relative to an Xcode variable. + path_tree = path_tree_match.group(1) + relative_path = path_tree_match.group(3) + + if path_tree in self.path_tree_to_subfolder: + subfolder = self.path_tree_to_subfolder[path_tree] + if relative_path is None: + relative_path = '' + else: + # The path starts with an unrecognized Xcode variable + # name like $(SRCROOT). Xcode will still handle this + # as an "absolute path" that starts with the variable. + subfolder = 0 + relative_path = path + elif path.startswith('/'): + # Special case. Absolute paths are in dstSubfolderSpec 0. + subfolder = 0 + relative_path = path[1:] + else: + raise ValueError('Can\'t use path %s in a %s' % \ + (path, self.__class__.__name__)) + + self._properties['dstPath'] = relative_path + self._properties['dstSubfolderSpec'] = subfolder + + +class PBXBuildRule(XCObject): + _schema = XCObject._schema.copy() + _schema.update({ + 'compilerSpec': [0, str, 0, 1], + 'filePatterns': [0, str, 0, 0], + 'fileType': [0, str, 0, 1], + 'isEditable': [0, int, 0, 1, 1], + 'outputFiles': [1, str, 0, 1, []], + 'script': [0, str, 0, 0], + }) + + def Name(self): + # Not very inspired, but it's what Xcode uses. + return self.__class__.__name__ + + def Hashables(self): + # super + hashables = XCObject.Hashables(self) + + # Use the hashables of the weak objects that this object refers to. + hashables.append(self._properties['fileType']) + if 'filePatterns' in self._properties: + hashables.append(self._properties['filePatterns']) + return hashables + + +class PBXContainerItemProxy(XCObject): + # When referencing an item in this project file, containerPortal is the + # PBXProject root object of this project file. When referencing an item in + # another project file, containerPortal is a PBXFileReference identifying + # the other project file. + # + # When serving as a proxy to an XCTarget (in this project file or another), + # proxyType is 1. When serving as a proxy to a PBXFileReference (in another + # project file), proxyType is 2. Type 2 is used for references to the + # producs of the other project file's targets. + # + # Xcode is weird about remoteGlobalIDString. Usually, it's printed without + # a comment, indicating that it's tracked internally simply as a string, but + # sometimes it's printed with a comment (usually when the object is initially + # created), indicating that it's tracked as a project file object at least + # sometimes. This module always tracks it as an object, but contains a hack + # to prevent it from printing the comment in the project file output. See + # _XCKVPrint. + _schema = XCObject._schema.copy() + _schema.update({ + 'containerPortal': [0, XCContainerPortal, 0, 1], + 'proxyType': [0, int, 0, 1], + 'remoteGlobalIDString': [0, XCRemoteObject, 0, 1], + 'remoteInfo': [0, str, 0, 1], + }) + + def __repr__(self): + props = self._properties + name = '%s.gyp:%s' % (props['containerPortal'].Name(), props['remoteInfo']) + return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self)) + + def Name(self): + # Admittedly not the best name, but it's what Xcode uses. + return self.__class__.__name__ + + def Hashables(self): + # super + hashables = XCObject.Hashables(self) + + # Use the hashables of the weak objects that this object refers to. + hashables.extend(self._properties['containerPortal'].Hashables()) + hashables.extend(self._properties['remoteGlobalIDString'].Hashables()) + return hashables + + +class PBXTargetDependency(XCObject): + # The "target" property accepts an XCTarget object, and obviously not + # NoneType. But XCTarget is defined below, so it can't be put into the + # schema yet. The definition of PBXTargetDependency can't be moved below + # XCTarget because XCTarget's own schema references PBXTargetDependency. + # Python doesn't deal well with this circular relationship, and doesn't have + # a real way to do forward declarations. To work around, the type of + # the "target" property is reset below, after XCTarget is defined. + # + # At least one of "name" and "target" is required. + _schema = XCObject._schema.copy() + _schema.update({ + 'name': [0, str, 0, 0], + 'target': [0, None.__class__, 0, 0], + 'targetProxy': [0, PBXContainerItemProxy, 1, 1], + }) + + def __repr__(self): + name = self._properties.get('name') or self._properties['target'].Name() + return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self)) + + def Name(self): + # Admittedly not the best name, but it's what Xcode uses. + return self.__class__.__name__ + + def Hashables(self): + # super + hashables = XCObject.Hashables(self) + + # Use the hashables of the weak objects that this object refers to. + hashables.extend(self._properties['targetProxy'].Hashables()) + return hashables + + +class PBXReferenceProxy(XCFileLikeElement): + _schema = XCFileLikeElement._schema.copy() + _schema.update({ + 'fileType': [0, str, 0, 1], + 'path': [0, str, 0, 1], + 'remoteRef': [0, PBXContainerItemProxy, 1, 1], + }) + + +class XCTarget(XCRemoteObject): + # An XCTarget is really just an XCObject, the XCRemoteObject thing is just + # to allow PBXProject to be used in the remoteGlobalIDString property of + # PBXContainerItemProxy. + # + # Setting a "name" property at instantiation may also affect "productName", + # which may in turn affect the "PRODUCT_NAME" build setting in children of + # "buildConfigurationList". See __init__ below. + _schema = XCRemoteObject._schema.copy() + _schema.update({ + 'buildConfigurationList': [0, XCConfigurationList, 1, 1, + XCConfigurationList()], + 'buildPhases': [1, XCBuildPhase, 1, 1, []], + 'dependencies': [1, PBXTargetDependency, 1, 1, []], + 'name': [0, str, 0, 1], + 'productName': [0, str, 0, 1], + }) + + def __init__(self, properties=None, id=None, parent=None, + force_outdir=None, force_prefix=None, force_extension=None): + # super + XCRemoteObject.__init__(self, properties, id, parent) + + # Set up additional defaults not expressed in the schema. If a "name" + # property was supplied, set "productName" if it is not present. Also set + # the "PRODUCT_NAME" build setting in each configuration, but only if + # the setting is not present in any build configuration. + if 'name' in self._properties: + if not 'productName' in self._properties: + self.SetProperty('productName', self._properties['name']) + + if 'productName' in self._properties: + if 'buildConfigurationList' in self._properties: + configs = self._properties['buildConfigurationList'] + if configs.HasBuildSetting('PRODUCT_NAME') == 0: + configs.SetBuildSetting('PRODUCT_NAME', + self._properties['productName']) + + def AddDependency(self, other): + pbxproject = self.PBXProjectAncestor() + other_pbxproject = other.PBXProjectAncestor() + if pbxproject == other_pbxproject: + # Add a dependency to another target in the same project file. + container = PBXContainerItemProxy({'containerPortal': pbxproject, + 'proxyType': 1, + 'remoteGlobalIDString': other, + 'remoteInfo': other.Name()}) + dependency = PBXTargetDependency({'target': other, + 'targetProxy': container}) + self.AppendProperty('dependencies', dependency) + else: + # Add a dependency to a target in a different project file. + other_project_ref = \ + pbxproject.AddOrGetProjectReference(other_pbxproject)[1] + container = PBXContainerItemProxy({ + 'containerPortal': other_project_ref, + 'proxyType': 1, + 'remoteGlobalIDString': other, + 'remoteInfo': other.Name(), + }) + dependency = PBXTargetDependency({'name': other.Name(), + 'targetProxy': container}) + self.AppendProperty('dependencies', dependency) + + # Proxy all of these through to the build configuration list. + + def ConfigurationNamed(self, name): + return self._properties['buildConfigurationList'].ConfigurationNamed(name) + + def DefaultConfiguration(self): + return self._properties['buildConfigurationList'].DefaultConfiguration() + + def HasBuildSetting(self, key): + return self._properties['buildConfigurationList'].HasBuildSetting(key) + + def GetBuildSetting(self, key): + return self._properties['buildConfigurationList'].GetBuildSetting(key) + + def SetBuildSetting(self, key, value): + return self._properties['buildConfigurationList'].SetBuildSetting(key, \ + value) + + def AppendBuildSetting(self, key, value): + return self._properties['buildConfigurationList'].AppendBuildSetting(key, \ + value) + + def DelBuildSetting(self, key): + return self._properties['buildConfigurationList'].DelBuildSetting(key) + + +# Redefine the type of the "target" property. See PBXTargetDependency._schema +# above. +PBXTargetDependency._schema['target'][1] = XCTarget + + +class PBXNativeTarget(XCTarget): + # buildPhases is overridden in the schema to be able to set defaults. + # + # NOTE: Contrary to most objects, it is advisable to set parent when + # constructing PBXNativeTarget. A parent of an XCTarget must be a PBXProject + # object. A parent reference is required for a PBXNativeTarget during + # construction to be able to set up the target defaults for productReference, + # because a PBXBuildFile object must be created for the target and it must + # be added to the PBXProject's mainGroup hierarchy. + _schema = XCTarget._schema.copy() + _schema.update({ + 'buildPhases': [1, XCBuildPhase, 1, 1, + [PBXSourcesBuildPhase(), PBXFrameworksBuildPhase()]], + 'buildRules': [1, PBXBuildRule, 1, 1, []], + 'productReference': [0, PBXFileReference, 0, 1], + 'productType': [0, str, 0, 1], + }) + + # Mapping from Xcode product-types to settings. The settings are: + # filetype : used for explicitFileType in the project file + # prefix : the prefix for the file name + # suffix : the suffix for the file name + _product_filetypes = { + 'com.apple.product-type.application': ['wrapper.application', + '', '.app'], + 'com.apple.product-type.application.watchapp': ['wrapper.application', + '', '.app'], + 'com.apple.product-type.watchkit-extension': ['wrapper.app-extension', + '', '.appex'], + 'com.apple.product-type.app-extension': ['wrapper.app-extension', + '', '.appex'], + 'com.apple.product-type.bundle': ['wrapper.cfbundle', + '', '.bundle'], + 'com.apple.product-type.framework': ['wrapper.framework', + '', '.framework'], + 'com.apple.product-type.library.dynamic': ['compiled.mach-o.dylib', + 'lib', '.dylib'], + 'com.apple.product-type.library.static': ['archive.ar', + 'lib', '.a'], + 'com.apple.product-type.tool': ['compiled.mach-o.executable', + '', ''], + 'com.apple.product-type.bundle.unit-test': ['wrapper.cfbundle', + '', '.xctest'], + 'com.googlecode.gyp.xcode.bundle': ['compiled.mach-o.dylib', + '', '.so'], + 'com.apple.product-type.kernel-extension': ['wrapper.kext', + '', '.kext'], + } + + def __init__(self, properties=None, id=None, parent=None, + force_outdir=None, force_prefix=None, force_extension=None): + # super + XCTarget.__init__(self, properties, id, parent) + + if 'productName' in self._properties and \ + 'productType' in self._properties and \ + not 'productReference' in self._properties and \ + self._properties['productType'] in self._product_filetypes: + products_group = None + pbxproject = self.PBXProjectAncestor() + if pbxproject != None: + products_group = pbxproject.ProductsGroup() + + if products_group != None: + (filetype, prefix, suffix) = \ + self._product_filetypes[self._properties['productType']] + # Xcode does not have a distinct type for loadable modules that are + # pure BSD targets (not in a bundle wrapper). GYP allows such modules + # to be specified by setting a target type to loadable_module without + # having mac_bundle set. These are mapped to the pseudo-product type + # com.googlecode.gyp.xcode.bundle. + # + # By picking up this special type and converting it to a dynamic + # library (com.apple.product-type.library.dynamic) with fix-ups, + # single-file loadable modules can be produced. + # + # MACH_O_TYPE is changed to mh_bundle to produce the proper file type + # (as opposed to mh_dylib). In order for linking to succeed, + # DYLIB_CURRENT_VERSION and DYLIB_COMPATIBILITY_VERSION must be + # cleared. They are meaningless for type mh_bundle. + # + # Finally, the .so extension is forcibly applied over the default + # (.dylib), unless another forced extension is already selected. + # .dylib is plainly wrong, and .bundle is used by loadable_modules in + # bundle wrappers (com.apple.product-type.bundle). .so seems an odd + # choice because it's used as the extension on many other systems that + # don't distinguish between linkable shared libraries and non-linkable + # loadable modules, but there's precedent: Python loadable modules on + # Mac OS X use an .so extension. + if self._properties['productType'] == 'com.googlecode.gyp.xcode.bundle': + self._properties['productType'] = \ + 'com.apple.product-type.library.dynamic' + self.SetBuildSetting('MACH_O_TYPE', 'mh_bundle') + self.SetBuildSetting('DYLIB_CURRENT_VERSION', '') + self.SetBuildSetting('DYLIB_COMPATIBILITY_VERSION', '') + if force_extension is None: + force_extension = suffix[1:] + + if self._properties['productType'] == \ + 'com.apple.product-type-bundle.unit.test': + if force_extension is None: + force_extension = suffix[1:] + + if force_extension is not None: + # If it's a wrapper (bundle), set WRAPPER_EXTENSION. + # Extension override. + suffix = '.' + force_extension + if filetype.startswith('wrapper.'): + self.SetBuildSetting('WRAPPER_EXTENSION', force_extension) + else: + self.SetBuildSetting('EXECUTABLE_EXTENSION', force_extension) + + if filetype.startswith('compiled.mach-o.executable'): + product_name = self._properties['productName'] + product_name += suffix + suffix = '' + self.SetProperty('productName', product_name) + self.SetBuildSetting('PRODUCT_NAME', product_name) + + # Xcode handles most prefixes based on the target type, however there + # are exceptions. If a "BSD Dynamic Library" target is added in the + # Xcode UI, Xcode sets EXECUTABLE_PREFIX. This check duplicates that + # behavior. + if force_prefix is not None: + prefix = force_prefix + if filetype.startswith('wrapper.'): + self.SetBuildSetting('WRAPPER_PREFIX', prefix) + else: + self.SetBuildSetting('EXECUTABLE_PREFIX', prefix) + + if force_outdir is not None: + self.SetBuildSetting('TARGET_BUILD_DIR', force_outdir) + + # TODO(tvl): Remove the below hack. + # http://code.google.com/p/gyp/issues/detail?id=122 + + # Some targets include the prefix in the target_name. These targets + # really should just add a product_name setting that doesn't include + # the prefix. For example: + # target_name = 'libevent', product_name = 'event' + # This check cleans up for them. + product_name = self._properties['productName'] + prefix_len = len(prefix) + if prefix_len and (product_name[:prefix_len] == prefix): + product_name = product_name[prefix_len:] + self.SetProperty('productName', product_name) + self.SetBuildSetting('PRODUCT_NAME', product_name) + + ref_props = { + 'explicitFileType': filetype, + 'includeInIndex': 0, + 'path': prefix + product_name + suffix, + 'sourceTree': 'BUILT_PRODUCTS_DIR', + } + file_ref = PBXFileReference(ref_props) + products_group.AppendChild(file_ref) + self.SetProperty('productReference', file_ref) + + def GetBuildPhaseByType(self, type): + if not 'buildPhases' in self._properties: + return None + + the_phase = None + for phase in self._properties['buildPhases']: + if isinstance(phase, type): + # Some phases may be present in multiples in a well-formed project file, + # but phases like PBXSourcesBuildPhase may only be present singly, and + # this function is intended as an aid to GetBuildPhaseByType. Loop + # over the entire list of phases and assert if more than one of the + # desired type is found. + assert the_phase is None + the_phase = phase + + return the_phase + + def HeadersPhase(self): + headers_phase = self.GetBuildPhaseByType(PBXHeadersBuildPhase) + if headers_phase is None: + headers_phase = PBXHeadersBuildPhase() + + # The headers phase should come before the resources, sources, and + # frameworks phases, if any. + insert_at = len(self._properties['buildPhases']) + for index in xrange(0, len(self._properties['buildPhases'])): + phase = self._properties['buildPhases'][index] + if isinstance(phase, PBXResourcesBuildPhase) or \ + isinstance(phase, PBXSourcesBuildPhase) or \ + isinstance(phase, PBXFrameworksBuildPhase): + insert_at = index + break + + self._properties['buildPhases'].insert(insert_at, headers_phase) + headers_phase.parent = self + + return headers_phase + + def ResourcesPhase(self): + resources_phase = self.GetBuildPhaseByType(PBXResourcesBuildPhase) + if resources_phase is None: + resources_phase = PBXResourcesBuildPhase() + + # The resources phase should come before the sources and frameworks + # phases, if any. + insert_at = len(self._properties['buildPhases']) + for index in xrange(0, len(self._properties['buildPhases'])): + phase = self._properties['buildPhases'][index] + if isinstance(phase, PBXSourcesBuildPhase) or \ + isinstance(phase, PBXFrameworksBuildPhase): + insert_at = index + break + + self._properties['buildPhases'].insert(insert_at, resources_phase) + resources_phase.parent = self + + return resources_phase + + def SourcesPhase(self): + sources_phase = self.GetBuildPhaseByType(PBXSourcesBuildPhase) + if sources_phase is None: + sources_phase = PBXSourcesBuildPhase() + self.AppendProperty('buildPhases', sources_phase) + + return sources_phase + + def FrameworksPhase(self): + frameworks_phase = self.GetBuildPhaseByType(PBXFrameworksBuildPhase) + if frameworks_phase is None: + frameworks_phase = PBXFrameworksBuildPhase() + self.AppendProperty('buildPhases', frameworks_phase) + + return frameworks_phase + + def AddDependency(self, other): + # super + XCTarget.AddDependency(self, other) + + static_library_type = 'com.apple.product-type.library.static' + shared_library_type = 'com.apple.product-type.library.dynamic' + framework_type = 'com.apple.product-type.framework' + if isinstance(other, PBXNativeTarget) and \ + 'productType' in self._properties and \ + self._properties['productType'] != static_library_type and \ + 'productType' in other._properties and \ + (other._properties['productType'] == static_library_type or \ + ((other._properties['productType'] == shared_library_type or \ + other._properties['productType'] == framework_type) and \ + ((not other.HasBuildSetting('MACH_O_TYPE')) or + other.GetBuildSetting('MACH_O_TYPE') != 'mh_bundle'))): + + file_ref = other.GetProperty('productReference') + + pbxproject = self.PBXProjectAncestor() + other_pbxproject = other.PBXProjectAncestor() + if pbxproject != other_pbxproject: + other_project_product_group = \ + pbxproject.AddOrGetProjectReference(other_pbxproject)[0] + file_ref = other_project_product_group.GetChildByRemoteObject(file_ref) + + self.FrameworksPhase().AppendProperty('files', + PBXBuildFile({'fileRef': file_ref})) + + +class PBXAggregateTarget(XCTarget): + pass + + +class PBXProject(XCContainerPortal): + # A PBXProject is really just an XCObject, the XCContainerPortal thing is + # just to allow PBXProject to be used in the containerPortal property of + # PBXContainerItemProxy. + """ + + Attributes: + path: "sample.xcodeproj". TODO(mark) Document me! + _other_pbxprojects: A dictionary, keyed by other PBXProject objects. Each + value is a reference to the dict in the + projectReferences list associated with the keyed + PBXProject. + """ + + _schema = XCContainerPortal._schema.copy() + _schema.update({ + 'attributes': [0, dict, 0, 0], + 'buildConfigurationList': [0, XCConfigurationList, 1, 1, + XCConfigurationList()], + 'compatibilityVersion': [0, str, 0, 1, 'Xcode 3.2'], + 'hasScannedForEncodings': [0, int, 0, 1, 1], + 'mainGroup': [0, PBXGroup, 1, 1, PBXGroup()], + 'projectDirPath': [0, str, 0, 1, ''], + 'projectReferences': [1, dict, 0, 0], + 'projectRoot': [0, str, 0, 1, ''], + 'targets': [1, XCTarget, 1, 1, []], + }) + + def __init__(self, properties=None, id=None, parent=None, path=None): + self.path = path + self._other_pbxprojects = {} + # super + return XCContainerPortal.__init__(self, properties, id, parent) + + def Name(self): + name = self.path + if name[-10:] == '.xcodeproj': + name = name[:-10] + return posixpath.basename(name) + + def Path(self): + return self.path + + def Comment(self): + return 'Project object' + + def Children(self): + # super + children = XCContainerPortal.Children(self) + + # Add children that the schema doesn't know about. Maybe there's a more + # elegant way around this, but this is the only case where we need to own + # objects in a dictionary (that is itself in a list), and three lines for + # a one-off isn't that big a deal. + if 'projectReferences' in self._properties: + for reference in self._properties['projectReferences']: + children.append(reference['ProductGroup']) + + return children + + def PBXProjectAncestor(self): + return self + + def _GroupByName(self, name): + if not 'mainGroup' in self._properties: + self.SetProperty('mainGroup', PBXGroup()) + + main_group = self._properties['mainGroup'] + group = main_group.GetChildByName(name) + if group is None: + group = PBXGroup({'name': name}) + main_group.AppendChild(group) + + return group + + # SourceGroup and ProductsGroup are created by default in Xcode's own + # templates. + def SourceGroup(self): + return self._GroupByName('Source') + + def ProductsGroup(self): + return self._GroupByName('Products') + + # IntermediatesGroup is used to collect source-like files that are generated + # by rules or script phases and are placed in intermediate directories such + # as DerivedSources. + def IntermediatesGroup(self): + return self._GroupByName('Intermediates') + + # FrameworksGroup and ProjectsGroup are top-level groups used to collect + # frameworks and projects. + def FrameworksGroup(self): + return self._GroupByName('Frameworks') + + def ProjectsGroup(self): + return self._GroupByName('Projects') + + def RootGroupForPath(self, path): + """Returns a PBXGroup child of this object to which path should be added. + + This method is intended to choose between SourceGroup and + IntermediatesGroup on the basis of whether path is present in a source + directory or an intermediates directory. For the purposes of this + determination, any path located within a derived file directory such as + PROJECT_DERIVED_FILE_DIR is treated as being in an intermediates + directory. + + The returned value is a two-element tuple. The first element is the + PBXGroup, and the second element specifies whether that group should be + organized hierarchically (True) or as a single flat list (False). + """ + + # TODO(mark): make this a class variable and bind to self on call? + # Also, this list is nowhere near exhaustive. + # INTERMEDIATE_DIR and SHARED_INTERMEDIATE_DIR are used by + # gyp.generator.xcode. There should probably be some way for that module + # to push the names in, rather than having to hard-code them here. + source_tree_groups = { + 'DERIVED_FILE_DIR': (self.IntermediatesGroup, True), + 'INTERMEDIATE_DIR': (self.IntermediatesGroup, True), + 'PROJECT_DERIVED_FILE_DIR': (self.IntermediatesGroup, True), + 'SHARED_INTERMEDIATE_DIR': (self.IntermediatesGroup, True), + } + + (source_tree, path) = SourceTreeAndPathFromPath(path) + if source_tree != None and source_tree in source_tree_groups: + (group_func, hierarchical) = source_tree_groups[source_tree] + group = group_func() + return (group, hierarchical) + + # TODO(mark): make additional choices based on file extension. + + return (self.SourceGroup(), True) + + def AddOrGetFileInRootGroup(self, path): + """Returns a PBXFileReference corresponding to path in the correct group + according to RootGroupForPath's heuristics. + + If an existing PBXFileReference for path exists, it will be returned. + Otherwise, one will be created and returned. + """ + + (group, hierarchical) = self.RootGroupForPath(path) + return group.AddOrGetFileByPath(path, hierarchical) + + def RootGroupsTakeOverOnlyChildren(self, recurse=False): + """Calls TakeOverOnlyChild for all groups in the main group.""" + + for group in self._properties['mainGroup']._properties['children']: + if isinstance(group, PBXGroup): + group.TakeOverOnlyChild(recurse) + + def SortGroups(self): + # Sort the children of the mainGroup (like "Source" and "Products") + # according to their defined order. + self._properties['mainGroup']._properties['children'] = \ + sorted(self._properties['mainGroup']._properties['children'], + cmp=lambda x,y: x.CompareRootGroup(y)) + + # Sort everything else by putting group before files, and going + # alphabetically by name within sections of groups and files. SortGroup + # is recursive. + for group in self._properties['mainGroup']._properties['children']: + if not isinstance(group, PBXGroup): + continue + + if group.Name() == 'Products': + # The Products group is a special case. Instead of sorting + # alphabetically, sort things in the order of the targets that + # produce the products. To do this, just build up a new list of + # products based on the targets. + products = [] + for target in self._properties['targets']: + if not isinstance(target, PBXNativeTarget): + continue + product = target._properties['productReference'] + # Make sure that the product is already in the products group. + assert product in group._properties['children'] + products.append(product) + + # Make sure that this process doesn't miss anything that was already + # in the products group. + assert len(products) == len(group._properties['children']) + group._properties['children'] = products + else: + group.SortGroup() + + def AddOrGetProjectReference(self, other_pbxproject): + """Add a reference to another project file (via PBXProject object) to this + one. + + Returns [ProductGroup, ProjectRef]. ProductGroup is a PBXGroup object in + this project file that contains a PBXReferenceProxy object for each + product of each PBXNativeTarget in the other project file. ProjectRef is + a PBXFileReference to the other project file. + + If this project file already references the other project file, the + existing ProductGroup and ProjectRef are returned. The ProductGroup will + still be updated if necessary. + """ + + if not 'projectReferences' in self._properties: + self._properties['projectReferences'] = [] + + product_group = None + project_ref = None + + if not other_pbxproject in self._other_pbxprojects: + # This project file isn't yet linked to the other one. Establish the + # link. + product_group = PBXGroup({'name': 'Products'}) + + # ProductGroup is strong. + product_group.parent = self + + # There's nothing unique about this PBXGroup, and if left alone, it will + # wind up with the same set of hashables as all other PBXGroup objects + # owned by the projectReferences list. Add the hashables of the + # remote PBXProject that it's related to. + product_group._hashables.extend(other_pbxproject.Hashables()) + + # The other project reports its path as relative to the same directory + # that this project's path is relative to. The other project's path + # is not necessarily already relative to this project. Figure out the + # pathname that this project needs to use to refer to the other one. + this_path = posixpath.dirname(self.Path()) + projectDirPath = self.GetProperty('projectDirPath') + if projectDirPath: + if posixpath.isabs(projectDirPath[0]): + this_path = projectDirPath + else: + this_path = posixpath.join(this_path, projectDirPath) + other_path = gyp.common.RelativePath(other_pbxproject.Path(), this_path) + + # ProjectRef is weak (it's owned by the mainGroup hierarchy). + project_ref = PBXFileReference({ + 'lastKnownFileType': 'wrapper.pb-project', + 'path': other_path, + 'sourceTree': 'SOURCE_ROOT', + }) + self.ProjectsGroup().AppendChild(project_ref) + + ref_dict = {'ProductGroup': product_group, 'ProjectRef': project_ref} + self._other_pbxprojects[other_pbxproject] = ref_dict + self.AppendProperty('projectReferences', ref_dict) + + # Xcode seems to sort this list case-insensitively + self._properties['projectReferences'] = \ + sorted(self._properties['projectReferences'], cmp=lambda x,y: + cmp(x['ProjectRef'].Name().lower(), + y['ProjectRef'].Name().lower())) + else: + # The link already exists. Pull out the relevnt data. + project_ref_dict = self._other_pbxprojects[other_pbxproject] + product_group = project_ref_dict['ProductGroup'] + project_ref = project_ref_dict['ProjectRef'] + + self._SetUpProductReferences(other_pbxproject, product_group, project_ref) + + inherit_unique_symroot = self._AllSymrootsUnique(other_pbxproject, False) + targets = other_pbxproject.GetProperty('targets') + if all(self._AllSymrootsUnique(t, inherit_unique_symroot) for t in targets): + dir_path = project_ref._properties['path'] + product_group._hashables.extend(dir_path) + + return [product_group, project_ref] + + def _AllSymrootsUnique(self, target, inherit_unique_symroot): + # Returns True if all configurations have a unique 'SYMROOT' attribute. + # The value of inherit_unique_symroot decides, if a configuration is assumed + # to inherit a unique 'SYMROOT' attribute from its parent, if it doesn't + # define an explicit value for 'SYMROOT'. + symroots = self._DefinedSymroots(target) + for s in self._DefinedSymroots(target): + if (s is not None and not self._IsUniqueSymrootForTarget(s) or + s is None and not inherit_unique_symroot): + return False + return True if symroots else inherit_unique_symroot + + def _DefinedSymroots(self, target): + # Returns all values for the 'SYMROOT' attribute defined in all + # configurations for this target. If any configuration doesn't define the + # 'SYMROOT' attribute, None is added to the returned set. If all + # configurations don't define the 'SYMROOT' attribute, an empty set is + # returned. + config_list = target.GetProperty('buildConfigurationList') + symroots = set() + for config in config_list.GetProperty('buildConfigurations'): + setting = config.GetProperty('buildSettings') + if 'SYMROOT' in setting: + symroots.add(setting['SYMROOT']) + else: + symroots.add(None) + if len(symroots) == 1 and None in symroots: + return set() + return symroots + + def _IsUniqueSymrootForTarget(self, symroot): + # This method returns True if all configurations in target contain a + # 'SYMROOT' attribute that is unique for the given target. A value is + # unique, if the Xcode macro '$SRCROOT' appears in it in any form. + uniquifier = ['$SRCROOT', '$(SRCROOT)'] + if any(x in symroot for x in uniquifier): + return True + return False + + def _SetUpProductReferences(self, other_pbxproject, product_group, + project_ref): + # TODO(mark): This only adds references to products in other_pbxproject + # when they don't exist in this pbxproject. Perhaps it should also + # remove references from this pbxproject that are no longer present in + # other_pbxproject. Perhaps it should update various properties if they + # change. + for target in other_pbxproject._properties['targets']: + if not isinstance(target, PBXNativeTarget): + continue + + other_fileref = target._properties['productReference'] + if product_group.GetChildByRemoteObject(other_fileref) is None: + # Xcode sets remoteInfo to the name of the target and not the name + # of its product, despite this proxy being a reference to the product. + container_item = PBXContainerItemProxy({ + 'containerPortal': project_ref, + 'proxyType': 2, + 'remoteGlobalIDString': other_fileref, + 'remoteInfo': target.Name() + }) + # TODO(mark): Does sourceTree get copied straight over from the other + # project? Can the other project ever have lastKnownFileType here + # instead of explicitFileType? (Use it if so?) Can path ever be + # unset? (I don't think so.) Can other_fileref have name set, and + # does it impact the PBXReferenceProxy if so? These are the questions + # that perhaps will be answered one day. + reference_proxy = PBXReferenceProxy({ + 'fileType': other_fileref._properties['explicitFileType'], + 'path': other_fileref._properties['path'], + 'sourceTree': other_fileref._properties['sourceTree'], + 'remoteRef': container_item, + }) + + product_group.AppendChild(reference_proxy) + + def SortRemoteProductReferences(self): + # For each remote project file, sort the associated ProductGroup in the + # same order that the targets are sorted in the remote project file. This + # is the sort order used by Xcode. + + def CompareProducts(x, y, remote_products): + # x and y are PBXReferenceProxy objects. Go through their associated + # PBXContainerItem to get the remote PBXFileReference, which will be + # present in the remote_products list. + x_remote = x._properties['remoteRef']._properties['remoteGlobalIDString'] + y_remote = y._properties['remoteRef']._properties['remoteGlobalIDString'] + x_index = remote_products.index(x_remote) + y_index = remote_products.index(y_remote) + + # Use the order of each remote PBXFileReference in remote_products to + # determine the sort order. + return cmp(x_index, y_index) + + for other_pbxproject, ref_dict in self._other_pbxprojects.iteritems(): + # Build up a list of products in the remote project file, ordered the + # same as the targets that produce them. + remote_products = [] + for target in other_pbxproject._properties['targets']: + if not isinstance(target, PBXNativeTarget): + continue + remote_products.append(target._properties['productReference']) + + # Sort the PBXReferenceProxy children according to the list of remote + # products. + product_group = ref_dict['ProductGroup'] + product_group._properties['children'] = sorted( + product_group._properties['children'], + cmp=lambda x, y, rp=remote_products: CompareProducts(x, y, rp)) + + +class XCProjectFile(XCObject): + _schema = XCObject._schema.copy() + _schema.update({ + 'archiveVersion': [0, int, 0, 1, 1], + 'classes': [0, dict, 0, 1, {}], + 'objectVersion': [0, int, 0, 1, 46], + 'rootObject': [0, PBXProject, 1, 1], + }) + + def ComputeIDs(self, recursive=True, overwrite=True, hash=None): + # Although XCProjectFile is implemented here as an XCObject, it's not a + # proper object in the Xcode sense, and it certainly doesn't have its own + # ID. Pass through an attempt to update IDs to the real root object. + if recursive: + self._properties['rootObject'].ComputeIDs(recursive, overwrite, hash) + + def Print(self, file=sys.stdout): + self.VerifyHasRequiredProperties() + + # Add the special "objects" property, which will be caught and handled + # separately during printing. This structure allows a fairly standard + # loop do the normal printing. + self._properties['objects'] = {} + self._XCPrint(file, 0, '// !$*UTF8*$!\n') + if self._should_print_single_line: + self._XCPrint(file, 0, '{ ') + else: + self._XCPrint(file, 0, '{\n') + for property, value in sorted(self._properties.iteritems(), + cmp=lambda x, y: cmp(x, y)): + if property == 'objects': + self._PrintObjects(file) + else: + self._XCKVPrint(file, 1, property, value) + self._XCPrint(file, 0, '}\n') + del self._properties['objects'] + + def _PrintObjects(self, file): + if self._should_print_single_line: + self._XCPrint(file, 0, 'objects = {') + else: + self._XCPrint(file, 1, 'objects = {\n') + + objects_by_class = {} + for object in self.Descendants(): + if object == self: + continue + class_name = object.__class__.__name__ + if not class_name in objects_by_class: + objects_by_class[class_name] = [] + objects_by_class[class_name].append(object) + + for class_name in sorted(objects_by_class): + self._XCPrint(file, 0, '\n') + self._XCPrint(file, 0, '/* Begin ' + class_name + ' section */\n') + for object in sorted(objects_by_class[class_name], + cmp=lambda x, y: cmp(x.id, y.id)): + object.Print(file) + self._XCPrint(file, 0, '/* End ' + class_name + ' section */\n') + + if self._should_print_single_line: + self._XCPrint(file, 0, '}; ') + else: + self._XCPrint(file, 1, '};\n') diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py new file mode 100644 index 0000000000000..5de848158d289 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py @@ -0,0 +1,69 @@ +# Copyright (c) 2011 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. + +"""Applies a fix to CR LF TAB handling in xml.dom. + +Fixes this: http://code.google.com/p/chromium/issues/detail?id=76293 +Working around this: http://bugs.python.org/issue5752 +TODO(bradnelson): Consider dropping this when we drop XP support. +""" + + +import xml.dom.minidom + + +def _Replacement_write_data(writer, data, is_attrib=False): + """Writes datachars to writer.""" + data = data.replace("&", "&").replace("<", "<") + data = data.replace("\"", """).replace(">", ">") + if is_attrib: + data = data.replace( + "\r", " ").replace( + "\n", " ").replace( + "\t", " ") + writer.write(data) + + +def _Replacement_writexml(self, writer, indent="", addindent="", newl=""): + # indent = current indentation + # addindent = indentation to add to higher levels + # newl = newline string + writer.write(indent+"<" + self.tagName) + + attrs = self._get_attributes() + a_names = attrs.keys() + a_names.sort() + + for a_name in a_names: + writer.write(" %s=\"" % a_name) + _Replacement_write_data(writer, attrs[a_name].value, is_attrib=True) + writer.write("\"") + if self.childNodes: + writer.write(">%s" % newl) + for node in self.childNodes: + node.writexml(writer, indent + addindent, addindent, newl) + writer.write("%s%s" % (indent, self.tagName, newl)) + else: + writer.write("/>%s" % newl) + + +class XmlFix(object): + """Object to manage temporary patching of xml.dom.minidom.""" + + def __init__(self): + # Preserve current xml.dom.minidom functions. + self.write_data = xml.dom.minidom._write_data + self.writexml = xml.dom.minidom.Element.writexml + # Inject replacement versions of a function and a method. + xml.dom.minidom._write_data = _Replacement_write_data + xml.dom.minidom.Element.writexml = _Replacement_writexml + + def Cleanup(self): + if self.write_data: + xml.dom.minidom._write_data = self.write_data + xml.dom.minidom.Element.writexml = self.writexml + self.write_data = None + + def __del__(self): + self.Cleanup() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples new file mode 100755 index 0000000000000..804b618998747 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples @@ -0,0 +1,81 @@ +#!/usr/bin/python + +# Copyright (c) 2009 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. + +import os.path +import shutil +import sys + + +gyps = [ + 'app/app.gyp', + 'base/base.gyp', + 'build/temp_gyp/googleurl.gyp', + 'build/all.gyp', + 'build/common.gypi', + 'build/external_code.gypi', + 'chrome/test/security_tests/security_tests.gyp', + 'chrome/third_party/hunspell/hunspell.gyp', + 'chrome/chrome.gyp', + 'media/media.gyp', + 'net/net.gyp', + 'printing/printing.gyp', + 'sdch/sdch.gyp', + 'skia/skia.gyp', + 'testing/gmock.gyp', + 'testing/gtest.gyp', + 'third_party/bzip2/bzip2.gyp', + 'third_party/icu38/icu38.gyp', + 'third_party/libevent/libevent.gyp', + 'third_party/libjpeg/libjpeg.gyp', + 'third_party/libpng/libpng.gyp', + 'third_party/libxml/libxml.gyp', + 'third_party/libxslt/libxslt.gyp', + 'third_party/lzma_sdk/lzma_sdk.gyp', + 'third_party/modp_b64/modp_b64.gyp', + 'third_party/npapi/npapi.gyp', + 'third_party/sqlite/sqlite.gyp', + 'third_party/zlib/zlib.gyp', + 'v8/tools/gyp/v8.gyp', + 'webkit/activex_shim/activex_shim.gyp', + 'webkit/activex_shim_dll/activex_shim_dll.gyp', + 'webkit/build/action_csspropertynames.py', + 'webkit/build/action_cssvaluekeywords.py', + 'webkit/build/action_jsconfig.py', + 'webkit/build/action_makenames.py', + 'webkit/build/action_maketokenizer.py', + 'webkit/build/action_useragentstylesheets.py', + 'webkit/build/rule_binding.py', + 'webkit/build/rule_bison.py', + 'webkit/build/rule_gperf.py', + 'webkit/tools/test_shell/test_shell.gyp', + 'webkit/webkit.gyp', +] + + +def Main(argv): + if len(argv) != 3 or argv[1] not in ['push', 'pull']: + print 'Usage: %s push/pull PATH_TO_CHROME' % argv[0] + return 1 + + path_to_chrome = argv[2] + + for g in gyps: + chrome_file = os.path.join(path_to_chrome, g) + local_file = os.path.join(os.path.dirname(argv[0]), os.path.split(g)[1]) + if argv[1] == 'push': + print 'Copying %s to %s' % (local_file, chrome_file) + shutil.copyfile(local_file, chrome_file) + elif argv[1] == 'pull': + print 'Copying %s to %s' % (chrome_file, local_file) + shutil.copyfile(chrome_file, local_file) + else: + assert False + + return 0 + + +if __name__ == '__main__': + sys.exit(Main(sys.argv)) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples.bat b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples.bat new file mode 100644 index 0000000000000..778d9c90f0606 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples.bat @@ -0,0 +1,5 @@ +@rem Copyright (c) 2009 Google Inc. All rights reserved. +@rem Use of this source code is governed by a BSD-style license that can be +@rem found in the LICENSE file. + +@python %~dp0/samples %* diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/setup.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/setup.py new file mode 100755 index 0000000000000..75a42558d8026 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/setup.py @@ -0,0 +1,19 @@ +#!/usr/bin/env python + +# Copyright (c) 2009 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. + +from setuptools import setup + +setup( + name='gyp', + version='0.1', + description='Generate Your Projects', + author='Chromium Authors', + author_email='chromium-dev@googlegroups.com', + url='http://code.google.com/p/gyp', + package_dir = {'': 'pylib'}, + packages=['gyp', 'gyp.generator'], + entry_points = {'console_scripts': ['gyp=gyp:script_main'] } +) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/README b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/README new file mode 100644 index 0000000000000..712e4efbb7a06 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/README @@ -0,0 +1,15 @@ +pretty_vcproj: + Usage: pretty_vcproj.py "c:\path\to\vcproj.vcproj" [key1=value1] [key2=value2] + + They key/value pair are used to resolve vsprops name. + + For example, if I want to diff the base.vcproj project: + + pretty_vcproj.py z:\dev\src-chrome\src\base\build\base.vcproj "$(SolutionDir)=z:\dev\src-chrome\src\chrome\\" "$(CHROMIUM_BUILD)=" "$(CHROME_BUILD_TYPE)=" > orignal.txt + pretty_vcproj.py z:\dev\src-chrome\src\base\base_gyp.vcproj "$(SolutionDir)=z:\dev\src-chrome\src\chrome\\" "$(CHROMIUM_BUILD)=" "$(CHROME_BUILD_TYPE)=" > gyp.txt + + And you can use your favorite diff tool to see the changes. + + Note: In the case of base.vcproj, the original vcproj is one level up the generated one. + I suggest you do a search and replace for '"..\' and replace it with '"' in original.txt + before you perform the diff. \ No newline at end of file diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/README b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/README new file mode 100644 index 0000000000000..2492a2c2f8f17 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/README @@ -0,0 +1,5 @@ +Specifications contains syntax formatters for Xcode 3. These do not appear to be supported yet on Xcode 4. To use these with Xcode 3 please install both the gyp.pbfilespec and gyp.xclangspec files in + +~/Library/Application Support/Developer/Shared/Xcode/Specifications/ + +and restart Xcode. \ No newline at end of file diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.pbfilespec b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.pbfilespec new file mode 100644 index 0000000000000..85e2e268a51b7 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.pbfilespec @@ -0,0 +1,27 @@ +/* + gyp.pbfilespec + GYP source file spec for Xcode 3 + + There is not much documentation available regarding the format + of .pbfilespec files. As a starting point, see for instance the + outdated documentation at: + http://maxao.free.fr/xcode-plugin-interface/specifications.html + and the files in: + /Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources/ + + Place this file in directory: + ~/Library/Application Support/Developer/Shared/Xcode/Specifications/ +*/ + +( + { + Identifier = sourcecode.gyp; + BasedOn = sourcecode; + Name = "GYP Files"; + Extensions = ("gyp", "gypi"); + MIMETypes = ("text/gyp"); + Language = "xcode.lang.gyp"; + IsTextFile = YES; + IsSourceFile = YES; + } +) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.xclangspec b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.xclangspec new file mode 100644 index 0000000000000..3b3506d319e0f --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.xclangspec @@ -0,0 +1,226 @@ +/* + Copyright (c) 2011 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. + + gyp.xclangspec + GYP language specification for Xcode 3 + + There is not much documentation available regarding the format + of .xclangspec files. As a starting point, see for instance the + outdated documentation at: + http://maxao.free.fr/xcode-plugin-interface/specifications.html + and the files in: + /Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources/ + + Place this file in directory: + ~/Library/Application Support/Developer/Shared/Xcode/Specifications/ +*/ + +( + + { + Identifier = "xcode.lang.gyp.keyword"; + Syntax = { + Words = ( + "and", + "or", + " (caar gyp-parse-history) target-point) + (setq gyp-parse-history (cdr gyp-parse-history)))) + +(defun gyp-parse-point () + "The point of the last parse state added by gyp-parse-to." + (caar gyp-parse-history)) + +(defun gyp-parse-sections () + "A list of section symbols holding at the last parse state point." + (cdar gyp-parse-history)) + +(defun gyp-inside-dictionary-p () + "Predicate returning true if the parser is inside a dictionary." + (not (eq (cadar gyp-parse-history) 'list))) + +(defun gyp-add-parse-history (point sections) + "Add parse state SECTIONS to the parse history at POINT so that parsing can be + resumed instantly." + (while (>= (caar gyp-parse-history) point) + (setq gyp-parse-history (cdr gyp-parse-history))) + (setq gyp-parse-history (cons (cons point sections) gyp-parse-history))) + +(defun gyp-parse-to (target-point) + "Parses from (point) to TARGET-POINT adding the parse state information to + gyp-parse-state-history. Parsing stops if TARGET-POINT is reached or if a + string literal has been parsed. Returns nil if no further parsing can be + done, otherwise returns the position of the start of a parsed string, leaving + the point at the end of the string." + (let ((parsing t) + string-start) + (while parsing + (setq string-start nil) + ;; Parse up to a character that starts a sexp, or if the nesting + ;; level decreases. + (let ((state (parse-partial-sexp (gyp-parse-point) + target-point + -1 + t)) + (sections (gyp-parse-sections))) + (if (= (nth 0 state) -1) + (setq sections (cdr sections)) ; pop out a level + (cond ((looking-at-p "['\"]") ; a string + (setq string-start (point)) + (goto-char (scan-sexps (point) 1)) + (if (gyp-inside-dictionary-p) + ;; Look for sections inside a dictionary + (let ((section (gyp-section-name + (buffer-substring-no-properties + (+ 1 string-start) + (- (point) 1))))) + (setq sections (cons section (cdr sections))))) + ;; Stop after the string so it can be fontified. + (setq target-point (point))) + ((looking-at-p "{") + ;; Inside a dictionary. Increase nesting. + (forward-char 1) + (setq sections (cons 'unknown sections))) + ((looking-at-p "\\[") + ;; Inside a list. Increase nesting + (forward-char 1) + (setq sections (cons 'list sections))) + ((not (eobp)) + ;; other + (forward-char 1)))) + (gyp-add-parse-history (point) sections) + (setq parsing (< (point) target-point)))) + string-start)) + +(defun gyp-section-at-point () + "Transform the last parse state, which is a list of nested sections and return + the section symbol that should be used to determine font-lock information for + the string. Can return nil indicating the string should not have any attached + section." + (let ((sections (gyp-parse-sections))) + (cond + ((eq (car sections) 'conditions) + ;; conditions can occur in a variables section, but we still want to + ;; highlight it as a keyword. + nil) + ((and (eq (car sections) 'list) + (eq (cadr sections) 'list)) + ;; conditions and sources can have items in [[ ]] + (caddr sections)) + (t (cadr sections))))) + +(defun gyp-section-match (limit) + "Parse from (point) to LIMIT returning by means of match data what was + matched. The group of the match indicates what style font-lock should apply. + See also `gyp-add-font-lock-keywords'." + (gyp-invalidate-parse-states-after (point)) + (let ((group nil) + (string-start t)) + (while (and (< (point) limit) + (not group) + string-start) + (setq string-start (gyp-parse-to limit)) + (if string-start + (setq group (case (gyp-section-at-point) + ('dependencies 1) + ('variables 2) + ('conditions 2) + ('sources 3) + ('defines 4) + (nil nil))))) + (if group + (progn + ;; Set the match data to indicate to the font-lock mechanism the + ;; highlighting to be performed. + (set-match-data (append (list string-start (point)) + (make-list (* (1- group) 2) nil) + (list (1+ string-start) (1- (point))))) + t)))) + +;;; Please see http://code.google.com/p/gyp/wiki/GypLanguageSpecification for +;;; canonical list of keywords. +(defun gyp-add-font-lock-keywords () + "Add gyp-mode keywords to font-lock mechanism." + ;; TODO(jknotten): Move all the keyword highlighting into gyp-section-match + ;; so that we can do the font-locking in a single font-lock pass. + (font-lock-add-keywords + nil + (list + ;; Top-level keywords + (list (concat "['\"]\\(" + (regexp-opt (list "action" "action_name" "actions" "cflags" + "cflags_cc" "conditions" "configurations" + "copies" "defines" "dependencies" "destination" + "direct_dependent_settings" + "export_dependent_settings" "extension" "files" + "include_dirs" "includes" "inputs" "ldflags" "libraries" + "link_settings" "mac_bundle" "message" + "msvs_external_rule" "outputs" "product_name" + "process_outputs_as_sources" "rules" "rule_name" + "sources" "suppress_wildcard" + "target_conditions" "target_defaults" + "target_defines" "target_name" "toolsets" + "targets" "type" "variables" "xcode_settings")) + "[!/+=]?\\)") 1 'font-lock-keyword-face t) + ;; Type of target + (list (concat "['\"]\\(" + (regexp-opt (list "loadable_module" "static_library" + "shared_library" "executable" "none")) + "\\)") 1 'font-lock-type-face t) + (list "\\(?:target\\|action\\)_name['\"]\\s-*:\\s-*['\"]\\([^ '\"]*\\)" 1 + 'font-lock-function-name-face t) + (list 'gyp-section-match + (list 1 'font-lock-function-name-face t t) ; dependencies + (list 2 'font-lock-variable-name-face t t) ; variables, conditions + (list 3 'font-lock-constant-face t t) ; sources + (list 4 'font-lock-preprocessor-face t t)) ; preprocessor + ;; Variable expansion + (list "<@?(\\([^\n )]+\\))" 1 'font-lock-variable-name-face t) + ;; Command expansion + (list " "%s"' % (src, dst) + + print '}' + + +def main(): + if len(sys.argv) < 2: + print >>sys.stderr, __doc__ + print >>sys.stderr + print >>sys.stderr, 'usage: %s target1 target2...' % (sys.argv[0]) + return 1 + + edges = LoadEdges('dump.json', sys.argv[1:]) + + WriteGraph(edges) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_gyp.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_gyp.py new file mode 100755 index 0000000000000..c51d35872cce6 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_gyp.py @@ -0,0 +1,155 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 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. + +"""Pretty-prints the contents of a GYP file.""" + +import sys +import re + + +# Regex to remove comments when we're counting braces. +COMMENT_RE = re.compile(r'\s*#.*') + +# Regex to remove quoted strings when we're counting braces. +# It takes into account quoted quotes, and makes sure that the quotes match. +# NOTE: It does not handle quotes that span more than one line, or +# cases where an escaped quote is preceeded by an escaped backslash. +QUOTE_RE_STR = r'(?P[\'"])(.*?)(? 0: + after = True + + # This catches the special case of a closing brace having something + # other than just whitespace ahead of it -- we don't want to + # unindent that until after this line is printed so it stays with + # the previous indentation level. + if cnt < 0 and closing_prefix_re.match(stripline): + after = True + return (cnt, after) + + +def prettyprint_input(lines): + """Does the main work of indenting the input based on the brace counts.""" + indent = 0 + basic_offset = 2 + last_line = "" + for line in lines: + if COMMENT_RE.match(line): + print line + else: + line = line.strip('\r\n\t ') # Otherwise doesn't strip \r on Unix. + if len(line) > 0: + (brace_diff, after) = count_braces(line) + if brace_diff != 0: + if after: + print " " * (basic_offset * indent) + line + indent += brace_diff + else: + indent += brace_diff + print " " * (basic_offset * indent) + line + else: + print " " * (basic_offset * indent) + line + else: + print "" + last_line = line + + +def main(): + if len(sys.argv) > 1: + data = open(sys.argv[1]).read().splitlines() + else: + data = sys.stdin.read().splitlines() + # Split up the double braces. + lines = split_double_braces(data) + + # Indent and print the output. + prettyprint_input(lines) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_sln.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_sln.py new file mode 100755 index 0000000000000..ca8cf4ad3fb83 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_sln.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 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. + +"""Prints the information in a sln file in a diffable way. + + It first outputs each projects in alphabetical order with their + dependencies. + + Then it outputs a possible build order. +""" + +__author__ = 'nsylvain (Nicolas Sylvain)' + +import os +import re +import sys +import pretty_vcproj + +def BuildProject(project, built, projects, deps): + # if all dependencies are done, we can build it, otherwise we try to build the + # dependency. + # This is not infinite-recursion proof. + for dep in deps[project]: + if dep not in built: + BuildProject(dep, built, projects, deps) + print project + built.append(project) + +def ParseSolution(solution_file): + # All projects, their clsid and paths. + projects = dict() + + # A list of dependencies associated with a project. + dependencies = dict() + + # Regular expressions that matches the SLN format. + # The first line of a project definition. + begin_project = re.compile(r'^Project\("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942' + r'}"\) = "(.*)", "(.*)", "(.*)"$') + # The last line of a project definition. + end_project = re.compile('^EndProject$') + # The first line of a dependency list. + begin_dep = re.compile( + r'ProjectSection\(ProjectDependencies\) = postProject$') + # The last line of a dependency list. + end_dep = re.compile('EndProjectSection$') + # A line describing a dependency. + dep_line = re.compile(' *({.*}) = ({.*})$') + + in_deps = False + solution = open(solution_file) + for line in solution: + results = begin_project.search(line) + if results: + # Hack to remove icu because the diff is too different. + if results.group(1).find('icu') != -1: + continue + # We remove "_gyp" from the names because it helps to diff them. + current_project = results.group(1).replace('_gyp', '') + projects[current_project] = [results.group(2).replace('_gyp', ''), + results.group(3), + results.group(2)] + dependencies[current_project] = [] + continue + + results = end_project.search(line) + if results: + current_project = None + continue + + results = begin_dep.search(line) + if results: + in_deps = True + continue + + results = end_dep.search(line) + if results: + in_deps = False + continue + + results = dep_line.search(line) + if results and in_deps and current_project: + dependencies[current_project].append(results.group(1)) + continue + + # Change all dependencies clsid to name instead. + for project in dependencies: + # For each dependencies in this project + new_dep_array = [] + for dep in dependencies[project]: + # Look for the project name matching this cldis + for project_info in projects: + if projects[project_info][1] == dep: + new_dep_array.append(project_info) + dependencies[project] = sorted(new_dep_array) + + return (projects, dependencies) + +def PrintDependencies(projects, deps): + print "---------------------------------------" + print "Dependencies for all projects" + print "---------------------------------------" + print "-- --" + + for (project, dep_list) in sorted(deps.items()): + print "Project : %s" % project + print "Path : %s" % projects[project][0] + if dep_list: + for dep in dep_list: + print " - %s" % dep + print "" + + print "-- --" + +def PrintBuildOrder(projects, deps): + print "---------------------------------------" + print "Build order " + print "---------------------------------------" + print "-- --" + + built = [] + for (project, _) in sorted(deps.items()): + if project not in built: + BuildProject(project, built, projects, deps) + + print "-- --" + +def PrintVCProj(projects): + + for project in projects: + print "-------------------------------------" + print "-------------------------------------" + print project + print project + print project + print "-------------------------------------" + print "-------------------------------------" + + project_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[1]), + projects[project][2])) + + pretty = pretty_vcproj + argv = [ '', + project_path, + '$(SolutionDir)=%s\\' % os.path.dirname(sys.argv[1]), + ] + argv.extend(sys.argv[3:]) + pretty.main(argv) + +def main(): + # check if we have exactly 1 parameter. + if len(sys.argv) < 2: + print 'Usage: %s "c:\\path\\to\\project.sln"' % sys.argv[0] + return 1 + + (projects, deps) = ParseSolution(sys.argv[1]) + PrintDependencies(projects, deps) + PrintBuildOrder(projects, deps) + + if '--recursive' in sys.argv: + PrintVCProj(projects) + return 0 + + +if __name__ == '__main__': + sys.exit(main()) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_vcproj.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_vcproj.py new file mode 100755 index 0000000000000..6099bd7cc4d8c --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_vcproj.py @@ -0,0 +1,329 @@ +#!/usr/bin/env python + +# Copyright (c) 2012 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. + +"""Make the format of a vcproj really pretty. + + This script normalize and sort an xml. It also fetches all the properties + inside linked vsprops and include them explicitly in the vcproj. + + It outputs the resulting xml to stdout. +""" + +__author__ = 'nsylvain (Nicolas Sylvain)' + +import os +import sys + +from xml.dom.minidom import parse +from xml.dom.minidom import Node + +REPLACEMENTS = dict() +ARGUMENTS = None + + +class CmpTuple(object): + """Compare function between 2 tuple.""" + def __call__(self, x, y): + return cmp(x[0], y[0]) + + +class CmpNode(object): + """Compare function between 2 xml nodes.""" + + def __call__(self, x, y): + def get_string(node): + node_string = "node" + node_string += node.nodeName + if node.nodeValue: + node_string += node.nodeValue + + if node.attributes: + # We first sort by name, if present. + node_string += node.getAttribute("Name") + + all_nodes = [] + for (name, value) in node.attributes.items(): + all_nodes.append((name, value)) + + all_nodes.sort(CmpTuple()) + for (name, value) in all_nodes: + node_string += name + node_string += value + + return node_string + + return cmp(get_string(x), get_string(y)) + + +def PrettyPrintNode(node, indent=0): + if node.nodeType == Node.TEXT_NODE: + if node.data.strip(): + print '%s%s' % (' '*indent, node.data.strip()) + return + + if node.childNodes: + node.normalize() + # Get the number of attributes + attr_count = 0 + if node.attributes: + attr_count = node.attributes.length + + # Print the main tag + if attr_count == 0: + print '%s<%s>' % (' '*indent, node.nodeName) + else: + print '%s<%s' % (' '*indent, node.nodeName) + + all_attributes = [] + for (name, value) in node.attributes.items(): + all_attributes.append((name, value)) + all_attributes.sort(CmpTuple()) + for (name, value) in all_attributes: + print '%s %s="%s"' % (' '*indent, name, value) + print '%s>' % (' '*indent) + if node.nodeValue: + print '%s %s' % (' '*indent, node.nodeValue) + + for sub_node in node.childNodes: + PrettyPrintNode(sub_node, indent=indent+2) + print '%s' % (' '*indent, node.nodeName) + + +def FlattenFilter(node): + """Returns a list of all the node and sub nodes.""" + node_list = [] + + if (node.attributes and + node.getAttribute('Name') == '_excluded_files'): + # We don't add the "_excluded_files" filter. + return [] + + for current in node.childNodes: + if current.nodeName == 'Filter': + node_list.extend(FlattenFilter(current)) + else: + node_list.append(current) + + return node_list + + +def FixFilenames(filenames, current_directory): + new_list = [] + for filename in filenames: + if filename: + for key in REPLACEMENTS: + filename = filename.replace(key, REPLACEMENTS[key]) + os.chdir(current_directory) + filename = filename.strip('"\' ') + if filename.startswith('$'): + new_list.append(filename) + else: + new_list.append(os.path.abspath(filename)) + return new_list + + +def AbsoluteNode(node): + """Makes all the properties we know about in this node absolute.""" + if node.attributes: + for (name, value) in node.attributes.items(): + if name in ['InheritedPropertySheets', 'RelativePath', + 'AdditionalIncludeDirectories', + 'IntermediateDirectory', 'OutputDirectory', + 'AdditionalLibraryDirectories']: + # We want to fix up these paths + path_list = value.split(';') + new_list = FixFilenames(path_list, os.path.dirname(ARGUMENTS[1])) + node.setAttribute(name, ';'.join(new_list)) + if not value: + node.removeAttribute(name) + + +def CleanupVcproj(node): + """For each sub node, we call recursively this function.""" + for sub_node in node.childNodes: + AbsoluteNode(sub_node) + CleanupVcproj(sub_node) + + # Normalize the node, and remove all extranous whitespaces. + for sub_node in node.childNodes: + if sub_node.nodeType == Node.TEXT_NODE: + sub_node.data = sub_node.data.replace("\r", "") + sub_node.data = sub_node.data.replace("\n", "") + sub_node.data = sub_node.data.rstrip() + + # Fix all the semicolon separated attributes to be sorted, and we also + # remove the dups. + if node.attributes: + for (name, value) in node.attributes.items(): + sorted_list = sorted(value.split(';')) + unique_list = [] + for i in sorted_list: + if not unique_list.count(i): + unique_list.append(i) + node.setAttribute(name, ';'.join(unique_list)) + if not value: + node.removeAttribute(name) + + if node.childNodes: + node.normalize() + + # For each node, take a copy, and remove it from the list. + node_array = [] + while node.childNodes and node.childNodes[0]: + # Take a copy of the node and remove it from the list. + current = node.childNodes[0] + node.removeChild(current) + + # If the child is a filter, we want to append all its children + # to this same list. + if current.nodeName == 'Filter': + node_array.extend(FlattenFilter(current)) + else: + node_array.append(current) + + + # Sort the list. + node_array.sort(CmpNode()) + + # Insert the nodes in the correct order. + for new_node in node_array: + # But don't append empty tool node. + if new_node.nodeName == 'Tool': + if new_node.attributes and new_node.attributes.length == 1: + # This one was empty. + continue + if new_node.nodeName == 'UserMacro': + continue + node.appendChild(new_node) + + +def GetConfiguationNodes(vcproj): + #TODO(nsylvain): Find a better way to navigate the xml. + nodes = [] + for node in vcproj.childNodes: + if node.nodeName == "Configurations": + for sub_node in node.childNodes: + if sub_node.nodeName == "Configuration": + nodes.append(sub_node) + + return nodes + + +def GetChildrenVsprops(filename): + dom = parse(filename) + if dom.documentElement.attributes: + vsprops = dom.documentElement.getAttribute('InheritedPropertySheets') + return FixFilenames(vsprops.split(';'), os.path.dirname(filename)) + return [] + +def SeekToNode(node1, child2): + # A text node does not have properties. + if child2.nodeType == Node.TEXT_NODE: + return None + + # Get the name of the current node. + current_name = child2.getAttribute("Name") + if not current_name: + # There is no name. We don't know how to merge. + return None + + # Look through all the nodes to find a match. + for sub_node in node1.childNodes: + if sub_node.nodeName == child2.nodeName: + name = sub_node.getAttribute("Name") + if name == current_name: + return sub_node + + # No match. We give up. + return None + + +def MergeAttributes(node1, node2): + # No attributes to merge? + if not node2.attributes: + return + + for (name, value2) in node2.attributes.items(): + # Don't merge the 'Name' attribute. + if name == 'Name': + continue + value1 = node1.getAttribute(name) + if value1: + # The attribute exist in the main node. If it's equal, we leave it + # untouched, otherwise we concatenate it. + if value1 != value2: + node1.setAttribute(name, ';'.join([value1, value2])) + else: + # The attribute does nto exist in the main node. We append this one. + node1.setAttribute(name, value2) + + # If the attribute was a property sheet attributes, we remove it, since + # they are useless. + if name == 'InheritedPropertySheets': + node1.removeAttribute(name) + + +def MergeProperties(node1, node2): + MergeAttributes(node1, node2) + for child2 in node2.childNodes: + child1 = SeekToNode(node1, child2) + if child1: + MergeProperties(child1, child2) + else: + node1.appendChild(child2.cloneNode(True)) + + +def main(argv): + """Main function of this vcproj prettifier.""" + global ARGUMENTS + ARGUMENTS = argv + + # check if we have exactly 1 parameter. + if len(argv) < 2: + print ('Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] ' + '[key2=value2]' % argv[0]) + return 1 + + # Parse the keys + for i in range(2, len(argv)): + (key, value) = argv[i].split('=') + REPLACEMENTS[key] = value + + # Open the vcproj and parse the xml. + dom = parse(argv[1]) + + # First thing we need to do is find the Configuration Node and merge them + # with the vsprops they include. + for configuration_node in GetConfiguationNodes(dom.documentElement): + # Get the property sheets associated with this configuration. + vsprops = configuration_node.getAttribute('InheritedPropertySheets') + + # Fix the filenames to be absolute. + vsprops_list = FixFilenames(vsprops.strip().split(';'), + os.path.dirname(argv[1])) + + # Extend the list of vsprops with all vsprops contained in the current + # vsprops. + for current_vsprops in vsprops_list: + vsprops_list.extend(GetChildrenVsprops(current_vsprops)) + + # Now that we have all the vsprops, we need to merge them. + for current_vsprops in vsprops_list: + MergeProperties(configuration_node, + parse(current_vsprops).documentElement) + + # Now that everything is merged, we need to cleanup the xml. + CleanupVcproj(dom.documentElement) + + # Finally, we use the prett xml function to print the vcproj back to the + # user. + #print dom.toprettyxml(newl="\n") + PrettyPrintNode(dom.documentElement) + return 0 + + +if __name__ == '__main__': + sys.exit(main(sys.argv)) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/Find-VS2017.cs b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/Find-VS2017.cs new file mode 100644 index 0000000000000..6e7429b771385 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/Find-VS2017.cs @@ -0,0 +1,273 @@ +// Copyright 2017 - Refael Ackermann +// Distributed under MIT style license +// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf + +// Usage: +// powershell -ExecutionPolicy Unrestricted -Version "2.0" -Command "&{Add-Type -Path Find-VS2017.cs; [VisualStudioConfiguration.Main]::Query()}" +using System; +using System.Text; +using System.Runtime.InteropServices; + +namespace VisualStudioConfiguration +{ + [Flags] + public enum InstanceState : uint + { + None = 0, + Local = 1, + Registered = 2, + NoRebootRequired = 4, + NoErrors = 8, + Complete = 4294967295, + } + + [Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface IEnumSetupInstances + { + + void Next([MarshalAs(UnmanagedType.U4), In] int celt, + [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt, + [MarshalAs(UnmanagedType.U4)] out int pceltFetched); + + void Skip([MarshalAs(UnmanagedType.U4), In] int celt); + + void Reset(); + + [return: MarshalAs(UnmanagedType.Interface)] + IEnumSetupInstances Clone(); + } + + [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupConfiguration + { + } + + [Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupConfiguration2 : ISetupConfiguration + { + + [return: MarshalAs(UnmanagedType.Interface)] + IEnumSetupInstances EnumInstances(); + + [return: MarshalAs(UnmanagedType.Interface)] + ISetupInstance GetInstanceForCurrentProcess(); + + [return: MarshalAs(UnmanagedType.Interface)] + ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path); + + [return: MarshalAs(UnmanagedType.Interface)] + IEnumSetupInstances EnumAllInstances(); + } + + [Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupInstance + { + } + + [Guid("89143C9A-05AF-49B0-B717-72E218A2185C")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupInstance2 : ISetupInstance + { + [return: MarshalAs(UnmanagedType.BStr)] + string GetInstanceId(); + + [return: MarshalAs(UnmanagedType.Struct)] + System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetInstallationName(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetInstallationPath(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetInstallationVersion(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid); + + [return: MarshalAs(UnmanagedType.BStr)] + string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath); + + [return: MarshalAs(UnmanagedType.U4)] + InstanceState GetState(); + + [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] + ISetupPackageReference[] GetPackages(); + + ISetupPackageReference GetProduct(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetProductPath(); + + [return: MarshalAs(UnmanagedType.VariantBool)] + bool IsLaunchable(); + + [return: MarshalAs(UnmanagedType.VariantBool)] + bool IsComplete(); + + [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] + ISetupPropertyStore GetProperties(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetEnginePath(); + } + + [Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupPackageReference + { + + [return: MarshalAs(UnmanagedType.BStr)] + string GetId(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetVersion(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetChip(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetLanguage(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetBranch(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetType(); + + [return: MarshalAs(UnmanagedType.BStr)] + string GetUniqueId(); + + [return: MarshalAs(UnmanagedType.VariantBool)] + bool GetIsExtension(); + } + + [Guid("c601c175-a3be-44bc-91f6-4568d230fc83")] + [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] + [ComImport] + public interface ISetupPropertyStore + { + + [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] + string[] GetNames(); + + object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName); + } + + [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] + [CoClass(typeof(SetupConfigurationClass))] + [ComImport] + public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration + { + } + + [Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")] + [ClassInterface(ClassInterfaceType.None)] + [ComImport] + public class SetupConfigurationClass + { + } + + public static class Main + { + public static void Query() + { + ISetupConfiguration query = new SetupConfiguration(); + ISetupConfiguration2 query2 = (ISetupConfiguration2)query; + IEnumSetupInstances e = query2.EnumAllInstances(); + + int pceltFetched; + ISetupInstance2[] rgelt = new ISetupInstance2[1]; + StringBuilder log = new StringBuilder(); + while (true) + { + e.Next(1, rgelt, out pceltFetched); + if (pceltFetched <= 0) + { + Console.WriteLine(String.Format("{{\"log\":\"{0}\"}}", log.ToString())); + return; + } + if (CheckInstance(rgelt[0], ref log)) + return; + } + } + + private static bool CheckInstance(ISetupInstance2 setupInstance2, ref StringBuilder log) + { + // Visual Studio Community 2017 component directory: + // https://www.visualstudio.com/en-us/productinfo/vs2017-install-product-Community.workloads + + string path = setupInstance2.GetInstallationPath().Replace("\\", "\\\\"); + log.Append(String.Format("Found installation at: {0}\\n", path)); + + bool hasMSBuild = false; + bool hasVCTools = false; + uint Win10SDKVer = 0; + bool hasWin8SDK = false; + + foreach (ISetupPackageReference package in setupInstance2.GetPackages()) + { + const string Win10SDKPrefix = "Microsoft.VisualStudio.Component.Windows10SDK."; + + string id = package.GetId(); + if (id == "Microsoft.VisualStudio.VC.MSBuild.Base") + hasMSBuild = true; + else if (id == "Microsoft.VisualStudio.Component.VC.Tools.x86.x64") + hasVCTools = true; + else if (id.StartsWith(Win10SDKPrefix)) { + string[] parts = id.Substring(Win10SDKPrefix.Length).Split('.'); + if (parts.Length > 1 && parts[1] != "Desktop") + continue; + uint foundSdkVer; + if (UInt32.TryParse(parts[0], out foundSdkVer)) + Win10SDKVer = Math.Max(Win10SDKVer, foundSdkVer); + } else if (id == "Microsoft.VisualStudio.Component.Windows81SDK") + hasWin8SDK = true; + else + continue; + + log.Append(String.Format(" - Found {0}\\n", id)); + } + + if (!hasMSBuild) + log.Append(" - Missing Visual Studio C++ core features (Microsoft.VisualStudio.VC.MSBuild.Base)\\n"); + if (!hasVCTools) + log.Append(" - Missing VC++ 2017 v141 toolset (x86,x64) (Microsoft.VisualStudio.Component.VC.Tools.x86.x64)\\n"); + if ((Win10SDKVer == 0) && (!hasWin8SDK)) + log.Append(" - Missing a Windows SDK (Microsoft.VisualStudio.Component.Windows10SDK.* or Microsoft.VisualStudio.Component.Windows81SDK)\\n"); + + if (hasMSBuild && hasVCTools) + { + if (Win10SDKVer > 0) + { + log.Append(" - Using this installation with Windows 10 SDK"/*\\n*/); + Console.WriteLine(String.Format("{{\"log\":\"{0}\",\"path\":\"{1}\",\"sdk\":\"10.0.{2}.0\"}}", log.ToString(), path, Win10SDKVer)); + return true; + } + else if (hasWin8SDK) + { + log.Append(" - Using this installation with Windows 8.1 SDK"/*\\n*/); + Console.WriteLine(String.Format("{{\"log\":\"{0}\",\"path\":\"{1}\",\"sdk\":\"8.1\"}}", log.ToString(), path)); + return true; + } + } + + log.Append(" - Some required components are missing, not using this installation\\n"); + return false; + } + } +} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/build.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/build.js new file mode 100644 index 0000000000000..2f8e14c37429d --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/build.js @@ -0,0 +1,270 @@ + +module.exports = exports = build + +/** + * Module dependencies. + */ + +var fs = require('graceful-fs') + , rm = require('rimraf') + , path = require('path') + , glob = require('glob') + , log = require('npmlog') + , which = require('which') + , exec = require('child_process').exec + , processRelease = require('./process-release') + , win = process.platform === 'win32' + +exports.usage = 'Invokes `' + (win ? 'msbuild' : 'make') + '` and builds the module' + +function build (gyp, argv, callback) { + var platformMake = 'make' + if (process.platform === 'aix') { + platformMake = 'gmake' + } else if (process.platform.indexOf('bsd') !== -1) { + platformMake = 'gmake' + } else if (win && argv.length > 0) { + argv = argv.map(function(target) { + return '/t:' + target + }) + } + + var release = processRelease(argv, gyp, process.version, process.release) + , makeCommand = gyp.opts.make || process.env.MAKE || platformMake + , command = win ? 'msbuild' : makeCommand + , buildDir = path.resolve('build') + , configPath = path.resolve(buildDir, 'config.gypi') + , jobs = gyp.opts.jobs || process.env.JOBS + , buildType + , config + , arch + , nodeDir + + loadConfigGypi() + + /** + * Load the "config.gypi" file that was generated during "configure". + */ + + function loadConfigGypi () { + fs.readFile(configPath, 'utf8', function (err, data) { + if (err) { + if (err.code == 'ENOENT') { + callback(new Error('You must run `node-gyp configure` first!')) + } else { + callback(err) + } + return + } + config = JSON.parse(data.replace(/\#.+\n/, '')) + + // get the 'arch', 'buildType', and 'nodeDir' vars from the config + buildType = config.target_defaults.default_configuration + arch = config.variables.target_arch + nodeDir = config.variables.nodedir + + if ('debug' in gyp.opts) { + buildType = gyp.opts.debug ? 'Debug' : 'Release' + } + if (!buildType) { + buildType = 'Release' + } + + log.verbose('build type', buildType) + log.verbose('architecture', arch) + log.verbose('node dev dir', nodeDir) + + if (win) { + findSolutionFile() + } else { + doWhich() + } + }) + } + + /** + * On Windows, find the first build/*.sln file. + */ + + function findSolutionFile () { + glob('build/*.sln', function (err, files) { + if (err) return callback(err) + if (files.length === 0) { + return callback(new Error('Could not find *.sln file. Did you run "configure"?')) + } + guessedSolution = files[0] + log.verbose('found first Solution file', guessedSolution) + doWhich() + }) + } + + /** + * Uses node-which to locate the msbuild / make executable. + */ + + function doWhich () { + // First make sure we have the build command in the PATH + which(command, function (err, execPath) { + if (err) { + if (win && /not found/.test(err.message)) { + // On windows and no 'msbuild' found. Let's guess where it is + findMsbuild() + } else { + // Some other error or 'make' not found on Unix, report that to the user + callback(err) + } + return + } + log.verbose('`which` succeeded for `' + command + '`', execPath) + doBuild() + }) + } + + /** + * Search for the location of "msbuild.exe" file on Windows. + */ + + function findMsbuild () { + if (config.variables.msbuild_path) { + command = config.variables.msbuild_path + log.verbose('using MSBuild:', command) + doBuild() + return + } + + log.verbose('could not find "msbuild.exe" in PATH - finding location in registry') + var notfoundErr = 'Can\'t find "msbuild.exe". Do you have Microsoft Visual Studio C++ 2008+ installed?' + var cmd = 'reg query "HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions" /s' + if (process.arch !== 'ia32') + cmd += ' /reg:32' + exec(cmd, function (err, stdout, stderr) { + if (err) { + return callback(new Error(err.message + '\n' + notfoundErr)) + } + var reVers = /ToolsVersions\\([^\\]+)$/i + , rePath = /\r\n[ \t]+MSBuildToolsPath[ \t]+REG_SZ[ \t]+([^\r]+)/i + , msbuilds = [] + , r + , msbuildPath + stdout.split('\r\n\r\n').forEach(function(l) { + if (!l) return + l = l.trim() + if (r = reVers.exec(l.substring(0, l.indexOf('\r\n')))) { + var ver = parseFloat(r[1], 10) + if (ver >= 3.5) { + if (r = rePath.exec(l)) { + msbuilds.push({ + version: ver, + path: r[1] + }) + } + } + } + }) + msbuilds.sort(function (x, y) { + return (x.version < y.version ? -1 : 1) + }) + ;(function verifyMsbuild () { + if (!msbuilds.length) return callback(new Error(notfoundErr)) + msbuildPath = path.resolve(msbuilds.pop().path, 'msbuild.exe') + fs.stat(msbuildPath, function (err, stat) { + if (err) { + if (err.code == 'ENOENT') { + if (msbuilds.length) { + return verifyMsbuild() + } else { + callback(new Error(notfoundErr)) + } + } else { + callback(err) + } + return + } + command = msbuildPath + doBuild() + }) + })() + }) + } + + + /** + * Actually spawn the process and compile the module. + */ + + function doBuild () { + + // Enable Verbose build + var verbose = log.levels[log.level] <= log.levels.verbose + if (!win && verbose) { + argv.push('V=1') + } + if (win && !verbose) { + argv.push('/clp:Verbosity=minimal') + } + + if (win) { + // Turn off the Microsoft logo on Windows + argv.push('/nologo') + } + + // Specify the build type, Release by default + if (win) { + var archLower = arch.toLowerCase() + var p = archLower === 'x64' ? 'x64' : + (archLower === 'arm' ? 'ARM' : 'Win32') + argv.push('/p:Configuration=' + buildType + ';Platform=' + p) + if (jobs) { + var j = parseInt(jobs, 10) + if (!isNaN(j) && j > 0) { + argv.push('/m:' + j) + } else if (jobs.toUpperCase() === 'MAX') { + argv.push('/m:' + require('os').cpus().length) + } + } + } else { + argv.push('BUILDTYPE=' + buildType) + // Invoke the Makefile in the 'build' dir. + argv.push('-C') + argv.push('build') + if (jobs) { + var j = parseInt(jobs, 10) + if (!isNaN(j) && j > 0) { + argv.push('--jobs') + argv.push(j) + } else if (jobs.toUpperCase() === 'MAX') { + argv.push('--jobs') + argv.push(require('os').cpus().length) + } + } + } + + if (win) { + // did the user specify their own .sln file? + var hasSln = argv.some(function (arg) { + return path.extname(arg) == '.sln' + }) + if (!hasSln) { + argv.unshift(gyp.opts.solution || guessedSolution) + } + } + + var proc = gyp.spawn(command, argv) + proc.on('exit', onExit) + } + + /** + * Invoked after the make/msbuild command exits. + */ + + function onExit (code, signal) { + if (code !== 0) { + return callback(new Error('`' + command + '` failed with exit code: ' + code)) + } + if (signal) { + return callback(new Error('`' + command + '` got signal: ' + signal)) + } + callback() + } + +} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/clean.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/clean.js new file mode 100644 index 0000000000000..e69164d45afcc --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/clean.js @@ -0,0 +1,22 @@ + +module.exports = exports = clean + +exports.usage = 'Removes any generated build files and the "out" dir' + +/** + * Module dependencies. + */ + +var rm = require('rimraf') +var log = require('npmlog') + + +function clean (gyp, argv, callback) { + + // Remove the 'build' dir + var buildDir = 'build' + + log.verbose('clean', 'removing "%s" directory', buildDir) + rm(buildDir, callback) + +} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/configure.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/configure.js new file mode 100644 index 0000000000000..35e6787d1f3e3 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/configure.js @@ -0,0 +1,524 @@ +module.exports = exports = configure +module.exports.test = { + PythonFinder: PythonFinder, + findAccessibleSync: findAccessibleSync, + findPython: findPython, +} + +/** + * Module dependencies. + */ + +var fs = require('graceful-fs') + , path = require('path') + , log = require('npmlog') + , osenv = require('osenv') + , which = require('which') + , semver = require('semver') + , mkdirp = require('mkdirp') + , cp = require('child_process') + , extend = require('util')._extend + , processRelease = require('./process-release') + , win = process.platform === 'win32' + , findNodeDirectory = require('./find-node-directory') + , msgFormat = require('util').format +if (win) + var findVS2017 = require('./find-vs2017') + +exports.usage = 'Generates ' + (win ? 'MSVC project files' : 'a Makefile') + ' for the current module' + +function configure (gyp, argv, callback) { + + var python = gyp.opts.python || process.env.PYTHON || 'python2' + , buildDir = path.resolve('build') + , configNames = [ 'config.gypi', 'common.gypi' ] + , configs = [] + , nodeDir + , release = processRelease(argv, gyp, process.version, process.release) + + findPython(python, function (err, found) { + if (err) { + callback(err) + } else { + python = found + getNodeDir() + } + }) + + function getNodeDir () { + + // 'python' should be set by now + process.env.PYTHON = python + + if (gyp.opts.nodedir) { + // --nodedir was specified. use that for the dev files + nodeDir = gyp.opts.nodedir.replace(/^~/, osenv.home()) + + log.verbose('get node dir', 'compiling against specified --nodedir dev files: %s', nodeDir) + createBuildDir() + + } else { + // if no --nodedir specified, ensure node dependencies are installed + if ('v' + release.version !== process.version) { + // if --target was given, then determine a target version to compile for + log.verbose('get node dir', 'compiling against --target node version: %s', release.version) + } else { + // if no --target was specified then use the current host node version + log.verbose('get node dir', 'no --target version specified, falling back to host node version: %s', release.version) + } + + if (!release.semver) { + // could not parse the version string with semver + return callback(new Error('Invalid version number: ' + release.version)) + } + + // If the tarball option is set, always remove and reinstall the headers + // into devdir. Otherwise only install if they're not already there. + gyp.opts.ensure = gyp.opts.tarball ? false : true + + gyp.commands.install([ release.version ], function (err, version) { + if (err) return callback(err) + log.verbose('get node dir', 'target node version installed:', release.versionDir) + nodeDir = path.resolve(gyp.devDir, release.versionDir) + createBuildDir() + }) + } + } + + function createBuildDir () { + log.verbose('build dir', 'attempting to create "build" dir: %s', buildDir) + mkdirp(buildDir, function (err, isNew) { + if (err) return callback(err) + log.verbose('build dir', '"build" dir needed to be created?', isNew) + if (win && (!gyp.opts.msvs_version || gyp.opts.msvs_version === '2017')) { + findVS2017(function (err, vsSetup) { + if (err) { + log.verbose('Not using VS2017:', err.message) + createConfigFile() + } else { + createConfigFile(null, vsSetup) + } + }) + } else { + createConfigFile() + } + }) + } + + function createConfigFile (err, vsSetup) { + if (err) return callback(err) + + var configFilename = 'config.gypi' + var configPath = path.resolve(buildDir, configFilename) + + log.verbose('build/' + configFilename, 'creating config file') + + var config = process.config || {} + , defaults = config.target_defaults + , variables = config.variables + + // default "config.variables" + if (!variables) variables = config.variables = {} + + // default "config.defaults" + if (!defaults) defaults = config.target_defaults = {} + + // don't inherit the "defaults" from node's `process.config` object. + // doing so could cause problems in cases where the `node` executable was + // compiled on a different machine (with different lib/include paths) than + // the machine where the addon is being built to + defaults.cflags = [] + defaults.defines = [] + defaults.include_dirs = [] + defaults.libraries = [] + + // set the default_configuration prop + if ('debug' in gyp.opts) { + defaults.default_configuration = gyp.opts.debug ? 'Debug' : 'Release' + } + if (!defaults.default_configuration) { + defaults.default_configuration = 'Release' + } + + // set the target_arch variable + variables.target_arch = gyp.opts.arch || process.arch || 'ia32' + + // set the node development directory + variables.nodedir = nodeDir + + // disable -T "thin" static archives by default + variables.standalone_static_library = gyp.opts.thin ? 0 : 1 + + if (vsSetup) { + // GYP doesn't (yet) have support for VS2017, so we force it to VS2015 + // to avoid pulling a floating patch that has not landed upstream. + // Ref: https://chromium-review.googlesource.com/#/c/433540/ + gyp.opts.msvs_version = '2015' + process.env['GYP_MSVS_VERSION'] = 2015 + process.env['GYP_MSVS_OVERRIDE_PATH'] = vsSetup.path + defaults['msbuild_toolset'] = 'v141' + defaults['msvs_windows_target_platform_version'] = vsSetup.sdk + variables['msbuild_path'] = path.join(vsSetup.path, 'MSBuild', '15.0', + 'Bin', 'MSBuild.exe') + } + + // loop through the rest of the opts and add the unknown ones as variables. + // this allows for module-specific configure flags like: + // + // $ node-gyp configure --shared-libxml2 + Object.keys(gyp.opts).forEach(function (opt) { + if (opt === 'argv') return + if (opt in gyp.configDefs) return + variables[opt.replace(/-/g, '_')] = gyp.opts[opt] + }) + + // ensures that any boolean values from `process.config` get stringified + function boolsToString (k, v) { + if (typeof v === 'boolean') + return String(v) + return v + } + + log.silly('build/' + configFilename, config) + + // now write out the config.gypi file to the build/ dir + var prefix = '# Do not edit. File was generated by node-gyp\'s "configure" step' + , json = JSON.stringify(config, boolsToString, 2) + log.verbose('build/' + configFilename, 'writing out config file: %s', configPath) + configs.push(configPath) + fs.writeFile(configPath, [prefix, json, ''].join('\n'), findConfigs) + } + + function findConfigs (err) { + if (err) return callback(err) + var name = configNames.shift() + if (!name) return runGyp() + var fullPath = path.resolve(name) + log.verbose(name, 'checking for gypi file: %s', fullPath) + fs.stat(fullPath, function (err, stat) { + if (err) { + if (err.code == 'ENOENT') { + findConfigs() // check next gypi filename + } else { + callback(err) + } + } else { + log.verbose(name, 'found gypi file') + configs.push(fullPath) + findConfigs() + } + }) + } + + function runGyp (err) { + if (err) return callback(err) + + if (!~argv.indexOf('-f') && !~argv.indexOf('--format')) { + if (win) { + log.verbose('gyp', 'gyp format was not specified; forcing "msvs"') + // force the 'make' target for non-Windows + argv.push('-f', 'msvs') + } else { + log.verbose('gyp', 'gyp format was not specified; forcing "make"') + // force the 'make' target for non-Windows + argv.push('-f', 'make') + } + } + + function hasMsvsVersion () { + return argv.some(function (arg) { + return arg.indexOf('msvs_version') === 0 + }) + } + + if (win && !hasMsvsVersion()) { + if ('msvs_version' in gyp.opts) { + argv.push('-G', 'msvs_version=' + gyp.opts.msvs_version) + } else { + argv.push('-G', 'msvs_version=auto') + } + } + + // include all the ".gypi" files that were found + configs.forEach(function (config) { + argv.push('-I', config) + }) + + // For AIX and z/OS we need to set up the path to the exports file + // which contains the symbols needed for linking. + var node_exp_file = undefined + if (process.platform === 'aix' || process.platform === 'os390') { + var ext = process.platform === 'aix' ? 'exp' : 'x' + var node_root_dir = findNodeDirectory() + var candidates = undefined + if (process.platform === 'aix') { + candidates = ['include/node/node', + 'out/Release/node', + 'out/Debug/node', + 'node' + ].map(function(file) { + return file + '.' + ext + }) + } else { + candidates = ['out/Release/obj.target/libnode', + 'out/Debug/obj.target/libnode', + 'lib/libnode' + ].map(function(file) { + return file + '.' + ext + }) + } + var logprefix = 'find exports file' + node_exp_file = findAccessibleSync(logprefix, node_root_dir, candidates) + if (node_exp_file !== undefined) { + log.verbose(logprefix, 'Found exports file: %s', node_exp_file) + } else { + var msg = msgFormat('Could not find node.%s file in %s', ext, node_root_dir) + log.error(logprefix, 'Could not find exports file') + return callback(new Error(msg)) + } + } + + // this logic ported from the old `gyp_addon` python file + var gyp_script = path.resolve(__dirname, '..', 'gyp', 'gyp_main.py') + var addon_gypi = path.resolve(__dirname, '..', 'addon.gypi') + var common_gypi = path.resolve(nodeDir, 'include/node/common.gypi') + fs.stat(common_gypi, function (err, stat) { + if (err) + common_gypi = path.resolve(nodeDir, 'common.gypi') + + var output_dir = 'build' + if (win) { + // Windows expects an absolute path + output_dir = buildDir + } + var nodeGypDir = path.resolve(__dirname, '..') + var nodeLibFile = path.join(nodeDir, + !gyp.opts.nodedir ? '<(target_arch)' : '$(Configuration)', + release.name + '.lib') + + argv.push('-I', addon_gypi) + argv.push('-I', common_gypi) + argv.push('-Dlibrary=shared_library') + argv.push('-Dvisibility=default') + argv.push('-Dnode_root_dir=' + nodeDir) + if (process.platform === 'aix' || process.platform === 'os390') { + argv.push('-Dnode_exp_file=' + node_exp_file) + } + argv.push('-Dnode_gyp_dir=' + nodeGypDir) + argv.push('-Dnode_lib_file=' + nodeLibFile) + argv.push('-Dmodule_root_dir=' + process.cwd()) + argv.push('-Dnode_engine=' + + (gyp.opts.node_engine || process.jsEngine || 'v8')) + argv.push('--depth=.') + argv.push('--no-parallel') + + // tell gyp to write the Makefile/Solution files into output_dir + argv.push('--generator-output', output_dir) + + // tell make to write its output into the same dir + argv.push('-Goutput_dir=.') + + // enforce use of the "binding.gyp" file + argv.unshift('binding.gyp') + + // execute `gyp` from the current target nodedir + argv.unshift(gyp_script) + + // make sure python uses files that came with this particular node package + var pypath = [path.join(__dirname, '..', 'gyp', 'pylib')] + if (process.env.PYTHONPATH) { + pypath.push(process.env.PYTHONPATH) + } + process.env.PYTHONPATH = pypath.join(win ? ';' : ':') + + var cp = gyp.spawn(python, argv) + cp.on('exit', onCpExit) + }) + } + + /** + * Called when the `gyp` child process exits. + */ + + function onCpExit (code, signal) { + if (code !== 0) { + callback(new Error('`gyp` failed with exit code: ' + code)) + } else { + // we're done + callback() + } + } + +} + +/** + * Returns the first file or directory from an array of candidates that is + * readable by the current user, or undefined if none of the candidates are + * readable. + */ +function findAccessibleSync (logprefix, dir, candidates) { + for (var next = 0; next < candidates.length; next++) { + var candidate = path.resolve(dir, candidates[next]) + try { + var fd = fs.openSync(candidate, 'r') + } catch (e) { + // this candidate was not found or not readable, do nothing + log.silly(logprefix, 'Could not open %s: %s', candidate, e.message) + continue + } + fs.closeSync(fd) + log.silly(logprefix, 'Found readable %s', candidate) + return candidate + } + + return undefined +} + +function PythonFinder(python, callback) { + this.callback = callback + this.python = python +} + +PythonFinder.prototype = { + checkPythonLauncherDepth: 0, + env: process.env, + execFile: cp.execFile, + log: log, + resolve: path.win32 && path.win32.resolve || path.resolve, + stat: fs.stat, + which: which, + win: win, + + checkPython: function checkPython () { + this.log.verbose('check python', + 'checking for Python executable "%s" in the PATH', + this.python) + this.which(this.python, function (err, execPath) { + if (err) { + this.log.verbose('`which` failed', this.python, err) + if (this.python === 'python2') { + this.python = 'python' + return this.checkPython() + } + if (this.win) { + this.checkPythonLauncher() + } else { + this.failNoPython() + } + } else { + this.log.verbose('`which` succeeded', this.python, execPath) + // Found the `python` executable, and from now on we use it explicitly. + // This solves #667 and #750 (`execFile` won't run batch files + // (*.cmd, and *.bat)) + this.python = execPath + this.checkPythonVersion() + } + }.bind(this)) + }, + + // Distributions of Python on Windows by default install with the "py.exe" + // Python launcher which is more likely to exist than the Python executable + // being in the $PATH. + // Because the Python launcher supports all versions of Python, we have to + // explicitly request a Python 2 version. This is done by supplying "-2" as + // the first command line argument. Since "py.exe -2" would be an invalid + // executable for "execFile", we have to use the launcher to figure out + // where the actual "python.exe" executable is located. + checkPythonLauncher: function checkPythonLauncher () { + this.checkPythonLauncherDepth += 1 + + this.log.verbose( + 'could not find "' + this.python + '". checking python launcher') + var env = extend({}, this.env) + env.TERM = 'dumb' + + var launcherArgs = ['-2', '-c', 'import sys; print sys.executable'] + this.execFile('py.exe', launcherArgs, { env: env }, function (err, stdout) { + if (err) { + this.guessPython() + } else { + this.python = stdout.trim() + this.log.verbose('check python launcher', + 'python executable found: %j', + this.python) + this.checkPythonVersion() + } + this.checkPythonLauncherDepth -= 1 + }.bind(this)) + }, + + checkPythonVersion: function checkPythonVersion () { + var args = ['-c', 'import sys; print "%s.%s.%s" % sys.version_info[:3];'] + var env = extend({}, this.env) + env.TERM = 'dumb' + + this.execFile(this.python, args, { env: env }, function (err, stdout) { + if (err) { + return this.callback(err) + } + this.log.verbose('check python version', + '`%s -c "' + args[1] + '"` returned: %j', + this.python, stdout) + var version = stdout.trim() + var range = semver.Range('>=2.5.0 <3.0.0') + var valid = false + try { + valid = range.test(version) + } catch (e) { + this.log.silly('range.test() error', e) + } + if (valid) { + this.callback(null, this.python) + } else if (this.win && this.checkPythonLauncherDepth === 0) { + this.checkPythonLauncher() + } else { + this.failPythonVersion(version) + } + }.bind(this)) + }, + + failNoPython: function failNoPython () { + var errmsg = + 'Can\'t find Python executable "' + this.python + + '", you can set the PYTHON env variable.' + this.callback(new Error(errmsg)) + }, + + failPythonVersion: function failPythonVersion (badVersion) { + var errmsg = + 'Python executable "' + this.python + + '" is v' + badVersion + ', which is not supported by gyp.\n' + + 'You can pass the --python switch to point to ' + + 'Python >= v2.5.0 & < 3.0.0.' + this.callback(new Error(errmsg)) + }, + + // Called on Windows when "python" isn't available in the current $PATH. + // We are going to check if "%SystemDrive%\python27\python.exe" exists. + guessPython: function guessPython () { + this.log.verbose('could not find "' + this.python + '". guessing location') + var rootDir = this.env.SystemDrive || 'C:\\' + if (rootDir[rootDir.length - 1] !== '\\') { + rootDir += '\\' + } + var pythonPath = this.resolve(rootDir, 'Python27', 'python.exe') + this.log.verbose('ensuring that file exists:', pythonPath) + this.stat(pythonPath, function (err, stat) { + if (err) { + if (err.code == 'ENOENT') { + this.failNoPython() + } else { + this.callback(err) + } + return + } + this.python = pythonPath + this.checkPythonVersion() + }.bind(this)) + }, +} + +function findPython (python, callback) { + var finder = new PythonFinder(python, callback) + finder.checkPython() +} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-node-directory.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-node-directory.js new file mode 100644 index 0000000000000..3aee8a109ae28 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-node-directory.js @@ -0,0 +1,61 @@ +var path = require('path') + , log = require('npmlog') + +function findNodeDirectory(scriptLocation, processObj) { + // set dirname and process if not passed in + // this facilitates regression tests + if (scriptLocation === undefined) { + scriptLocation = __dirname + } + if (processObj === undefined) { + processObj = process + } + + // Have a look to see what is above us, to try and work out where we are + npm_parent_directory = path.join(scriptLocation, '../../../..') + log.verbose('node-gyp root', 'npm_parent_directory is ' + + path.basename(npm_parent_directory)) + node_root_dir = "" + + log.verbose('node-gyp root', 'Finding node root directory') + if (path.basename(npm_parent_directory) === 'deps') { + // We are in a build directory where this script lives in + // deps/npm/node_modules/node-gyp/lib + node_root_dir = path.join(npm_parent_directory, '..') + log.verbose('node-gyp root', 'in build directory, root = ' + + node_root_dir) + } else if (path.basename(npm_parent_directory) === 'node_modules') { + // We are in a node install directory where this script lives in + // lib/node_modules/npm/node_modules/node-gyp/lib or + // node_modules/npm/node_modules/node-gyp/lib depending on the + // platform + if (processObj.platform === 'win32') { + node_root_dir = path.join(npm_parent_directory, '..') + } else { + node_root_dir = path.join(npm_parent_directory, '../..') + } + log.verbose('node-gyp root', 'in install directory, root = ' + + node_root_dir) + } else { + // We don't know where we are, try working it out from the location + // of the node binary + var node_dir = path.dirname(processObj.execPath) + var directory_up = path.basename(node_dir) + if (directory_up === 'bin') { + node_root_dir = path.join(node_dir, '..') + } else if (directory_up === 'Release' || directory_up === 'Debug') { + // If we are a recently built node, and the directory structure + // is that of a repository. If we are on Windows then we only need + // to go one level up, everything else, two + if (processObj.platform === 'win32') { + node_root_dir = path.join(node_dir, '..') + } else { + node_root_dir = path.join(node_dir, '../..') + } + } + // Else return the default blank, "". + } + return node_root_dir +} + +module.exports = findNodeDirectory diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-vs2017.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-vs2017.js new file mode 100644 index 0000000000000..ad46ceaf88c98 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-vs2017.js @@ -0,0 +1,46 @@ +var log = require('npmlog') + , execFile = require('child_process').execFile + , path = require('path') + +function findVS2017(callback) { + var ps = path.join(process.env.SystemRoot, 'System32', 'WindowsPowerShell', + 'v1.0', 'powershell.exe') + var csFile = path.join(__dirname, 'Find-VS2017.cs') + var psArgs = ['-ExecutionPolicy', 'Unrestricted', '-NoProfile', + '-Command', '&{Add-Type -Path \'' + csFile + '\';' + + '[VisualStudioConfiguration.Main]::Query()}'] + + log.silly('find vs2017', 'Running', ps, psArgs) + var child = execFile(ps, psArgs, { encoding: 'utf8' }, + function (err, stdout, stderr) { + log.silly('find vs2017', 'PS err:', err) + log.silly('find vs2017', 'PS stdout:', stdout) + log.silly('find vs2017', 'PS stderr:', stderr) + + if (err) + return callback(new Error('Could not use PowerShell to find VS2017')) + + var vsSetup + try { + vsSetup = JSON.parse(stdout) + } catch (e) { + log.silly('find vs2017', e) + return callback(new Error('Could not use PowerShell to find VS2017')) + } + log.silly('find vs2017', 'vsSetup:', vsSetup) + + if (vsSetup && vsSetup.log) + log.verbose('find vs2017', vsSetup.log.trimRight()) + + if (!vsSetup || !vsSetup.path || !vsSetup.sdk) { + return callback(new Error('No usable installation of VS2017 found')) + } + + log.verbose('find vs2017', 'using installation:', vsSetup.path) + callback(null, { "path": vsSetup.path, "sdk": vsSetup.sdk }) + }) + + child.stdin.end() +} + +module.exports = findVS2017 diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/install.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/install.js new file mode 100644 index 0000000000000..cb84972e18325 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/install.js @@ -0,0 +1,475 @@ +module.exports = exports = function (gyp, argv, callback) { + return install(fs, gyp, argv, callback) +} + +module.exports.test = { + download: download, + install: install, + readCAFile: readCAFile, +} + +exports.usage = 'Install node development files for the specified node version.' + +/** + * Module dependencies. + */ + +var fs = require('graceful-fs') + , osenv = require('osenv') + , tar = require('tar') + , rm = require('rimraf') + , path = require('path') + , crypto = require('crypto') + , zlib = require('zlib') + , log = require('npmlog') + , semver = require('semver') + , fstream = require('fstream') + , request = require('request') + , mkdir = require('mkdirp') + , processRelease = require('./process-release') + , win = process.platform == 'win32' + +function install (fs, gyp, argv, callback) { + + var release = processRelease(argv, gyp, process.version, process.release) + + // ensure no double-callbacks happen + function cb (err) { + if (cb.done) return + cb.done = true + if (err) { + log.warn('install', 'got an error, rolling back install') + // roll-back the install if anything went wrong + gyp.commands.remove([ release.versionDir ], function (err2) { + callback(err) + }) + } else { + callback(null, release.version) + } + } + + // Determine which node dev files version we are installing + log.verbose('install', 'input version string %j', release.version) + + if (!release.semver) { + // could not parse the version string with semver + return callback(new Error('Invalid version number: ' + release.version)) + } + + if (semver.lt(release.version, '0.8.0')) { + return callback(new Error('Minimum target version is `0.8.0` or greater. Got: ' + release.version)) + } + + // 0.x.y-pre versions are not published yet and cannot be installed. Bail. + if (release.semver.prerelease[0] === 'pre') { + log.verbose('detected "pre" node version', release.version) + if (gyp.opts.nodedir) { + log.verbose('--nodedir flag was passed; skipping install', gyp.opts.nodedir) + callback() + } else { + callback(new Error('"pre" versions of node cannot be installed, use the --nodedir flag instead')) + } + return + } + + // flatten version into String + log.verbose('install', 'installing version: %s', release.versionDir) + + // the directory where the dev files will be installed + var devDir = path.resolve(gyp.devDir, release.versionDir) + + // If '--ensure' was passed, then don't *always* install the version; + // check if it is already installed, and only install when needed + if (gyp.opts.ensure) { + log.verbose('install', '--ensure was passed, so won\'t reinstall if already installed') + fs.stat(devDir, function (err, stat) { + if (err) { + if (err.code == 'ENOENT') { + log.verbose('install', 'version not already installed, continuing with install', release.version) + go() + } else if (err.code == 'EACCES') { + eaccesFallback(err) + } else { + cb(err) + } + return + } + log.verbose('install', 'version is already installed, need to check "installVersion"') + var installVersionFile = path.resolve(devDir, 'installVersion') + fs.readFile(installVersionFile, 'ascii', function (err, ver) { + if (err && err.code != 'ENOENT') { + return cb(err) + } + var installVersion = parseInt(ver, 10) || 0 + log.verbose('got "installVersion"', installVersion) + log.verbose('needs "installVersion"', gyp.package.installVersion) + if (installVersion < gyp.package.installVersion) { + log.verbose('install', 'version is no good; reinstalling') + go() + } else { + log.verbose('install', 'version is good') + cb() + } + }) + }) + } else { + go() + } + + function getContentSha(res, callback) { + var shasum = crypto.createHash('sha256') + 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) + + // first create the dir for the node dev files + mkdir(devDir, function (err, created) { + if (err) { + if (err.code == 'EACCES') { + eaccesFallback(err) + } else { + cb(err) + } + return + } + + if (created) { + log.verbose('created nodedir', created) + } + + // now download the node tarball + var tarPath = gyp.opts.tarball + var 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 () { + var name = this.path.substring(devDir.length + 1) + var isValid = valid(name) + if (name === '' && this.type === 'Directory') { + // the first directory entry is ok + return true + } + if (isValid) { + log.verbose('extracted file from tarball', name) + extractCount++ + } else { + // invalid + log.silly('ignoring from tarball', name) + } + return isValid + } + + gunzip.on('error', cb) + extracter.on('error', cb) + extracter.on('end', afterTarball) + + // download the tarball, gunzip and extract! + + if (tarPath) { + var input = fs.createReadStream(tarPath) + input.pipe(gunzip).pipe(extracter) + return + } + + try { + var req = download(gyp, process.env, release.tarballUrl) + } catch (e) { + return cb(e) + } + + // something went wrong downloading the tarball? + req.on('error', function (err) { + if (err.code === 'ENOTFOUND') { + return cb(new Error('This is most likely not a problem with node-gyp or the package itself and\n' + + 'is related to network connectivity. In most cases you are behind a proxy or have bad \n' + + 'network settings.')) + } + badDownload = true + cb(err) + }) + + req.on('close', function () { + if (extractCount === 0) { + cb(new Error('Connection closed while downloading tarball file')) + } + }) + + req.on('response', function (res) { + if (res.statusCode !== 200) { + badDownload = true + cb(new Error(res.statusCode + ' response downloading ' + release.tarballUrl)) + return + } + // content checksum + getContentSha(res, function (_, checksum) { + var filename = path.basename(release.tarballUrl).trim() + contentShasums[filename] = checksum + log.verbose('content checksum', filename, checksum) + }) + + // start unzipping and untaring + req.pipe(gunzip).pipe(extracter) + }) + + // invoked after the tarball has finished being extracted + function afterTarball () { + if (badDownload) return + if (extractCount === 0) { + return cb(new Error('There was a fatal problem while downloading/extracting the tarball')) + } + log.verbose('tarball', 'done parsing tarball') + var async = 0 + + if (win) { + // need to download node.lib + async++ + downloadNodeLib(deref) + } + + // write the "installVersion" file + async++ + var installVersionPath = path.resolve(devDir, 'installVersion') + fs.writeFile(installVersionPath, gyp.package.installVersion + '\n', deref) + + // Only download SHASUMS.txt if not using tarPath override + if (!tarPath) { + // download SHASUMS.txt + async++ + downloadShasums(deref) + } + + if (async === 0) { + // no async tasks required + cb() + } + + function deref (err) { + if (err) return cb(err) + + async-- + if (!async) { + log.verbose('download contents checksum', JSON.stringify(contentShasums)) + // check content shasums + for (var k in contentShasums) { + log.verbose('validating download checksum for ' + k, '(%s == %s)', contentShasums[k], expectShasums[k]) + if (contentShasums[k] !== expectShasums[k]) { + cb(new Error(k + ' local checksum ' + contentShasums[k] + ' not match remote ' + expectShasums[k])) + return + } + } + cb() + } + } + } + + function downloadShasums(done) { + log.verbose('check download content checksum, need to download `SHASUMS256.txt`...') + var shasumsPath = path.resolve(devDir, 'SHASUMS256.txt') + + log.verbose('checksum url', release.shasumsUrl) + try { + var req = download(gyp, process.env, release.shasumsUrl) + } catch (e) { + return cb(e) + } + + req.on('error', done) + req.on('response', function (res) { + if (res.statusCode !== 200) { + done(new Error(res.statusCode + ' status code downloading checksum')) + 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('checksum data', JSON.stringify(expectShasums)) + done() + }) + }) + } + + function downloadNodeLib (done) { + log.verbose('on Windows; need to download `' + release.name + '.lib`...') + var dir32 = path.resolve(devDir, 'ia32') + , dir64 = path.resolve(devDir, 'x64') + , libPath32 = path.resolve(dir32, release.name + '.lib') + , libPath64 = path.resolve(dir64, release.name + '.lib') + + log.verbose('32-bit ' + release.name + '.lib dir', dir32) + log.verbose('64-bit ' + release.name + '.lib dir', dir64) + log.verbose('`' + release.name + '.lib` 32-bit url', release.libUrl32) + log.verbose('`' + release.name + '.lib` 64-bit url', release.libUrl64) + + var async = 2 + mkdir(dir32, function (err) { + if (err) return done(err) + log.verbose('streaming 32-bit ' + release.name + '.lib to:', libPath32) + + try { + var req = download(gyp, process.env, release.libUrl32, cb) + } catch (e) { + return cb(e) + } + + req.on('error', done) + req.on('response', function (res) { + if (res.statusCode !== 200) { + done(new Error(res.statusCode + ' status code downloading 32-bit ' + release.name + '.lib')) + return + } + + getContentSha(res, function (_, checksum) { + contentShasums[release.libPath32] = checksum + log.verbose('content checksum', release.libPath32, checksum) + }) + + var ws = fs.createWriteStream(libPath32) + ws.on('error', cb) + req.pipe(ws) + }) + req.on('end', function () { + --async || done() + }) + }) + mkdir(dir64, function (err) { + if (err) return done(err) + log.verbose('streaming 64-bit ' + release.name + '.lib to:', libPath64) + + try { + var req = download(gyp, process.env, release.libUrl64, cb) + } catch (e) { + return cb(e) + } + + req.on('error', done) + req.on('response', function (res) { + if (res.statusCode !== 200) { + done(new Error(res.statusCode + ' status code downloading 64-bit ' + release.name + '.lib')) + return + } + + getContentSha(res, function (_, checksum) { + contentShasums[release.libPath64] = checksum + log.verbose('content checksum', release.libPath64, checksum) + }) + + var ws = fs.createWriteStream(libPath64) + ws.on('error', cb) + req.pipe(ws) + }) + req.on('end', function () { + --async || done() + }) + }) + } // downloadNodeLib() + + }) // mkdir() + + } // go() + + /** + * Checks if a given filename is "valid" for this installation. + */ + + function valid (file) { + // header files + var extname = path.extname(file); + return extname === '.h' || extname === '.gypi'; + } + + /** + * The EACCES fallback is a workaround for npm's `sudo` behavior, where + * it drops the permissions before invoking any child processes (like + * node-gyp). So what happens is the "nobody" user doesn't have + * permission to create the dev dir. As a fallback, make the tmpdir() be + * the dev dir for this installation. This is not ideal, but at least + * the compilation will succeed... + */ + + function eaccesFallback (err) { + var noretry = '--node_gyp_internal_noretry' + if (-1 !== argv.indexOf(noretry)) return cb(err) + var tmpdir = osenv.tmpdir() + gyp.devDir = path.resolve(tmpdir, '.node-gyp') + log.warn('EACCES', 'user "%s" does not have permission to access the dev dir "%s"', osenv.user(), devDir) + log.warn('EACCES', 'attempting to reinstall using temporary dev dir "%s"', gyp.devDir) + if (process.cwd() == tmpdir) { + log.verbose('tmpdir == cwd', 'automatically will remove dev files after to save disk space') + gyp.todo.push({ name: 'remove', args: argv }) + } + gyp.commands.install([noretry].concat(argv), cb) + } + +} + +function download (gyp, env, url) { + log.http('GET', url) + + var requestOpts = { + uri: url + , headers: { + 'User-Agent': 'node-gyp v' + gyp.version + ' (node ' + process.version + ')' + } + } + + var cafile = gyp.opts.cafile + if (cafile) { + requestOpts.ca = readCAFile(cafile) + } + + // basic support for a proxy server + var proxyUrl = gyp.opts.proxy + || env.http_proxy + || env.HTTP_PROXY + || env.npm_config_proxy + if (proxyUrl) { + if (/^https?:\/\//i.test(proxyUrl)) { + log.verbose('download', 'using proxy url: "%s"', proxyUrl) + requestOpts.proxy = proxyUrl + } else { + log.warn('download', 'ignoring invalid "proxy" config setting: "%s"', proxyUrl) + } + } + + var req = request(requestOpts) + req.on('response', function (res) { + log.http(res.statusCode, url) + }) + + return req +} + +function readCAFile (filename) { + // The CA file can contain multiple certificates so split on certificate + // boundaries. [\S\s]*? is used to match everything including newlines. + var ca = fs.readFileSync(filename, 'utf8') + var re = /(-----BEGIN CERTIFICATE-----[\S\s]*?-----END CERTIFICATE-----)/g + return ca.match(re) +} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/list.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/list.js new file mode 100644 index 0000000000000..9d680a56a434a --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/list.js @@ -0,0 +1,33 @@ + +module.exports = exports = list + +exports.usage = 'Prints a listing of the currently installed node development files' + +/** + * Module dependencies. + */ + +var fs = require('graceful-fs') + , path = require('path') + , log = require('npmlog') + +function list (gyp, args, callback) { + + var devDir = gyp.devDir + log.verbose('list', 'using node-gyp dir:', devDir) + + // readdir() the node-gyp dir + fs.readdir(devDir, onreaddir) + + function onreaddir (err, versions) { + if (err && err.code != 'ENOENT') { + return callback(err) + } + if (Array.isArray(versions)) { + versions = versions.filter(function (v) { return v != 'current' }) + } else { + versions = [] + } + callback(null, versions) + } +} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/node-gyp.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/node-gyp.js new file mode 100644 index 0000000000000..a841161e32eec --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/node-gyp.js @@ -0,0 +1,216 @@ + +/** + * Module exports. + */ + +module.exports = exports = gyp + +/** + * Module dependencies. + */ + +var fs = require('graceful-fs') + , path = require('path') + , nopt = require('nopt') + , log = require('npmlog') + , child_process = require('child_process') + , EE = require('events').EventEmitter + , inherits = require('util').inherits + , commands = [ + // Module build commands + 'build' + , 'clean' + , 'configure' + , 'rebuild' + // Development Header File management commands + , 'install' + , 'list' + , 'remove' + ] + , aliases = { + 'ls': 'list' + , 'rm': 'remove' + } + +// differentiate node-gyp's logs from npm's +log.heading = 'gyp' + +/** + * The `gyp` function. + */ + +function gyp () { + return new Gyp() +} + +function Gyp () { + var self = this + + this.devDir = '' + this.commands = {} + + commands.forEach(function (command) { + self.commands[command] = function (argv, callback) { + log.verbose('command', command, argv) + return require('./' + command)(self, argv, callback) + } + }) +} +inherits(Gyp, EE) +exports.Gyp = Gyp +var proto = Gyp.prototype + +/** + * Export the contents of the package.json. + */ + +proto.package = require('../package') + +/** + * nopt configuration definitions + */ + +proto.configDefs = { + help: Boolean // everywhere + , arch: String // 'configure' + , cafile: String // 'install' + , debug: Boolean // 'build' + , directory: String // bin + , make: String // 'build' + , msvs_version: String // 'configure' + , ensure: Boolean // 'install' + , solution: String // 'build' (windows only) + , proxy: String // 'install' + , devdir: String // everywhere + , nodedir: String // 'configure' + , loglevel: String // everywhere + , python: String // 'configure' + , 'dist-url': String // 'install' + , 'tarball': String // 'install' + , jobs: String // 'build' + , thin: String // 'configure' +} + +/** + * nopt shorthands + */ + +proto.shorthands = { + release: '--no-debug' + , C: '--directory' + , debug: '--debug' + , j: '--jobs' + , silly: '--loglevel=silly' + , verbose: '--loglevel=verbose' + , silent: '--loglevel=silent' +} + +/** + * expose the command aliases for the bin file to use. + */ + +proto.aliases = aliases + +/** + * Parses the given argv array and sets the 'opts', + * 'argv' and 'command' properties. + */ + +proto.parseArgv = function parseOpts (argv) { + this.opts = nopt(this.configDefs, this.shorthands, argv) + this.argv = this.opts.argv.remain.slice() + + var commands = this.todo = [] + + // create a copy of the argv array with aliases mapped + argv = this.argv.map(function (arg) { + // is this an alias? + if (arg in this.aliases) { + arg = this.aliases[arg] + } + return arg + }, this) + + // process the mapped args into "command" objects ("name" and "args" props) + argv.slice().forEach(function (arg) { + if (arg in this.commands) { + var args = argv.splice(0, argv.indexOf(arg)) + argv.shift() + if (commands.length > 0) { + commands[commands.length - 1].args = args + } + commands.push({ name: arg, args: [] }) + } + }, this) + if (commands.length > 0) { + commands[commands.length - 1].args = argv.splice(0) + } + + // support for inheriting config env variables from npm + var npm_config_prefix = 'npm_config_' + Object.keys(process.env).forEach(function (name) { + if (name.indexOf(npm_config_prefix) !== 0) return + var val = process.env[name] + if (name === npm_config_prefix + 'loglevel') { + log.level = val + } else { + // add the user-defined options to the config + name = name.substring(npm_config_prefix.length) + // gyp@741b7f1 enters an infinite loop when it encounters + // zero-length options so ensure those don't get through. + if (name) this.opts[name] = val + } + }, this) + + if (this.opts.loglevel) { + log.level = this.opts.loglevel + } + log.resume() +} + +/** + * Spawns a child process and emits a 'spawn' event. + */ + +proto.spawn = function spawn (command, args, opts) { + if (!opts) opts = {} + if (!opts.silent && !opts.stdio) { + opts.stdio = [ 0, 1, 2 ] + } + var cp = child_process.spawn(command, args, opts) + log.info('spawn', command) + log.info('spawn args', args) + return cp +} + +/** + * Returns the usage instructions for node-gyp. + */ + +proto.usage = function usage () { + var str = [ + '' + , ' Usage: node-gyp [options]' + , '' + , ' where is one of:' + , commands.map(function (c) { + return ' - ' + c + ' - ' + require('./' + c).usage + }).join('\n') + , '' + , 'node-gyp@' + this.version + ' ' + path.resolve(__dirname, '..') + , 'node@' + process.versions.node + ].join('\n') + return str +} + +/** + * Version number getter. + */ + +Object.defineProperty(proto, 'version', { + get: function () { + return this.package.version + } + , enumerable: true +}) + diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/process-release.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/process-release.js new file mode 100644 index 0000000000000..0d177f1c93e4d --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/process-release.js @@ -0,0 +1,155 @@ +var semver = require('semver') + , url = require('url') + , path = require('path') + , log = require('npmlog') + + // versions where -headers.tar.gz started shipping + , headersTarballRange = '>= 3.0.0 || ~0.12.10 || ~0.10.42' + , bitsre = /\/win-(x86|x64)\// + , bitsreV3 = /\/win-(x86|ia32|x64)\// // io.js v3.x.x shipped with "ia32" but should + // have been "x86" + +// Captures all the logic required to determine download URLs, local directory and +// file names. Inputs come from command-line switches (--target, --dist-url), +// `process.version` and `process.release` where it exists. +function processRelease (argv, gyp, defaultVersion, defaultRelease) { + var version = (semver.valid(argv[0]) && argv[0]) || gyp.opts.target || defaultVersion + , versionSemver = semver.parse(version) + , overrideDistUrl = gyp.opts['dist-url'] || gyp.opts.disturl + , isDefaultVersion + , isIojs + , name + , distBaseUrl + , baseUrl + , libUrl32 + , libUrl64 + , tarballUrl + , canGetHeaders + + if (!versionSemver) { + // not a valid semver string, nothing we can do + return { version: version } + } + // flatten version into String + version = versionSemver.version + + // defaultVersion should come from process.version so ought to be valid semver + isDefaultVersion = version === semver.parse(defaultVersion).version + + // can't use process.release if we're using --target=x.y.z + if (!isDefaultVersion) + defaultRelease = null + + if (defaultRelease) { + // v3 onward, has process.release + name = defaultRelease.name.replace(/io\.js/, 'iojs') // remove the '.' for directory naming purposes + isIojs = name === 'iojs' + } else { + // old node or alternative --target= + // semver.satisfies() doesn't like prerelease tags so test major directly + isIojs = versionSemver.major >= 1 && versionSemver.major < 4 + name = isIojs ? 'iojs' : 'node' + } + + // check for the nvm.sh standard mirror env variables + if (!overrideDistUrl) { + if (isIojs) { + if (process.env.IOJS_ORG_MIRROR) { + overrideDistUrl = process.env.IOJS_ORG_MIRROR + } else if (process.env.NVM_IOJS_ORG_MIRROR) {// remove on next semver-major + overrideDistUrl = process.env.NVM_IOJS_ORG_MIRROR + log.warn('download', + 'NVM_IOJS_ORG_MIRROR is deprecated and will be removed in node-gyp v4, ' + + 'please use IOJS_ORG_MIRROR') + } + } else { + if (process.env.NODEJS_ORG_MIRROR) { + overrideDistUrl = process.env.NODEJS_ORG_MIRROR + } else if (process.env.NVM_NODEJS_ORG_MIRROR) {// remove on next semver-major + overrideDistUrl = process.env.NVM_NODEJS_ORG_MIRROR + log.warn('download', + 'NVM_NODEJS_ORG_MIRROR is deprecated and will be removed in node-gyp v4, ' + + 'please use NODEJS_ORG_MIRROR') + } + } + } + + if (overrideDistUrl) + log.verbose('download', 'using dist-url', overrideDistUrl) + + if (overrideDistUrl) + distBaseUrl = overrideDistUrl.replace(/\/+$/, '') + else + distBaseUrl = isIojs ? 'https://iojs.org/download/release' : 'https://nodejs.org/dist' + distBaseUrl += '/v' + version + '/' + + // new style, based on process.release so we have a lot of the data we need + if (defaultRelease && defaultRelease.headersUrl && !overrideDistUrl) { + baseUrl = url.resolve(defaultRelease.headersUrl, './') + libUrl32 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || distBaseUrl, 'x86', versionSemver.major) + libUrl64 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || distBaseUrl, 'x64', versionSemver.major) + + return { + version: version, + semver: versionSemver, + name: name, + baseUrl: baseUrl, + tarballUrl: defaultRelease.headersUrl, + shasumsUrl: url.resolve(baseUrl, 'SHASUMS256.txt'), + versionDir: (name !== 'node' ? name + '-' : '') + version, + libUrl32: libUrl32, + libUrl64: libUrl64, + libPath32: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrl32).path)), + libPath64: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrl64).path)) + } + } + + // older versions without process.release are captured here and we have to make + // a lot of assumptions, additionally if you --target=x.y.z then we can't use the + // current process.release + + baseUrl = distBaseUrl + libUrl32 = resolveLibUrl(name, baseUrl, 'x86', versionSemver.major) + libUrl64 = resolveLibUrl(name, baseUrl, 'x64', versionSemver.major) + // making the bold assumption that anything with a version number >3.0.0 will + // have a *-headers.tar.gz file in its dist location, even some frankenstein + // custom version + canGetHeaders = semver.satisfies(versionSemver, headersTarballRange) + tarballUrl = url.resolve(baseUrl, name + '-v' + version + (canGetHeaders ? '-headers' : '') + '.tar.gz') + + return { + version: version, + semver: versionSemver, + name: name, + baseUrl: baseUrl, + tarballUrl: tarballUrl, + shasumsUrl: url.resolve(baseUrl, 'SHASUMS256.txt'), + versionDir: (name !== 'node' ? name + '-' : '') + version, + libUrl32: libUrl32, + libUrl64: libUrl64, + libPath32: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrl32).path)), + libPath64: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrl64).path)) + } +} + +function normalizePath (p) { + return path.normalize(p).replace(/\\/g, '/') +} + +function resolveLibUrl (name, defaultUrl, arch, versionMajor) { + var base = url.resolve(defaultUrl, './') + , hasLibUrl = bitsre.test(defaultUrl) || (versionMajor === 3 && bitsreV3.test(defaultUrl)) + + if (!hasLibUrl) { + // let's assume it's a baseUrl then + if (versionMajor >= 1) + return url.resolve(base, 'win-' + arch +'/' + name + '.lib') + // prior to io.js@1.0.0 32-bit node.lib lives in /, 64-bit lives in /x64/ + return url.resolve(base, (arch === 'x64' ? 'x64/' : '') + name + '.lib') + } + + // else we have a proper url to a .lib, just make sure it's the right arch + return defaultUrl.replace(versionMajor === 3 ? bitsreV3 : bitsre, '/win-' + arch + '/') +} + +module.exports = processRelease diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/rebuild.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/rebuild.js new file mode 100644 index 0000000000000..4c6f472aa7c07 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/rebuild.js @@ -0,0 +1,14 @@ + +module.exports = exports = rebuild + +exports.usage = 'Runs "clean", "configure" and "build" all at once' + +function rebuild (gyp, argv, callback) { + + gyp.todo.push( + { name: 'clean', args: [] } + , { name: 'configure', args: argv } + , { name: 'build', args: [] } + ) + process.nextTick(callback) +} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/remove.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/remove.js new file mode 100644 index 0000000000000..eb80981b88feb --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/remove.js @@ -0,0 +1,52 @@ + +module.exports = exports = remove + +exports.usage = 'Removes the node development files for the specified version' + +/** + * Module dependencies. + */ + +var fs = require('fs') + , rm = require('rimraf') + , path = require('path') + , log = require('npmlog') + , semver = require('semver') + +function remove (gyp, argv, callback) { + + var devDir = gyp.devDir + log.verbose('remove', 'using node-gyp dir:', devDir) + + // get the user-specified version to remove + var version = argv[0] || gyp.opts.target + log.verbose('remove', 'removing target version:', version) + + if (!version) { + return callback(new Error('You must specify a version number to remove. Ex: "' + process.version + '"')) + } + + var versionSemver = semver.parse(version) + if (versionSemver) { + // flatten the version Array into a String + version = versionSemver.version + } + + var versionPath = path.resolve(gyp.devDir, version) + log.verbose('remove', 'removing development files for version:', version) + + // first check if its even installed + fs.stat(versionPath, function (err, stat) { + if (err) { + if (err.code == 'ENOENT') { + callback(null, 'version was already uninstalled: ' + version) + } else { + callback(err) + } + return + } + // Go ahead and delete the dir + rm(versionPath, callback) + }) + +} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/package.json b/node_modules/npm-lifecycle/node_modules/node-gyp/package.json new file mode 100644 index 0000000000000..6a1cda10d52a4 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/package.json @@ -0,0 +1,85 @@ +{ + "_from": "node-gyp@^3.8.0", + "_id": "node-gyp@3.8.0", + "_inBundle": false, + "_integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "_location": "/npm-lifecycle/node-gyp", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "node-gyp@^3.8.0", + "name": "node-gyp", + "escapedName": "node-gyp", + "rawSpec": "^3.8.0", + "saveSpec": null, + "fetchSpec": "^3.8.0" + }, + "_requiredBy": [ + "/npm-lifecycle" + ], + "_resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "_shasum": "540304261c330e80d0d5edce253a68cb3964218c", + "_spec": "node-gyp@^3.8.0", + "_where": "/home/hugh/Development/github.com/npm/cli/node_modules/npm-lifecycle", + "author": { + "name": "Nathan Rajlich", + "email": "nathan@tootallnate.net", + "url": "http://tootallnate.net" + }, + "bin": { + "node-gyp": "./bin/node-gyp.js" + }, + "bugs": { + "url": "https://github.com/nodejs/node-gyp/issues" + }, + "bundleDependencies": false, + "dependencies": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + }, + "deprecated": false, + "description": "Node.js native addon build tool", + "devDependencies": { + "bindings": "~1.2.1", + "nan": "^2.0.0", + "require-inject": "~1.3.0", + "tape": "~4.2.0" + }, + "engines": { + "node": ">= 0.8.0" + }, + "homepage": "https://github.com/nodejs/node-gyp#readme", + "installVersion": 9, + "keywords": [ + "native", + "addon", + "module", + "c", + "c++", + "bindings", + "gyp" + ], + "license": "MIT", + "main": "./lib/node-gyp.js", + "name": "node-gyp", + "preferGlobal": true, + "repository": { + "type": "git", + "url": "git://github.com/nodejs/node-gyp.git" + }, + "scripts": { + "test": "tape test/test-*" + }, + "version": "3.8.0" +} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/src/win_delay_load_hook.cc b/node_modules/npm-lifecycle/node_modules/node-gyp/src/win_delay_load_hook.cc new file mode 100644 index 0000000000000..e75954b605101 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/src/win_delay_load_hook.cc @@ -0,0 +1,36 @@ +/* + * When this file is linked to a DLL, it sets up a delay-load hook that + * intervenes when the DLL is trying to load 'node.exe' or 'iojs.exe' + * dynamically. Instead of trying to locate the .exe file it'll just return + * a handle to the process image. + * + * This allows compiled addons to work when node.exe or iojs.exe is renamed. + */ + +#ifdef _MSC_VER + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif + +#include + +#include +#include + +static FARPROC WINAPI load_exe_hook(unsigned int event, DelayLoadInfo* info) { + HMODULE m; + if (event != dliNotePreLoadLibrary) + return NULL; + + if (_stricmp(info->szDll, "iojs.exe") != 0 && + _stricmp(info->szDll, "node.exe") != 0) + return NULL; + + m = GetModuleHandle(NULL); + return (FARPROC) m; +} + +decltype(__pfnDliNotifyHook2) __pfnDliNotifyHook2 = load_exe_hook; + +#endif diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/docker.sh b/node_modules/npm-lifecycle/node_modules/node-gyp/test/docker.sh new file mode 100755 index 0000000000000..ac21aa8d75c98 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/docker.sh @@ -0,0 +1,164 @@ +#!/bin/bash + +#set -e + +test_node_versions="0.8.28 0.10.40 0.12.7 4.3.0 5.6.0" +test_iojs_versions="1.8.4 2.4.0 3.3.0" + +myuid=$(id -u) +mygid=$(id -g) +__dirname="$(CDPATH= cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +dot_node_gyp=${__dirname}/.node-gyp/ + +# borrows from https://github.com/rvagg/dnt/ + +# Simple setup function for a container: +# setup_container(image id, base image, commands to run to set up) +setup_container() { + local container_id="$1" + local base_container="$2" + local run_cmd="$3" + + # Does this image exist? If yes, ignore + docker inspect "$container_id" &> /dev/null + if [[ $? -eq 0 ]]; then + echo "Found existing container [$container_id]" + else + # No such image, so make it + echo "Did not find container [$container_id], creating..." + docker run -i $base_container /bin/bash -c "$run_cmd" + sleep 2 + docker commit $(docker ps -l -q) $container_id + fi +} + +# Run tests inside each of the versioned containers, copy cwd into npm's copy of node-gyp +# so it'll be invoked by npm when a compile is needed +# run_tests(version, test-commands) +run_tests() { + local version="$1" + local run_cmd="$2" + + run_cmd="rsync -aAXx --delete --exclude .git --exclude build /node-gyp-src/ /usr/lib/node_modules/npm/node_modules/node-gyp/; + /bin/su -s /bin/bash node-gyp -c 'cd && ${run_cmd}'" + + rm -rf $dot_node_gyp + mkdir $dot_node_gyp + + docker run \ + --rm -i \ + -v ~/.npm/:/node-gyp/.npm/ \ + -v ${dot_node_gyp}:/node-gyp/.node-gyp/ \ + -v $(pwd):/node-gyp-src/:ro \ + node-gyp-test/${version} /bin/bash -c "${run_cmd}" +} + +# A base image with build tools and a user account +setup_container "node-gyp-test/base" "ubuntu:14.04" " + adduser --gecos node-gyp --home /node-gyp/ --disabled-login node-gyp --uid $myuid && + echo "node-gyp:node-gyp" | chpasswd && + apt-get update && + apt-get install -y build-essential python git rsync curl +" + +# An image on top of the base containing clones of repos we want to use for testing +setup_container "node-gyp-test/clones" "node-gyp-test/base" " + cd /node-gyp/ && git clone https://github.com/justmoon/node-bignum.git && + cd /node-gyp/ && git clone https://github.com/bnoordhuis/node-buffertools.git && + chown -R node-gyp.node-gyp /node-gyp/ +" + +# An image for each of the node versions we want to test with that version installed and the latest npm +for v in $test_node_versions; do + setup_container "node-gyp-test/${v}" "node-gyp-test/clones" " + curl -sL https://nodejs.org/dist/v${v}/node-v${v}-linux-x64.tar.gz | tar -zxv --strip-components=1 -C /usr/ && + npm install npm@latest -g && + node -v && npm -v + " +done + +# An image for each of the io.js versions we want to test with that version installed and the latest npm +for v in $test_iojs_versions; do + setup_container "node-gyp-test/${v}" "node-gyp-test/clones" " + curl -sL https://iojs.org/dist/v${v}/iojs-v${v}-linux-x64.tar.gz | tar -zxv --strip-components=1 -C /usr/ && + npm install npm@latest -g && + node -v && npm -v + " +done + +# Run the tests for all of the test images we've created, +# we should see node-gyp doing its download, configure and run thing +# _NOTE: bignum doesn't compile on 0.8 currently so it'll fail for that version only_ +for v in $test_node_versions $test_iojs_versions; do + run_tests $v " + cd node-buffertools && npm install --loglevel=info && npm test && cd + " + # removed for now, too noisy: cd node-bignum && npm install --loglevel=info && npm test +done + +# Test use of --target=x.y.z to compile against alternate versions +test_download_node_version() { + local run_with_ver="$1" + local expected_dir="$2" + local expected_ver="$3" + run_tests $run_with_ver "cd node-buffertools && npm install --loglevel=info --target=${expected_ver}" + local node_ver=$(cat "${dot_node_gyp}${expected_dir}/node_version.h" | grep '#define NODE_\w*_VERSION [0-9]*$') + node_ver=$(echo $node_ver | sed 's/#define NODE_[A-Z]*_VERSION //g' | sed 's/ /./g') + if [ "X$(echo $node_ver)" != "X${expected_ver}" ]; then + echo "Did not download v${expected_ver} using --target, instead got: $(echo $node_ver)" + exit 1 + fi + echo "Verified correct download of [v${node_ver}]" +} + +test_download_node_version "0.12.7" "0.10.30/src" "0.10.30" +test_download_node_version "3.3.0" "iojs-1.8.4/src" "1.8.4" +# should download the headers file +test_download_node_version "3.3.0" "iojs-3.3.0/include/node" "3.3.0" +test_download_node_version "4.3.0" "4.3.0/include/node" "4.3.0" +test_download_node_version "5.6.0" "5.6.0/include/node" "5.6.0" + +# TODO: test --dist-url by starting up a localhost server and serving up tarballs + +# testing --dist-url, using simple-proxy.js to make localhost work as a distribution +# point for tarballs +# we can test whether it uses the proxy because after 2 connections the proxy will +# die and therefore should not be running at the end of the test, `nc` can tell us this +run_tests "3.3.0" " + (node /node-gyp-src/test/simple-proxy.js 8080 /foobar/ https://iojs.org/dist/ &) && + cd node-buffertools && + /node-gyp-src/bin/node-gyp.js --loglevel=info --dist-url=http://localhost:8080/foobar/ rebuild && + nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\" +" + +# REMOVE after next semver-major +run_tests "3.3.0" " + (node /node-gyp-src/test/simple-proxy.js 8080 /doobar/ https://iojs.org/dist/ &) && + cd node-buffertools && + NVM_IOJS_ORG_MIRROR=http://localhost:8080/doobar/ /node-gyp-src/bin/node-gyp.js --loglevel=info rebuild && + nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\" +" + +# REMOVE after next semver-major +run_tests "0.12.7" " + (node /node-gyp-src/test/simple-proxy.js 8080 /boombar/ https://nodejs.org/dist/ &) && + cd node-buffertools && + NVM_NODEJS_ORG_MIRROR=http://localhost:8080/boombar/ /node-gyp-src/bin/node-gyp.js --loglevel=info rebuild && + nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\" +" + +run_tests "3.3.0" " + (node /node-gyp-src/test/simple-proxy.js 8080 /doobar/ https://iojs.org/dist/ &) && + cd node-buffertools && + IOJS_ORG_MIRROR=http://localhost:8080/doobar/ /node-gyp-src/bin/node-gyp.js --loglevel=info rebuild && + nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\" +" + +run_tests "0.12.7" " + (node /node-gyp-src/test/simple-proxy.js 8080 /boombar/ https://nodejs.org/dist/ &) && + cd node-buffertools && + NODEJS_ORG_MIRROR=http://localhost:8080/boombar/ /node-gyp-src/bin/node-gyp.js --loglevel=info rebuild && + nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\" +" + +rm -rf $dot_node_gyp diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca-bundle.crt b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca-bundle.crt new file mode 100644 index 0000000000000..fb1dea98a78c8 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca-bundle.crt @@ -0,0 +1,40 @@ +-----BEGIN CERTIFICATE----- +MIIDJjCCAg4CAhnOMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQU3Ryb25n +TG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRowGAYDVQQDDBFjYS5zdHJv +bmdsb29wLmNvbTAeFw0xNTEyMDgyMzM1MzNaFw00MzA0MjQyMzM1MzNaMBkxFzAV +BgNVBAMMDnN0cm9uZ2xvb3AuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAwOYI7OZ2FX/YjRgLZoDQlbPc5UZXU/j0e1wwiJNPtPEax9Y5Uoza0Pnt +Ikzkc2SfvQ+IJrhXo385tI0W5juuqbHnE7UrjUuPjUX6NHevkxcs/flmjan5wnZM +cPsGhH71WDuUEEflvZihf2Se2x+xgZtMhc5XGmVmRuZFYKvkgUhA2/w8/QrK+jPT +n9QRJxZjWNh2RBdC1B7u4jffSmOSUljYFH1I2eTeY+Rdi6YUIYSU9gEoZxsv3Tia +SomfMF5jt2Mouo6MzA+IhLvvFjcrcph1Qxgi9RkfdCMMd+Ipm9YWELkyG1bDRpQy +0iyHD4gvVsAqz1Y2KdRSdc3Kt+nTqwIDAQABoxkwFzAVBgNVHREEDjAMhwQAAAAA +hwR/AAABMA0GCSqGSIb3DQEBBQUAA4IBAQAhy4J0hML3NgmDRHdL5/iTucBe22Mf +jJjg2aifD1S187dHm+Il4qZNO2plWwAhN0h704f+8wpsaALxUvBIu6nvlvcMP5PH +jGN5JLe2Km3UaPvYOQU2SgacLilu+uBcIo2JSHLV6O7ziqUj5Gior6YxDLCtEZie +Ea8aX5/YjuACtEMJ1JjRqjgkM66XAoUe0E8onOK3FgTIO3tGoTJwRp0zS50pFuP0 +PsZtT04ck6mmXEXXknNoAyBCvPypfms9OHqcUIW9fiQnrGbS/Ri4QSQYj0DtFk/1 +na4fY1gf3zTHxH8259b/TOOaPfTnCEsOQtjUrWNR4xhmVZ+HJy4yytUW +-----END CERTIFICATE----- +-----BEGIN CERTIFICATE----- +MIIDbzCCAlcCAmm6MA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQU3Ryb25n +TG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRowGAYDVQQDDBFjYS5zdHJv +bmdsb29wLmNvbTAeFw0xNTEyMDgyMzM1MzNaFw00MzA0MjQyMzM1MzNaMH0xCzAJ +BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZ +MBcGA1UECgwQU3Ryb25nTG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRow +GAYDVQQDDBFjYS5zdHJvbmdsb29wLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBANfj86jkvvYDjHBgiqWhk9Cj+bqiMq3MqnV0CBO4iuK33Fo6XssE +H+yVdXlIBFbFe6t655MdBVOR2Sfj7WqNh96vhu6PyDHiwcQlTaiLU6nhIed1J4Wv +lvnJHFmp8Wbtx5AgLT4UYu03ftvXEl2DLi3vhSL2tRM1ebXHB/KPbRWkb25DPX0P +foOHot3f2dgNe2x6kponf7E/QDmAu3s7Nlkfh+ryDhgGU7wocXEhXbprNqRqOGNo +xbXgUI+/9XDxYT/7Gn5LF/fPjtN+aB0SKMnTsDhprVlZie83mlqJ46fOOrR+vrsQ +mi/1m/TadrARtZoIExC/cQRdVM05EK4tUa8CAwEAATANBgkqhkiG9w0BAQsFAAOC +AQEAQ7k5WhyhDTIGYCNzRnrMHWSzGqa1y4tJMW06wafJNRqTm1cthq1ibc6Hfq5a +K10K0qMcgauRTfQ1MWrVCTW/KnJ1vkhiTOH+RvxapGn84gSaRmV6KZen0+gMsgae +KEGe/3Hn+PmDVV+PTamHgPACfpTww38WHIe/7Ce9gHfG7MZ8cKHNZhDy0IAYPln+ +YRwMLd7JNQffHAbWb2CE1mcea4H/12U8JZW5tHCF6y9V+7IuDzqwIrLKcW3lG17n +VUG6ODF/Ryqn3V5X+TL91YyXi6c34y34IpC7MQDV/67U7+5Bp5CfeDPWW2wVSrW+ +uGZtfEvhbNm6m2i4UNmpCXxUZQ== +-----END CERTIFICATE----- diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca.crt b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca.crt new file mode 100644 index 0000000000000..9d2755a74f6cd --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca.crt @@ -0,0 +1,21 @@ +-----BEGIN CERTIFICATE----- +MIIDbzCCAlcCAmm6MA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQU3Ryb25n +TG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRowGAYDVQQDDBFjYS5zdHJv +bmdsb29wLmNvbTAeFw0xNTEyMDgyMzM1MzNaFw00MzA0MjQyMzM1MzNaMH0xCzAJ +BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZ +MBcGA1UECgwQU3Ryb25nTG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRow +GAYDVQQDDBFjYS5zdHJvbmdsb29wLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP +ADCCAQoCggEBANfj86jkvvYDjHBgiqWhk9Cj+bqiMq3MqnV0CBO4iuK33Fo6XssE +H+yVdXlIBFbFe6t655MdBVOR2Sfj7WqNh96vhu6PyDHiwcQlTaiLU6nhIed1J4Wv +lvnJHFmp8Wbtx5AgLT4UYu03ftvXEl2DLi3vhSL2tRM1ebXHB/KPbRWkb25DPX0P +foOHot3f2dgNe2x6kponf7E/QDmAu3s7Nlkfh+ryDhgGU7wocXEhXbprNqRqOGNo +xbXgUI+/9XDxYT/7Gn5LF/fPjtN+aB0SKMnTsDhprVlZie83mlqJ46fOOrR+vrsQ +mi/1m/TadrARtZoIExC/cQRdVM05EK4tUa8CAwEAATANBgkqhkiG9w0BAQsFAAOC +AQEAQ7k5WhyhDTIGYCNzRnrMHWSzGqa1y4tJMW06wafJNRqTm1cthq1ibc6Hfq5a +K10K0qMcgauRTfQ1MWrVCTW/KnJ1vkhiTOH+RvxapGn84gSaRmV6KZen0+gMsgae +KEGe/3Hn+PmDVV+PTamHgPACfpTww38WHIe/7Ce9gHfG7MZ8cKHNZhDy0IAYPln+ +YRwMLd7JNQffHAbWb2CE1mcea4H/12U8JZW5tHCF6y9V+7IuDzqwIrLKcW3lG17n +VUG6ODF/Ryqn3V5X+TL91YyXi6c34y34IpC7MQDV/67U7+5Bp5CfeDPWW2wVSrW+ +uGZtfEvhbNm6m2i4UNmpCXxUZQ== +-----END CERTIFICATE----- diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.crt b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.crt new file mode 100644 index 0000000000000..fe13bb96c599c --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.crt @@ -0,0 +1,19 @@ +-----BEGIN CERTIFICATE----- +MIIDJjCCAg4CAhnOMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNVBAYTAlVTMQswCQYD +VQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQU3Ryb25n +TG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRowGAYDVQQDDBFjYS5zdHJv +bmdsb29wLmNvbTAeFw0xNTEyMDgyMzM1MzNaFw00MzA0MjQyMzM1MzNaMBkxFzAV +BgNVBAMMDnN0cm9uZ2xvb3AuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAwOYI7OZ2FX/YjRgLZoDQlbPc5UZXU/j0e1wwiJNPtPEax9Y5Uoza0Pnt +Ikzkc2SfvQ+IJrhXo385tI0W5juuqbHnE7UrjUuPjUX6NHevkxcs/flmjan5wnZM +cPsGhH71WDuUEEflvZihf2Se2x+xgZtMhc5XGmVmRuZFYKvkgUhA2/w8/QrK+jPT +n9QRJxZjWNh2RBdC1B7u4jffSmOSUljYFH1I2eTeY+Rdi6YUIYSU9gEoZxsv3Tia +SomfMF5jt2Mouo6MzA+IhLvvFjcrcph1Qxgi9RkfdCMMd+Ipm9YWELkyG1bDRpQy +0iyHD4gvVsAqz1Y2KdRSdc3Kt+nTqwIDAQABoxkwFzAVBgNVHREEDjAMhwQAAAAA +hwR/AAABMA0GCSqGSIb3DQEBBQUAA4IBAQAhy4J0hML3NgmDRHdL5/iTucBe22Mf +jJjg2aifD1S187dHm+Il4qZNO2plWwAhN0h704f+8wpsaALxUvBIu6nvlvcMP5PH +jGN5JLe2Km3UaPvYOQU2SgacLilu+uBcIo2JSHLV6O7ziqUj5Gior6YxDLCtEZie +Ea8aX5/YjuACtEMJ1JjRqjgkM66XAoUe0E8onOK3FgTIO3tGoTJwRp0zS50pFuP0 +PsZtT04ck6mmXEXXknNoAyBCvPypfms9OHqcUIW9fiQnrGbS/Ri4QSQYj0DtFk/1 +na4fY1gf3zTHxH8259b/TOOaPfTnCEsOQtjUrWNR4xhmVZ+HJy4yytUW +-----END CERTIFICATE----- diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.key b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.key new file mode 100644 index 0000000000000..f8227f4c0c2d4 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDA5gjs5nYVf9iN +GAtmgNCVs9zlRldT+PR7XDCIk0+08RrH1jlSjNrQ+e0iTORzZJ+9D4gmuFejfzm0 +jRbmO66psecTtSuNS4+NRfo0d6+TFyz9+WaNqfnCdkxw+waEfvVYO5QQR+W9mKF/ +ZJ7bH7GBm0yFzlcaZWZG5kVgq+SBSEDb/Dz9Csr6M9Of1BEnFmNY2HZEF0LUHu7i +N99KY5JSWNgUfUjZ5N5j5F2LphQhhJT2AShnGy/dOJpKiZ8wXmO3Yyi6jozMD4iE +u+8WNytymHVDGCL1GR90Iwx34imb1hYQuTIbVsNGlDLSLIcPiC9WwCrPVjYp1FJ1 +zcq36dOrAgMBAAECggEACg60Xm2xsHNG/ixHw+NpfLSxCr89JGKxlJD88tIDcOK1 +S8AOoxA3BHhTddteeenALmJV7fbkkuC6SICmtgBcnfppmuxyRd6vsGT6o6ut2tR1 +gxRy1WYMYKg8WhOshlH8RspscODeyKDhorvDUJd5cNGBDuTwQ68PwxiUe3La6iac +EVQoKohg9EmRIhMF1i8I00zXE8p3XENrlTc491ipc+gLPIP5vtqHyQztEUkZHkWd +dXbs+n1hGCr+4FxrphGYEW80HINzmume7dGChr8nvF4ZZcuWW13DJuNim6pQno1i +hM8VdXm8XphLh0XEGI5OCfu/CetkBILZRXKltZk6AQKBgQDoBqJzRlp7regYNU4q +usfS+43tPNaJ0o4DIzcLawqpmK/B/cZStzHl14Sm62BVkKV6cnWAJPeLkENPMFoV +7Q7wLZBJxpPzqXkpeiDkKN4Wovca891Rffne5Sz6IDB5mOxMjfKIEPd5RkmB5Lkp +qQLwm3YJ2AJcLagG/Gi1DFDRAQKBgQDU1G9T43Mjke6TXG0u7gCSb+VwyDRsrvJA +u2vy6+MANRc1EEF31YLmTKOU5XxUmhtIu7TUbgPoNi0HuRFXx4Zul3BPlAosLMJv +kNQbA/9d0YQAfSgTsploN5CX65dLZ4ejIzVgDZREzpIBWTze6YZTA2DT5iOIet84 +DD5DujY4qwKBgG0PuUo/9oYOD3tZiv1wwD5+uY6auykbTF9TLStzzBY9y9d+hrsY +mx6zOAoRtz1g+TdeF7b9KVJzo//T9XQ68nuYnyreaWrt7SK+4jj8sK+pOEd1+0Cz +20CXLpX/jWmKpP+y9R5aA0kA7cpdjV90rwoTuN8Vpr5XQ5TNDhaTzGUBAoGABYig +fGXlkH8y3NICZL37ddNC+/O4qTrDQbudyusnM9ItkEuj6CG9DY/gkPaGjQyUuQdo +ZD2YDGmcMh81vDqL3ERDv03yFcP0KkJxwWIRObdA32JhsGFsa7FGKS0O+f7vH+bC +dITl3gQg97gCRSl9PJtR4TCSq/HF7Acld01YK5ECgYEAwLFB5JIuxrowJe74cCMP +n5Rwuc8vWdOsg+ytvQTv0/hVCdzcaLet6YvagnWTWaU7PUwTFxZs/mLQ9CAWVutK +IRzs/GWxGFjH5xotDaJdDDzSdQye4tUqvUVxv7zzzsVycCPBYFkyRQ8Tmr5FLtUJ +Cl48TZ6J8Rx5avjdtOw3QC8= +-----END PRIVATE KEY----- diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/test-charmap.py b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/test-charmap.py new file mode 100644 index 0000000000000..d9fa6fb25e6c6 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/test-charmap.py @@ -0,0 +1,22 @@ +import sys +import locale + +reload(sys) + +def main(): + encoding = locale.getdefaultlocale()[1] + if not encoding: + return False + + sys.setdefaultencoding(encoding) + textmap = { + 'cp936': u'\u4e2d\u6587', + 'cp1252': u'Lat\u012Bna', + 'cp932': u'\u306b\u307b\u3093\u3054' + } + if textmap.has_key(encoding): + print textmap[encoding] + return True + +if __name__ == '__main__': + print main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/process-exec-sync.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/process-exec-sync.js new file mode 100644 index 0000000000000..859cbc1f6fe2b --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/process-exec-sync.js @@ -0,0 +1,138 @@ +'use strict' + +var fs = require('graceful-fs') +var child_process = require('child_process') + +if (!String.prototype.startsWith) { + String.prototype.startsWith = function(search, pos) { + return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search + } +} + +function processExecSync(file, args, options) { + var child, error, timeout, tmpdir, command, quote + command = makeCommand(file, args) + + /* + this function emulates child_process.execSync for legacy node <= 0.10.x + derived from https://github.com/gvarsanyi/sync-exec/blob/master/js/sync-exec.js + */ + + options = options || {} + // init timeout + timeout = Date.now() + options.timeout + // init tmpdir + var os_temp_base = '/tmp' + var os = determine_os() + os_temp_base = '/tmp' + + if (process.env.TMP) { + os_temp_base = process.env.TMP + } + + if (os_temp_base[os_temp_base.length - 1] !== '/') { + os_temp_base += '/' + } + + tmpdir = os_temp_base + 'processExecSync.' + Date.now() + Math.random() + fs.mkdirSync(tmpdir) + + // init command + if (os === 'linux') { + command = '(' + command + ' > ' + tmpdir + '/stdout 2> ' + tmpdir + + '/stderr); echo $? > ' + tmpdir + '/status' + } else { + command = '(' + command + ' > ' + tmpdir + '/stdout 2> ' + tmpdir + + '/stderr) | echo %errorlevel% > ' + tmpdir + '/status | exit' + } + + // init child + child = child_process.exec(command, options) + + var maxTry = 100000 // increases the test time by 6 seconds on win-2016-node-0.10 + var tryCount = 0 + while (tryCount < maxTry) { + try { + var x = fs.readFileSync(tmpdir + '/status') + if (x.toString() === '0') { + break + } + } catch (ignore) {} + tryCount++ + if (Date.now() > timeout) { + error = child + break + } + } + + ['stdout', 'stderr', 'status'].forEach(function (file) { + child[file] = fs.readFileSync(tmpdir + '/' + file, options.encoding) + setTimeout(unlinkFile, 500, tmpdir + '/' + file) + }) + + child.status = Number(child.status) + if (child.status !== 0) { + error = child + } + + try { + fs.rmdirSync(tmpdir) + } catch (ignore) {} + if (error) { + throw error + } + return child.stdout +} + +function makeCommand(file, args) { + var command, quote + command = file + if (args.length > 0) { + for(var i in args) { + command = command + ' ' + if (args[i][0] === '-') { + command = command + args[i] + } else { + if (!quote) { + command = command + '\"' + quote = true + } + command = command + args[i] + if (quote) { + if (args.length === (parseInt(i) + 1)) { + command = command + '\"' + } + } + } + } + } + return command +} + +function determine_os() { + var os = '' + var tmpVar = '' + if (process.env.OSTYPE) { + tmpVar = process.env.OSTYPE + } else if (process.env.OS) { + tmpVar = process.env.OS + } else { + //default is linux + tmpVar = 'linux' + } + + if (tmpVar.startsWith('linux')) { + os = 'linux' + } + if (tmpVar.startsWith('win')) { + os = 'win' + } + + return os +} + +function unlinkFile(file) { + fs.unlinkSync(file) +} + +module.exports = processExecSync diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/simple-proxy.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/simple-proxy.js new file mode 100644 index 0000000000000..e55330c445bf6 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/simple-proxy.js @@ -0,0 +1,24 @@ +var http = require('http') + , https = require('https') + , server = http.createServer(handler) + , port = +process.argv[2] + , prefix = process.argv[3] + , upstream = process.argv[4] + , calls = 0 + +server.listen(port) + +function handler (req, res) { + if (req.url.indexOf(prefix) != 0) + throw new Error('request url [' + req.url + '] does not start with [' + prefix + ']') + + var upstreamUrl = upstream + req.url.substring(prefix.length) + console.log(req.url + ' -> ' + upstreamUrl) + https.get(upstreamUrl, function (ures) { + ures.on('end', function () { + if (++calls == 2) + server.close() + }) + ures.pipe(res) + }) +} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-addon.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-addon.js new file mode 100644 index 0000000000000..89350effc46b4 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-addon.js @@ -0,0 +1,113 @@ +'use strict' + +var test = require('tape') +var path = require('path') +var fs = require('graceful-fs') +var child_process = require('child_process') +var addonPath = path.resolve(__dirname, 'node_modules', 'hello_world') +var nodeGyp = path.resolve(__dirname, '..', 'bin', 'node-gyp.js') +var execFileSync = child_process.execFileSync || require('./process-exec-sync') +var execFile = child_process.execFile + +function runHello() { + var testCode = "console.log(require('hello_world').hello())" + return execFileSync(process.execPath, ['-e', testCode], { cwd: __dirname }).toString() +} + +function getEncoding() { + var code = 'import locale;print locale.getdefaultlocale()[1]' + return execFileSync('python', ['-c', code]).toString().trim() +} + +function checkCharmapValid() { + var data + try { + data = execFileSync('python', ['fixtures/test-charmap.py'], + { cwd: __dirname }) + } catch (err) { + return false + } + var lines = data.toString().trim().split('\n') + return lines.pop() === 'True' +} + +test('build simple addon', function (t) { + t.plan(3) + + // Set the loglevel otherwise the output disappears when run via 'npm test' + var cmd = [nodeGyp, 'rebuild', '-C', addonPath, '--loglevel=verbose'] + var proc = execFile(process.execPath, cmd, function (err, stdout, stderr) { + var logLines = stderr.toString().trim().split(/\r?\n/) + var lastLine = logLines[logLines.length-1] + t.strictEqual(err, null) + t.strictEqual(lastLine, 'gyp info ok', 'should end in ok') + t.strictEqual(runHello().trim(), 'world') + }) + proc.stdout.setEncoding('utf-8') + proc.stderr.setEncoding('utf-8') +}) + +test('build simple addon in path with non-ascii characters', function (t) { + t.plan(1) + + if (!checkCharmapValid()) { + return t.skip('python console app can\'t encode non-ascii character.') + } + + var testDirNames = { + 'cp936': '文件夹', + 'cp1252': 'Latīna', + 'cp932': 'フォルダ' + } + // Select non-ascii characters by current encoding + var testDirName = testDirNames[getEncoding()] + // If encoding is UTF-8 or other then no need to test + if (!testDirName) { + return t.skip('no need to test') + } + + t.plan(3) + + var data, configPath = path.join(addonPath, 'build', 'config.gypi') + try { + data = fs.readFileSync(configPath, 'utf8') + } catch (err) { + t.error(err) + return + } + var config = JSON.parse(data.replace(/\#.+\n/, '')) + var nodeDir = config.variables.nodedir + var testNodeDir = path.join(addonPath, testDirName) + // Create symbol link to path with non-ascii characters + try { + fs.symlinkSync(nodeDir, testNodeDir, 'dir') + } catch (err) { + switch (err.code) { + case 'EEXIST': break + case 'EPERM': + t.error(err, 'Please try to running console as an administrator') + return + default: + t.error(err) + return + } + } + + var cmd = [nodeGyp, 'rebuild', '-C', addonPath, + '--loglevel=verbose', '-nodedir=' + testNodeDir] + var proc = execFile(process.execPath, cmd, function (err, stdout, stderr) { + try { + fs.unlink(testNodeDir) + } catch (err) { + t.error(err) + } + + var logLines = stderr.toString().trim().split(/\r?\n/) + var lastLine = logLines[logLines.length-1] + t.strictEqual(err, null) + t.strictEqual(lastLine, 'gyp info ok', 'should end in ok') + t.strictEqual(runHello().trim(), 'world') + }) + proc.stdout.setEncoding('utf-8') + proc.stderr.setEncoding('utf-8') +}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-configure-python.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-configure-python.js new file mode 100644 index 0000000000000..f235bdbba1c9f --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-configure-python.js @@ -0,0 +1,74 @@ +'use strict' + +var test = require('tape') +var path = require('path') +var gyp = require('../lib/node-gyp') +var requireInject = require('require-inject') +var configure = requireInject('../lib/configure', { + 'graceful-fs': { + 'openSync': function (file, mode) { return 0; }, + 'closeSync': function (fd) { }, + 'writeFile': function (file, data, cb) { cb() }, + 'stat': function (file, cb) { cb(null, {}) } + } +}) + +var EXPECTED_PYPATH = path.join(__dirname, '..', 'gyp', 'pylib') +var SEPARATOR = process.platform == 'win32' ? ';' : ':' +var SPAWN_RESULT = { on: function () { } } + +test('configure PYTHONPATH with no existing env', function (t) { + t.plan(1) + + delete process.env.PYTHONPATH + + var prog = gyp() + prog.parseArgv([]) + prog.spawn = function () { + t.equal(process.env.PYTHONPATH, EXPECTED_PYPATH) + return SPAWN_RESULT + } + configure(prog, [], t.fail) +}) + +test('configure PYTHONPATH with existing env of one dir', function (t) { + t.plan(2) + + var existingPath = path.join('a', 'b') + process.env.PYTHONPATH = existingPath + + var prog = gyp() + prog.parseArgv([]) + prog.spawn = function () { + + t.equal(process.env.PYTHONPATH, [EXPECTED_PYPATH, existingPath].join(SEPARATOR)) + + var dirs = process.env.PYTHONPATH.split(SEPARATOR) + t.deepEqual(dirs, [EXPECTED_PYPATH, existingPath]) + + return SPAWN_RESULT + } + configure(prog, [], t.fail) +}) + +test('configure PYTHONPATH with existing env of multiple dirs', function (t) { + t.plan(2) + + var pythonDir1 = path.join('a', 'b') + var pythonDir2 = path.join('b', 'c') + var existingPath = [pythonDir1, pythonDir2].join(SEPARATOR) + process.env.PYTHONPATH = existingPath + + var prog = gyp() + prog.parseArgv([]) + prog.spawn = function () { + + t.equal(process.env.PYTHONPATH, [EXPECTED_PYPATH, existingPath].join(SEPARATOR)) + + var dirs = process.env.PYTHONPATH.split(SEPARATOR) + t.deepEqual(dirs, [EXPECTED_PYPATH, pythonDir1, pythonDir2]) + + return SPAWN_RESULT + } + configure(prog, [], t.fail) +}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-download.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-download.js new file mode 100644 index 0000000000000..6e6f64f058c2e --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-download.js @@ -0,0 +1,102 @@ +'use strict' + +var fs = require('fs') +var http = require('http') +var https = require('https') +var test = require('tape') +var install = require('../lib/install') + +test('download over http', function (t) { + t.plan(2) + + var server = http.createServer(function (req, res) { + t.strictEqual(req.headers['user-agent'], + 'node-gyp v42 (node ' + process.version + ')') + res.end('ok') + server.close() + }) + + var host = '127.0.0.1' + server.listen(0, host, function () { + var port = this.address().port + var gyp = { + opts: {}, + version: '42', + } + var url = 'http://' + host + ':' + port + var req = install.test.download(gyp, {}, url) + req.on('response', function (res) { + var body = '' + res.setEncoding('utf8') + res.on('data', function(data) { + body += data + }) + res.on('end', function() { + t.strictEqual(body, 'ok') + }) + }) + }) +}) + +test('download over https with custom ca', function (t) { + t.plan(3) + + var cert = fs.readFileSync(__dirname + '/fixtures/server.crt', 'utf8') + var key = fs.readFileSync(__dirname + '/fixtures/server.key', 'utf8') + + var cafile = __dirname + '/fixtures/ca.crt' + var ca = install.test.readCAFile(cafile) + t.strictEqual(ca.length, 1) + + var options = { ca: ca, cert: cert, key: key } + var server = https.createServer(options, function (req, res) { + t.strictEqual(req.headers['user-agent'], + 'node-gyp v42 (node ' + process.version + ')') + res.end('ok') + server.close() + }) + + server.on('clientError', function (err) { + throw err + }) + + var host = '127.0.0.1' + server.listen(8000, host, function () { + var port = this.address().port + var gyp = { + opts: { cafile: cafile }, + version: '42', + } + var url = 'https://' + host + ':' + port + var req = install.test.download(gyp, {}, url) + req.on('response', function (res) { + var body = '' + res.setEncoding('utf8') + res.on('data', function(data) { + body += data + }) + res.on('end', function() { + t.strictEqual(body, 'ok') + }) + }) + }) +}) + +test('download with missing cafile', function (t) { + t.plan(1) + var gyp = { + opts: { cafile: 'no.such.file' }, + } + try { + install.test.download(gyp, {}, 'http://bad/') + } catch (e) { + t.ok(/no.such.file/.test(e.message)) + } +}) + +test('check certificate splitting', function (t) { + var cas = install.test.readCAFile(__dirname + '/fixtures/ca-bundle.crt') + t.plan(2) + t.strictEqual(cas.length, 2) + t.notStrictEqual(cas[0], cas[1]) +}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-accessible-sync.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-accessible-sync.js new file mode 100644 index 0000000000000..d336243dd0d7b --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-accessible-sync.js @@ -0,0 +1,86 @@ +'use strict' + +var test = require('tape') +var path = require('path') +var requireInject = require('require-inject') +var configure = requireInject('../lib/configure', { + 'graceful-fs': { + 'closeSync': function (fd) { return undefined }, + 'openSync': function (path) { + if (readableFiles.some(function (f) { return f === path} )) { + return 0 + } else { + var error = new Error('ENOENT - not found') + throw error + } + } + } +}) + +var dir = path.sep + 'testdir' +var readableFile = 'readable_file' +var anotherReadableFile = 'another_readable_file' +var readableFileInDir = 'somedir' + path.sep + readableFile +var readableFiles = [ + path.resolve(dir, readableFile), + path.resolve(dir, anotherReadableFile), + path.resolve(dir, readableFileInDir) +] + +test('find accessible - empty array', function (t) { + t.plan(1) + + var candidates = [] + var found = configure.test.findAccessibleSync('test', dir, candidates) + t.strictEqual(found, undefined) +}) + +test('find accessible - single item array, readable', function (t) { + t.plan(1) + + var candidates = [ readableFile ] + var found = configure.test.findAccessibleSync('test', dir, candidates) + t.strictEqual(found, path.resolve(dir, readableFile)) +}) + +test('find accessible - single item array, readable in subdir', function (t) { + t.plan(1) + + var candidates = [ readableFileInDir ] + var found = configure.test.findAccessibleSync('test', dir, candidates) + t.strictEqual(found, path.resolve(dir, readableFileInDir)) +}) + +test('find accessible - single item array, unreadable', function (t) { + t.plan(1) + + var candidates = [ 'unreadable_file' ] + var found = configure.test.findAccessibleSync('test', dir, candidates) + t.strictEqual(found, undefined) +}) + + +test('find accessible - multi item array, no matches', function (t) { + t.plan(1) + + var candidates = [ 'non_existent_file', 'unreadable_file' ] + var found = configure.test.findAccessibleSync('test', dir, candidates) + t.strictEqual(found, undefined) +}) + + +test('find accessible - multi item array, single match', function (t) { + t.plan(1) + + var candidates = [ 'non_existent_file', readableFile ] + var found = configure.test.findAccessibleSync('test', dir, candidates) + t.strictEqual(found, path.resolve(dir, readableFile)) +}) + +test('find accessible - multi item array, return first match', function (t) { + t.plan(1) + + var candidates = [ 'non_existent_file', anotherReadableFile, readableFile ] + var found = configure.test.findAccessibleSync('test', dir, candidates) + t.strictEqual(found, path.resolve(dir, anotherReadableFile)) +}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-node-directory.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-node-directory.js new file mode 100644 index 0000000000000..46659d0cfe8fa --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-node-directory.js @@ -0,0 +1,115 @@ +var test = require('tape') +var path = require('path') +var findNodeDirectory = require('../lib/find-node-directory') + +var platforms = ['darwin', 'freebsd', 'linux', 'sunos', 'win32', 'aix'] + +// we should find the directory based on the directory +// the script is running in and it should match the layout +// in a build tree where npm is installed in +// .... /deps/npm +test('test find-node-directory - node install', function (t) { + t.plan(platforms.length) + for (var next = 0; next < platforms.length; next++) { + var processObj = {execPath: '/x/y/bin/node', platform: platforms[next]} + t.equal( + findNodeDirectory('/x/deps/npm/node_modules/node-gyp/lib', processObj), + path.join('/x')) + } +}) + +// we should find the directory based on the directory +// the script is running in and it should match the layout +// in an installed tree where npm is installed in +// .... /lib/node_modules/npm or .../node_modules/npm +// depending on the patform +test('test find-node-directory - node build', function (t) { + t.plan(platforms.length) + for (var next = 0; next < platforms.length; next++) { + var processObj = {execPath: '/x/y/bin/node', platform: platforms[next]} + if (platforms[next] === 'win32') { + t.equal( + findNodeDirectory('/y/node_modules/npm/node_modules/node-gyp/lib', + processObj), path.join('/y')) + } else { + t.equal( + findNodeDirectory('/y/lib/node_modules/npm/node_modules/node-gyp/lib', + processObj), path.join('/y')) + } + } +}) + +// we should find the directory based on the execPath +// for node and match because it was in the bin directory +test('test find-node-directory - node in bin directory', function (t) { + t.plan(platforms.length) + for (var next = 0; next < platforms.length; next++) { + var processObj = {execPath: '/x/y/bin/node', platform: platforms[next]} + t.equal( + findNodeDirectory('/nothere/npm/node_modules/node-gyp/lib', processObj), + path.join('/x/y')) + } +}) + +// we should find the directory based on the execPath +// for node and match because it was in the Release directory +test('test find-node-directory - node in build release dir', function (t) { + t.plan(platforms.length) + for (var next = 0; next < platforms.length; next++) { + var processObj + if (platforms[next] === 'win32') { + processObj = {execPath: '/x/y/Release/node', platform: platforms[next]} + } else { + processObj = {execPath: '/x/y/out/Release/node', + platform: platforms[next]} + } + + t.equal( + findNodeDirectory('/nothere/npm/node_modules/node-gyp/lib', processObj), + path.join('/x/y')) + } +}) + +// we should find the directory based on the execPath +// for node and match because it was in the Debug directory +test('test find-node-directory - node in Debug release dir', function (t) { + t.plan(platforms.length) + for (var next = 0; next < platforms.length; next++) { + var processObj + if (platforms[next] === 'win32') { + processObj = {execPath: '/a/b/Debug/node', platform: platforms[next]} + } else { + processObj = {execPath: '/a/b/out/Debug/node', platform: platforms[next]} + } + + t.equal( + findNodeDirectory('/nothere/npm/node_modules/node-gyp/lib', processObj), + path.join('/a/b')) + } +}) + +// we should not find it as it will not match based on the execPath nor +// the directory from which the script is running +test('test find-node-directory - not found', function (t) { + t.plan(platforms.length) + for (var next = 0; next < platforms.length; next++) { + var processObj = {execPath: '/x/y/z/y', platform:next} + t.equal(findNodeDirectory('/a/b/c/d', processObj), '') + } +}) + +// we should find the directory based on the directory +// the script is running in and it should match the layout +// in a build tree where npm is installed in +// .... /deps/npm +// same test as above but make sure additional directory entries +// don't cause an issue +test('test find-node-directory - node install', function (t) { + t.plan(platforms.length) + for (var next = 0; next < platforms.length; next++) { + var processObj = {execPath: '/x/y/bin/node', platform: platforms[next]} + t.equal( + findNodeDirectory('/x/y/z/a/b/c/deps/npm/node_modules/node-gyp/lib', + processObj), path.join('/x/y/z/a/b/c')) + } +}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-python.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-python.js new file mode 100644 index 0000000000000..570eb180de7c7 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-python.js @@ -0,0 +1,339 @@ +'use strict' + +var test = require('tape') +var path = require('path') +var configure = require('../lib/configure') +var execFile = require('child_process').execFile +var PythonFinder = configure.test.PythonFinder + +test('find python', function (t) { + t.plan(4) + + configure.test.findPython('python', function (err, found) { + t.strictEqual(err, null) + var proc = execFile(found, ['-V'], function (err, stdout, stderr) { + t.strictEqual(err, null) + t.strictEqual(stdout, '') + t.ok(/Python 2/.test(stderr)) + }) + proc.stdout.setEncoding('utf-8') + proc.stderr.setEncoding('utf-8') + }) +}) + +function poison(object, property) { + function fail() { + throw new Error('Property ' + property + ' should not have been accessed.') + } + var descriptor = { + configurable: true, + enumerable: false, + writable: true, + getter: fail, + setter: fail, + } + Object.defineProperty(object, property, descriptor) +} + +// Work around a v0.10.x CI issue where path.resolve() on UNIX systems prefixes +// Windows paths with the current working directory. v0.12 and up are free of +// this issue because they use path.win32.resolve() which does the right thing. +var resolve = path.win32 && path.win32.resolve || function() { + function rstrip(s) { return s.replace(/\\+$/, '') } + return [].slice.call(arguments).map(rstrip).join('\\') +} + +function TestPythonFinder() { PythonFinder.apply(this, arguments) } +TestPythonFinder.prototype = Object.create(PythonFinder.prototype) +poison(TestPythonFinder.prototype, 'env') +poison(TestPythonFinder.prototype, 'execFile') +poison(TestPythonFinder.prototype, 'resolve') +poison(TestPythonFinder.prototype, 'stat') +poison(TestPythonFinder.prototype, 'which') +poison(TestPythonFinder.prototype, 'win') + +test('find python - python', function (t) { + t.plan(5) + + var f = new TestPythonFinder('python', done) + f.which = function(program, cb) { + t.strictEqual(program, 'python') + cb(null, program) + } + f.execFile = function(program, args, opts, cb) { + t.strictEqual(program, 'python') + t.ok(/import sys/.test(args[1])) + cb(null, '2.7.0') + } + f.checkPython() + + function done(err, python) { + t.strictEqual(err, null) + t.strictEqual(python, 'python') + } +}) + +test('find python - python too old', function (t) { + t.plan(4) + + var f = new TestPythonFinder('python', done) + f.which = function(program, cb) { + t.strictEqual(program, 'python') + cb(null, program) + } + f.execFile = function(program, args, opts, cb) { + t.strictEqual(program, 'python') + t.ok(/import sys/.test(args[1])) + cb(null, '2.3.4') + } + f.checkPython() + + function done(err, python) { + t.ok(/is not supported by gyp/.test(err)) + } +}) + +test('find python - python too new', function (t) { + t.plan(4) + + var f = new TestPythonFinder('python', done) + f.which = function(program, cb) { + t.strictEqual(program, 'python') + cb(null, program) + } + f.execFile = function(program, args, opts, cb) { + t.strictEqual(program, 'python') + t.ok(/import sys/.test(args[1])) + cb(null, '3.0.0') + } + f.checkPython() + + function done(err, python) { + t.ok(/is not supported by gyp/.test(err)) + } +}) + +test('find python - no python', function (t) { + t.plan(2) + + var f = new TestPythonFinder('python', done) + f.which = function(program, cb) { + t.strictEqual(program, 'python') + cb(new Error('not found')) + } + f.checkPython() + + function done(err, python) { + t.ok(/Can't find Python executable/.test(err)) + } +}) + +test('find python - no python2', function (t) { + t.plan(6) + + var f = new TestPythonFinder('python2', done) + f.which = function(program, cb) { + f.which = function(program, cb) { + t.strictEqual(program, 'python') + cb(null, program) + } + t.strictEqual(program, 'python2') + cb(new Error('not found')) + } + f.execFile = function(program, args, opts, cb) { + t.strictEqual(program, 'python') + t.ok(/import sys/.test(args[1])) + cb(null, '2.7.0') + } + f.checkPython() + + function done(err, python) { + t.strictEqual(err, null) + t.strictEqual(python, 'python') + } +}) + +test('find python - no python2, no python, unix', function (t) { + t.plan(3) + + var f = new TestPythonFinder('python2', done) + poison(f, 'checkPythonLauncher') + f.win = false + + f.which = function(program, cb) { + f.which = function(program, cb) { + t.strictEqual(program, 'python') + cb(new Error('not found')) + } + t.strictEqual(program, 'python2') + cb(new Error('not found')) + } + f.checkPython() + + function done(err, python) { + t.ok(/Can't find Python executable/.test(err)) + } +}) + +test('find python - no python, use python launcher', function (t) { + t.plan(8) + + var f = new TestPythonFinder('python', done) + f.env = {} + f.win = true + + f.which = function(program, cb) { + t.strictEqual(program, 'python') + cb(new Error('not found')) + } + f.execFile = function(program, args, opts, cb) { + f.execFile = function(program, args, opts, cb) { + t.strictEqual(program, 'Z:\\snake.exe') + t.ok(/import sys/.test(args[1])) + cb(null, '2.7.0') + } + t.strictEqual(program, 'py.exe') + t.notEqual(args.indexOf('-2'), -1) + t.notEqual(args.indexOf('-c'), -1) + cb(null, 'Z:\\snake.exe') + } + f.checkPython() + + function done(err, python) { + t.strictEqual(err, null) + t.strictEqual(python, 'Z:\\snake.exe') + } +}) + +test('find python - python 3, use python launcher', function (t) { + t.plan(10) + + var f = new TestPythonFinder('python', done) + f.env = {} + f.win = true + + f.which = function(program, cb) { + t.strictEqual(program, 'python') + cb(null, program) + } + f.execFile = function(program, args, opts, cb) { + f.execFile = function(program, args, opts, cb) { + f.execFile = function(program, args, opts, cb) { + t.strictEqual(program, 'Z:\\snake.exe') + t.ok(/import sys/.test(args[1])) + cb(null, '2.7.0') + } + t.strictEqual(program, 'py.exe') + t.notEqual(args.indexOf('-2'), -1) + t.notEqual(args.indexOf('-c'), -1) + cb(null, 'Z:\\snake.exe') + } + t.strictEqual(program, 'python') + t.ok(/import sys/.test(args[1])) + cb(null, '3.0.0') + } + f.checkPython() + + function done(err, python) { + t.strictEqual(err, null) + t.strictEqual(python, 'Z:\\snake.exe') + } +}) + +test('find python - python 3, use python launcher, python 2 too old', + function (t) { + t.plan(9) + + var f = new TestPythonFinder('python', done) + f.checkedPythonLauncher = false + f.env = {} + f.win = true + + f.which = function(program, cb) { + t.strictEqual(program, 'python') + cb(null, program) + } + f.execFile = function(program, args, opts, cb) { + f.execFile = function(program, args, opts, cb) { + f.execFile = function(program, args, opts, cb) { + t.strictEqual(program, 'Z:\\snake.exe') + t.ok(/import sys/.test(args[1])) + cb(null, '2.3.4') + } + t.strictEqual(program, 'py.exe') + t.notEqual(args.indexOf('-2'), -1) + t.notEqual(args.indexOf('-c'), -1) + cb(null, 'Z:\\snake.exe') + } + t.strictEqual(program, 'python') + t.ok(/import sys/.test(args[1])) + cb(null, '3.0.0') + } + f.checkPython() + + function done(err, python) { + t.ok(/is not supported by gyp/.test(err)) + } +}) + +test('find python - no python, no python launcher, good guess', function (t) { + t.plan(6) + + var re = /C:[\\\/]Python27[\\\/]python[.]exe/ + var f = new TestPythonFinder('python', done) + f.env = {} + f.win = true + + f.which = function(program, cb) { + t.strictEqual(program, 'python') + cb(new Error('not found')) + } + f.execFile = function(program, args, opts, cb) { + f.execFile = function(program, args, opts, cb) { + t.ok(re.test(program)) + t.ok(/import sys/.test(args[1])) + cb(null, '2.7.0') + } + t.strictEqual(program, 'py.exe') + cb(new Error('not found')) + } + f.resolve = resolve + f.stat = function(path, cb) { + t.ok(re.test(path)) + cb(null, {}) + } + f.checkPython() + + function done(err, python) { + t.ok(re.test(python)) + } +}) + +test('find python - no python, no python launcher, bad guess', function (t) { + t.plan(4) + + var f = new TestPythonFinder('python', done) + f.env = { SystemDrive: 'Z:\\' } + f.win = true + + f.which = function(program, cb) { + t.strictEqual(program, 'python') + cb(new Error('not found')) + } + f.execFile = function(program, args, opts, cb) { + t.strictEqual(program, 'py.exe') + cb(new Error('not found')) + } + f.resolve = resolve + f.stat = function(path, cb) { + t.ok(/Z:[\\\/]Python27[\\\/]python.exe/.test(path)) + var err = new Error('not found') + err.code = 'ENOENT' + cb(err) + } + f.checkPython() + + function done(err, python) { + t.ok(/Can't find Python executable/.test(err)) + } +}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-install.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-install.js new file mode 100644 index 0000000000000..f647326a7fc66 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-install.js @@ -0,0 +1,37 @@ +'use strict' + +var test = require('tape') +var install = require('../lib/install').test.install + +test('EACCES retry once', function (t) { + t.plan(3) + + var fs = {} + fs.stat = function (path, cb) { + var err = new Error() + err.code = 'EACCES' + cb(err) + t.ok(true); + } + + + var gyp = {} + gyp.devDir = __dirname + gyp.opts = {} + gyp.opts.ensure = true + gyp.commands = {} + gyp.commands.install = function (argv, cb) { + install(fs, gyp, argv, cb) + } + gyp.commands.remove = function (argv, cb) { + cb() + } + + gyp.commands.install([], function (err) { + t.ok(true) + if (/"pre" versions of node cannot be installed/.test(err.message)) { + t.ok(true) + t.ok(true) + } + }) +}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-options.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-options.js new file mode 100644 index 0000000000000..d097f81be62c8 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-options.js @@ -0,0 +1,25 @@ +'use strict'; + +var test = require('tape') +var gyp = require('../lib/node-gyp') + +test('options in environment', function (t) { + t.plan(1) + + // `npm test` dumps a ton of npm_config_* variables in the environment. + Object.keys(process.env) + .filter(function(key) { return /^npm_config_/.test(key) }) + .forEach(function(key) { delete process.env[key] }) + + // Zero-length keys should get filtered out. + process.env.npm_config_ = '42' + // Other keys should get added. + process.env.npm_config_x = '42' + // Except loglevel. + process.env.npm_config_loglevel = 'debug' + + var g = gyp(); + g.parseArgv(['rebuild']) // Also sets opts.argv. + + t.deepEqual(Object.keys(g.opts).sort(), ['argv', 'x']) +}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-process-release.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-process-release.js new file mode 100644 index 0000000000000..48411ae0a7d5a --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-process-release.js @@ -0,0 +1,637 @@ +var test = require('tape') +var processRelease = require('../lib/process-release') + +test('test process release - process.version = 0.8.20', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v0.8.20', null) + + t.equal(release.semver.version, '0.8.20') + delete release.semver + + t.deepEqual(release, { + version: '0.8.20', + name: 'node', + baseUrl: 'https://nodejs.org/dist/v0.8.20/', + tarballUrl: 'https://nodejs.org/dist/v0.8.20/node-v0.8.20.tar.gz', + shasumsUrl: 'https://nodejs.org/dist/v0.8.20/SHASUMS256.txt', + versionDir: '0.8.20', + libUrl32: 'https://nodejs.org/dist/v0.8.20/node.lib', + libUrl64: 'https://nodejs.org/dist/v0.8.20/x64/node.lib', + libPath32: 'node.lib', + libPath64: 'x64/node.lib' + }) +}) + +test('test process release - process.version = 0.10.21', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v0.10.21', null) + + t.equal(release.semver.version, '0.10.21') + delete release.semver + + t.deepEqual(release, { + version: '0.10.21', + name: 'node', + baseUrl: 'https://nodejs.org/dist/v0.10.21/', + tarballUrl: 'https://nodejs.org/dist/v0.10.21/node-v0.10.21.tar.gz', + shasumsUrl: 'https://nodejs.org/dist/v0.10.21/SHASUMS256.txt', + versionDir: '0.10.21', + libUrl32: 'https://nodejs.org/dist/v0.10.21/node.lib', + libUrl64: 'https://nodejs.org/dist/v0.10.21/x64/node.lib', + libPath32: 'node.lib', + libPath64: 'x64/node.lib' + }) +}) + +// prior to -headers.tar.gz +test('test process release - process.version = 0.12.9', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v0.12.9', null) + + t.equal(release.semver.version, '0.12.9') + delete release.semver + + t.deepEqual(release, { + version: '0.12.9', + name: 'node', + baseUrl: 'https://nodejs.org/dist/v0.12.9/', + tarballUrl: 'https://nodejs.org/dist/v0.12.9/node-v0.12.9.tar.gz', + shasumsUrl: 'https://nodejs.org/dist/v0.12.9/SHASUMS256.txt', + versionDir: '0.12.9', + libUrl32: 'https://nodejs.org/dist/v0.12.9/node.lib', + libUrl64: 'https://nodejs.org/dist/v0.12.9/x64/node.lib', + libPath32: 'node.lib', + libPath64: 'x64/node.lib' + }) +}) + +// prior to -headers.tar.gz +test('test process release - process.version = 0.10.41', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v0.10.41', null) + + t.equal(release.semver.version, '0.10.41') + delete release.semver + + t.deepEqual(release, { + version: '0.10.41', + name: 'node', + baseUrl: 'https://nodejs.org/dist/v0.10.41/', + tarballUrl: 'https://nodejs.org/dist/v0.10.41/node-v0.10.41.tar.gz', + shasumsUrl: 'https://nodejs.org/dist/v0.10.41/SHASUMS256.txt', + versionDir: '0.10.41', + libUrl32: 'https://nodejs.org/dist/v0.10.41/node.lib', + libUrl64: 'https://nodejs.org/dist/v0.10.41/x64/node.lib', + libPath32: 'node.lib', + libPath64: 'x64/node.lib' + }) +}) + +// has -headers.tar.gz +test('test process release - process.release ~ node@0.10.42', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v0.10.42', null) + + t.equal(release.semver.version, '0.10.42') + delete release.semver + + t.deepEqual(release, { + version: '0.10.42', + name: 'node', + baseUrl: 'https://nodejs.org/dist/v0.10.42/', + tarballUrl: 'https://nodejs.org/dist/v0.10.42/node-v0.10.42-headers.tar.gz', + shasumsUrl: 'https://nodejs.org/dist/v0.10.42/SHASUMS256.txt', + versionDir: '0.10.42', + libUrl32: 'https://nodejs.org/dist/v0.10.42/node.lib', + libUrl64: 'https://nodejs.org/dist/v0.10.42/x64/node.lib', + libPath32: 'node.lib', + libPath64: 'x64/node.lib' + }) +}) + +// has -headers.tar.gz +test('test process release - process.release ~ node@0.12.10', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v0.12.10', null) + + t.equal(release.semver.version, '0.12.10') + delete release.semver + + t.deepEqual(release, { + version: '0.12.10', + name: 'node', + baseUrl: 'https://nodejs.org/dist/v0.12.10/', + tarballUrl: 'https://nodejs.org/dist/v0.12.10/node-v0.12.10-headers.tar.gz', + shasumsUrl: 'https://nodejs.org/dist/v0.12.10/SHASUMS256.txt', + versionDir: '0.12.10', + libUrl32: 'https://nodejs.org/dist/v0.12.10/node.lib', + libUrl64: 'https://nodejs.org/dist/v0.12.10/x64/node.lib', + libPath32: 'node.lib', + libPath64: 'x64/node.lib' + }) +}) + +test('test process release - process.release ~ node@4.1.23', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v4.1.23', { + name: 'node', + headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz' + }) + + t.equal(release.semver.version, '4.1.23') + delete release.semver + + t.deepEqual(release, { + version: '4.1.23', + name: 'node', + baseUrl: 'https://nodejs.org/dist/v4.1.23/', + tarballUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz', + shasumsUrl: 'https://nodejs.org/dist/v4.1.23/SHASUMS256.txt', + versionDir: '4.1.23', + libUrl32: 'https://nodejs.org/dist/v4.1.23/win-x86/node.lib', + libUrl64: 'https://nodejs.org/dist/v4.1.23/win-x64/node.lib', + libPath32: 'win-x86/node.lib', + libPath64: 'win-x64/node.lib' + }) +}) + +test('test process release - process.release ~ node@4.1.23 / corp build', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v4.1.23', { + name: 'node', + headersUrl: 'https://some.custom.location/node-v4.1.23-headers.tar.gz' + }) + + t.equal(release.semver.version, '4.1.23') + delete release.semver + + t.deepEqual(release, { + version: '4.1.23', + name: 'node', + baseUrl: 'https://some.custom.location/', + tarballUrl: 'https://some.custom.location/node-v4.1.23-headers.tar.gz', + shasumsUrl: 'https://some.custom.location/SHASUMS256.txt', + versionDir: '4.1.23', + libUrl32: 'https://some.custom.location/win-x86/node.lib', + libUrl64: 'https://some.custom.location/win-x64/node.lib', + libPath32: 'win-x86/node.lib', + libPath64: 'win-x64/node.lib' + }) +}) + +test('test process release - process.version = 1.8.4', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v1.8.4', null) + + t.equal(release.semver.version, '1.8.4') + delete release.semver + + t.deepEqual(release, { + version: '1.8.4', + name: 'iojs', + baseUrl: 'https://iojs.org/download/release/v1.8.4/', + tarballUrl: 'https://iojs.org/download/release/v1.8.4/iojs-v1.8.4.tar.gz', + shasumsUrl: 'https://iojs.org/download/release/v1.8.4/SHASUMS256.txt', + versionDir: 'iojs-1.8.4', + libUrl32: 'https://iojs.org/download/release/v1.8.4/win-x86/iojs.lib', + libUrl64: 'https://iojs.org/download/release/v1.8.4/win-x64/iojs.lib', + libPath32: 'win-x86/iojs.lib', + libPath64: 'win-x64/iojs.lib' + }) +}) + +test('test process release - process.release ~ iojs@3.2.24', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v3.2.24', { + name: 'io.js', + headersUrl: 'https://iojs.org/download/release/v3.2.24/iojs-v3.2.24-headers.tar.gz' + }) + + t.equal(release.semver.version, '3.2.24') + delete release.semver + + t.deepEqual(release, { + version: '3.2.24', + name: 'iojs', + baseUrl: 'https://iojs.org/download/release/v3.2.24/', + tarballUrl: 'https://iojs.org/download/release/v3.2.24/iojs-v3.2.24-headers.tar.gz', + shasumsUrl: 'https://iojs.org/download/release/v3.2.24/SHASUMS256.txt', + versionDir: 'iojs-3.2.24', + libUrl32: 'https://iojs.org/download/release/v3.2.24/win-x86/iojs.lib', + libUrl64: 'https://iojs.org/download/release/v3.2.24/win-x64/iojs.lib', + libPath32: 'win-x86/iojs.lib', + libPath64: 'win-x64/iojs.lib' + }) +}) + +test('test process release - process.release ~ iojs@3.2.11 +libUrl32', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v3.2.11', { + name: 'io.js', + headersUrl: 'https://iojs.org/download/release/v3.2.11/iojs-v3.2.11-headers.tar.gz', + libUrl: 'https://iojs.org/download/release/v3.2.11/win-x86/iojs.lib' // custom + }) + + t.equal(release.semver.version, '3.2.11') + delete release.semver + + t.deepEqual(release, { + version: '3.2.11', + name: 'iojs', + baseUrl: 'https://iojs.org/download/release/v3.2.11/', + tarballUrl: 'https://iojs.org/download/release/v3.2.11/iojs-v3.2.11-headers.tar.gz', + shasumsUrl: 'https://iojs.org/download/release/v3.2.11/SHASUMS256.txt', + versionDir: 'iojs-3.2.11', + libUrl32: 'https://iojs.org/download/release/v3.2.11/win-x86/iojs.lib', + libUrl64: 'https://iojs.org/download/release/v3.2.11/win-x64/iojs.lib', + libPath32: 'win-x86/iojs.lib', + libPath64: 'win-x64/iojs.lib' + }) +}) + +test('test process release - process.release ~ iojs@3.2.101 +libUrl64', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v3.2.101', { + name: 'io.js', + headersUrl: 'https://iojs.org/download/release/v3.2.101/iojs-v3.2.101-headers.tar.gz', + libUrl: 'https://iojs.org/download/release/v3.2.101/win-x64/iojs.lib' // custom + }) + + t.equal(release.semver.version, '3.2.101') + delete release.semver + + t.deepEqual(release, { + version: '3.2.101', + name: 'iojs', + baseUrl: 'https://iojs.org/download/release/v3.2.101/', + tarballUrl: 'https://iojs.org/download/release/v3.2.101/iojs-v3.2.101-headers.tar.gz', + shasumsUrl: 'https://iojs.org/download/release/v3.2.101/SHASUMS256.txt', + versionDir: 'iojs-3.2.101', + libUrl32: 'https://iojs.org/download/release/v3.2.101/win-x86/iojs.lib', + libUrl64: 'https://iojs.org/download/release/v3.2.101/win-x64/iojs.lib', + libPath32: 'win-x86/iojs.lib', + libPath64: 'win-x64/iojs.lib' + }) +}) + +test('test process release - process.release ~ iojs@3.3.0 - borked win-ia32', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v3.2.101', { + name: 'io.js', + headersUrl: 'https://iojs.org/download/release/v3.2.101/iojs-v3.2.101-headers.tar.gz', + libUrl: 'https://iojs.org/download/release/v3.2.101/win-ia32/iojs.lib' // custom + }) + + t.equal(release.semver.version, '3.2.101') + delete release.semver + + t.deepEqual(release, { + version: '3.2.101', + name: 'iojs', + baseUrl: 'https://iojs.org/download/release/v3.2.101/', + tarballUrl: 'https://iojs.org/download/release/v3.2.101/iojs-v3.2.101-headers.tar.gz', + shasumsUrl: 'https://iojs.org/download/release/v3.2.101/SHASUMS256.txt', + versionDir: 'iojs-3.2.101', + libUrl32: 'https://iojs.org/download/release/v3.2.101/win-x86/iojs.lib', + libUrl64: 'https://iojs.org/download/release/v3.2.101/win-x64/iojs.lib', + libPath32: 'win-x86/iojs.lib', + libPath64: 'win-x64/iojs.lib' + }) +}) + +test('test process release - process.release ~ node@4.1.23 --target=0.10.40', function (t) { + t.plan(2) + + var release = processRelease([], { opts: { target: '0.10.40' } }, 'v4.1.23', { + name: 'node', + headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz' + }) + + t.equal(release.semver.version, '0.10.40') + delete release.semver + + t.deepEqual(release, { + version: '0.10.40', + name: 'node', + baseUrl: 'https://nodejs.org/dist/v0.10.40/', + tarballUrl: 'https://nodejs.org/dist/v0.10.40/node-v0.10.40.tar.gz', + shasumsUrl: 'https://nodejs.org/dist/v0.10.40/SHASUMS256.txt', + versionDir: '0.10.40', + libUrl32: 'https://nodejs.org/dist/v0.10.40/node.lib', + libUrl64: 'https://nodejs.org/dist/v0.10.40/x64/node.lib', + libPath32: 'node.lib', + libPath64: 'x64/node.lib' + }) +}) + +test('test process release - process.release ~ node@4.1.23 --target=1.8.4', function (t) { + t.plan(2) + + var release = processRelease([], { opts: { target: '1.8.4' } }, 'v4.1.23', { + name: 'node', + headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz' + }) + + t.equal(release.semver.version, '1.8.4') + delete release.semver + + t.deepEqual(release, { + version: '1.8.4', + name: 'iojs', + baseUrl: 'https://iojs.org/download/release/v1.8.4/', + tarballUrl: 'https://iojs.org/download/release/v1.8.4/iojs-v1.8.4.tar.gz', + shasumsUrl: 'https://iojs.org/download/release/v1.8.4/SHASUMS256.txt', + versionDir: 'iojs-1.8.4', + libUrl32: 'https://iojs.org/download/release/v1.8.4/win-x86/iojs.lib', + libUrl64: 'https://iojs.org/download/release/v1.8.4/win-x64/iojs.lib', + libPath32: 'win-x86/iojs.lib', + libPath64: 'win-x64/iojs.lib' + }) +}) + +test('test process release - process.release ~ node@4.1.23 --dist-url=https://foo.bar/baz', function (t) { + t.plan(2) + + var release = processRelease([], { opts: { 'dist-url': 'https://foo.bar/baz' } }, 'v4.1.23', { + name: 'node', + headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz' + }) + + t.equal(release.semver.version, '4.1.23') + delete release.semver + + t.deepEqual(release, { + version: '4.1.23', + name: 'node', + baseUrl: 'https://foo.bar/baz/v4.1.23/', + tarballUrl: 'https://foo.bar/baz/v4.1.23/node-v4.1.23-headers.tar.gz', + shasumsUrl: 'https://foo.bar/baz/v4.1.23/SHASUMS256.txt', + versionDir: '4.1.23', + libUrl32: 'https://foo.bar/baz/v4.1.23/win-x86/node.lib', + libUrl64: 'https://foo.bar/baz/v4.1.23/win-x64/node.lib', + libPath32: 'win-x86/node.lib', + libPath64: 'win-x64/node.lib' + }) +}) + +test('test process release - process.release ~ frankenstein@4.1.23', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v4.1.23', { + name: 'frankenstein', + headersUrl: 'https://frankensteinjs.org/dist/v4.1.23/frankenstein-v4.1.23-headers.tar.gz' + }) + + t.equal(release.semver.version, '4.1.23') + delete release.semver + + t.deepEqual(release, { + version: '4.1.23', + name: 'frankenstein', + baseUrl: 'https://frankensteinjs.org/dist/v4.1.23/', + tarballUrl: 'https://frankensteinjs.org/dist/v4.1.23/frankenstein-v4.1.23-headers.tar.gz', + shasumsUrl: 'https://frankensteinjs.org/dist/v4.1.23/SHASUMS256.txt', + versionDir: 'frankenstein-4.1.23', + libUrl32: 'https://frankensteinjs.org/dist/v4.1.23/win-x86/frankenstein.lib', + libUrl64: 'https://frankensteinjs.org/dist/v4.1.23/win-x64/frankenstein.lib', + libPath32: 'win-x86/frankenstein.lib', + libPath64: 'win-x64/frankenstein.lib' + }) +}) + + +test('test process release - process.release ~ frankenstein@4.1.23 --dist-url=http://foo.bar/baz/', function (t) { + t.plan(2) + + var release = processRelease([], { opts: { 'dist-url': 'http://foo.bar/baz/' } }, 'v4.1.23', { + name: 'frankenstein', + headersUrl: 'https://frankensteinjs.org/dist/v4.1.23/frankenstein-v4.1.23.tar.gz' + }) + + t.equal(release.semver.version, '4.1.23') + delete release.semver + + t.deepEqual(release, { + version: '4.1.23', + name: 'frankenstein', + baseUrl: 'http://foo.bar/baz/v4.1.23/', + tarballUrl: 'http://foo.bar/baz/v4.1.23/frankenstein-v4.1.23-headers.tar.gz', + shasumsUrl: 'http://foo.bar/baz/v4.1.23/SHASUMS256.txt', + versionDir: 'frankenstein-4.1.23', + libUrl32: 'http://foo.bar/baz/v4.1.23/win-x86/frankenstein.lib', + libUrl64: 'http://foo.bar/baz/v4.1.23/win-x64/frankenstein.lib', + libPath32: 'win-x86/frankenstein.lib', + libPath64: 'win-x64/frankenstein.lib' + }) +}) + +test('test process release - process.release ~ node@4.0.0-rc.4', function (t) { + t.plan(2) + + var release = processRelease([], { opts: {} }, 'v4.0.0-rc.4', { + name: 'node', + headersUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz' + }) + + t.equal(release.semver.version, '4.0.0-rc.4') + delete release.semver + + t.deepEqual(release, { + version: '4.0.0-rc.4', + name: 'node', + baseUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/', + tarballUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz', + shasumsUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/SHASUMS256.txt', + versionDir: '4.0.0-rc.4', + libUrl32: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x86/node.lib', + libUrl64: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x64/node.lib', + libPath32: 'win-x86/node.lib', + libPath64: 'win-x64/node.lib' + }) +}) + + +test('test process release - process.release ~ node@4.0.0-rc.4 passed as argv[0]', function (t) { + t.plan(2) + + // note the missing 'v' on the arg, it should normalise when checking + // whether we're on the default or not + var release = processRelease([ '4.0.0-rc.4' ], { opts: {} }, 'v4.0.0-rc.4', { + name: 'node', + headersUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz' + }) + + t.equal(release.semver.version, '4.0.0-rc.4') + delete release.semver + + t.deepEqual(release, { + version: '4.0.0-rc.4', + name: 'node', + baseUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/', + tarballUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz', + shasumsUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/SHASUMS256.txt', + versionDir: '4.0.0-rc.4', + libUrl32: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x86/node.lib', + libUrl64: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x64/node.lib', + libPath32: 'win-x86/node.lib', + libPath64: 'win-x64/node.lib' + }) +}) + + +test('test process release - process.release ~ node@4.0.0-rc.4 - bogus string passed as argv[0]', function (t) { + t.plan(2) + + // additional arguments can be passed in on the commandline that should be ignored if they + // are not specifying a valid version @ position 0 + var release = processRelease([ 'this is no version!' ], { opts: {} }, 'v4.0.0-rc.4', { + name: 'node', + headersUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz' + }) + + t.equal(release.semver.version, '4.0.0-rc.4') + delete release.semver + + t.deepEqual(release, { + version: '4.0.0-rc.4', + name: 'node', + baseUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/', + tarballUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz', + shasumsUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/SHASUMS256.txt', + versionDir: '4.0.0-rc.4', + libUrl32: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x86/node.lib', + libUrl64: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x64/node.lib', + libPath32: 'win-x86/node.lib', + libPath64: 'win-x64/node.lib' + }) +}) + +test('test process release - NODEJS_ORG_MIRROR', function (t) { + t.plan(2) + + process.env.NODEJS_ORG_MIRROR = 'http://foo.bar' + + var release = processRelease([], { opts: {} }, 'v4.1.23', { + name: 'node', + headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz' + }) + + t.equal(release.semver.version, '4.1.23') + delete release.semver + + t.deepEqual(release, { + version: '4.1.23', + name: 'node', + baseUrl: 'http://foo.bar/v4.1.23/', + tarballUrl: 'http://foo.bar/v4.1.23/node-v4.1.23-headers.tar.gz', + shasumsUrl: 'http://foo.bar/v4.1.23/SHASUMS256.txt', + versionDir: '4.1.23', + libUrl32: 'http://foo.bar/v4.1.23/win-x86/node.lib', + libUrl64: 'http://foo.bar/v4.1.23/win-x64/node.lib', + libPath32: 'win-x86/node.lib', + libPath64: 'win-x64/node.lib' + }) + + delete process.env.NODEJS_ORG_MIRROR +}) + +test('test process release - NVM_NODEJS_ORG_MIRROR', function (t) { + t.plan(2) + + process.env.NVM_NODEJS_ORG_MIRROR = 'http://foo.bar' + + var release = processRelease([], { opts: {} }, 'v4.1.23', { + name: 'node', + headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz' + }) + + t.equal(release.semver.version, '4.1.23') + delete release.semver + + t.deepEqual(release, { + version: '4.1.23', + name: 'node', + baseUrl: 'http://foo.bar/v4.1.23/', + tarballUrl: 'http://foo.bar/v4.1.23/node-v4.1.23-headers.tar.gz', + shasumsUrl: 'http://foo.bar/v4.1.23/SHASUMS256.txt', + versionDir: '4.1.23', + libUrl32: 'http://foo.bar/v4.1.23/win-x86/node.lib', + libUrl64: 'http://foo.bar/v4.1.23/win-x64/node.lib', + libPath32: 'win-x86/node.lib', + libPath64: 'win-x64/node.lib' + }) + + delete process.env.NVM_NODEJS_ORG_MIRROR +}) + +test('test process release - IOJS_ORG_MIRROR', function (t) { + t.plan(2) + + process.env.IOJS_ORG_MIRROR = 'http://foo.bar' + + var release = processRelease([], { opts: {} }, 'v3.2.24', { + name: 'io.js', + headersUrl: 'https://iojs.org/download/release/v3.2.24/iojs-v3.2.24-headers.tar.gz' + }) + + t.equal(release.semver.version, '3.2.24') + delete release.semver + + t.deepEqual(release, { + version: '3.2.24', + name: 'iojs', + baseUrl: 'http://foo.bar/v3.2.24/', + tarballUrl: 'http://foo.bar/v3.2.24/iojs-v3.2.24-headers.tar.gz', + shasumsUrl: 'http://foo.bar/v3.2.24/SHASUMS256.txt', + versionDir: 'iojs-3.2.24', + libUrl32: 'http://foo.bar/v3.2.24/win-x86/iojs.lib', + libUrl64: 'http://foo.bar/v3.2.24/win-x64/iojs.lib', + libPath32: 'win-x86/iojs.lib', + libPath64: 'win-x64/iojs.lib' + }) + + delete process.env.IOJS_ORG_MIRROR +}) + + +test('test process release - NVM_IOJS_ORG_MIRROR', function (t) { + t.plan(2) + + process.env.NVM_IOJS_ORG_MIRROR = 'http://foo.bar' + + var release = processRelease([], { opts: {} }, 'v3.2.24', { + name: 'io.js', + headersUrl: 'https://iojs.org/download/release/v3.2.24/iojs-v3.2.24-headers.tar.gz' + }) + + t.equal(release.semver.version, '3.2.24') + delete release.semver + + t.deepEqual(release, { + version: '3.2.24', + name: 'iojs', + baseUrl: 'http://foo.bar/v3.2.24/', + tarballUrl: 'http://foo.bar/v3.2.24/iojs-v3.2.24-headers.tar.gz', + shasumsUrl: 'http://foo.bar/v3.2.24/SHASUMS256.txt', + versionDir: 'iojs-3.2.24', + libUrl32: 'http://foo.bar/v3.2.24/win-x86/iojs.lib', + libUrl64: 'http://foo.bar/v3.2.24/win-x64/iojs.lib', + libPath32: 'win-x86/iojs.lib', + libPath64: 'win-x64/iojs.lib' + }) + + delete process.env.NVM_IOJS_ORG_MIRROR +}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/tools/gyp/pylib/gyp/generator/compile_commands_json.py b/node_modules/npm-lifecycle/node_modules/node-gyp/tools/gyp/pylib/gyp/generator/compile_commands_json.py new file mode 100644 index 0000000000000..575db63c4e194 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/node-gyp/tools/gyp/pylib/gyp/generator/compile_commands_json.py @@ -0,0 +1,115 @@ +# Copyright (c) 2016 Ben Noordhuis . All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import gyp.common +import gyp.xcode_emulation +import json +import os + +generator_additional_non_configuration_keys = [] +generator_additional_path_sections = [] +generator_extra_sources_for_rules = [] +generator_filelist_paths = None +generator_supports_multiple_toolsets = True +generator_wants_sorted_dependencies = False + +# Lifted from make.py. The actual values don't matter much. +generator_default_variables = { + 'CONFIGURATION_NAME': '$(BUILDTYPE)', + 'EXECUTABLE_PREFIX': '', + 'EXECUTABLE_SUFFIX': '', + 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/$(TARGET)/geni', + 'PRODUCT_DIR': '$(builddir)', + 'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s', + 'RULE_INPUT_EXT': '$(suffix $<)', + 'RULE_INPUT_NAME': '$(notdir $<)', + 'RULE_INPUT_PATH': '$(abspath $<)', + 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', + 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen', + 'SHARED_LIB_PREFIX': 'lib', + 'STATIC_LIB_PREFIX': 'lib', + 'STATIC_LIB_SUFFIX': '.a', +} + + +def IsMac(params): + return 'mac' == gyp.common.GetFlavor(params) + + +def CalculateVariables(default_variables, params): + default_variables.setdefault('OS', gyp.common.GetFlavor(params)) + + +def AddCommandsForTarget(cwd, target, params, per_config_commands): + output_dir = params['generator_flags']['output_dir'] + for configuration_name, configuration in target['configurations'].iteritems(): + builddir_name = os.path.join(output_dir, configuration_name) + + if IsMac(params): + xcode_settings = gyp.xcode_emulation.XcodeSettings(target) + cflags = xcode_settings.GetCflags(configuration_name) + cflags_c = xcode_settings.GetCflagsC(configuration_name) + cflags_cc = xcode_settings.GetCflagsCC(configuration_name) + else: + cflags = configuration.get('cflags', []) + cflags_c = configuration.get('cflags_c', []) + cflags_cc = configuration.get('cflags_cc', []) + + cflags_c = cflags + cflags_c + cflags_cc = cflags + cflags_cc + + defines = configuration.get('defines', []) + defines = ['-D' + s for s in defines] + + # TODO(bnoordhuis) Handle generated source files. + sources = target.get('sources', []) + sources = [s for s in sources if s.endswith('.c') or s.endswith('.cc')] + + def resolve(filename): + return os.path.abspath(os.path.join(cwd, filename)) + + # TODO(bnoordhuis) Handle generated header files. + include_dirs = configuration.get('include_dirs', []) + include_dirs = [s for s in include_dirs if not s.startswith('$(obj)')] + includes = ['-I' + resolve(s) for s in include_dirs] + + defines = gyp.common.EncodePOSIXShellList(defines) + includes = gyp.common.EncodePOSIXShellList(includes) + cflags_c = gyp.common.EncodePOSIXShellList(cflags_c) + cflags_cc = gyp.common.EncodePOSIXShellList(cflags_cc) + + commands = per_config_commands.setdefault(configuration_name, []) + for source in sources: + file = resolve(source) + isc = source.endswith('.c') + cc = 'cc' if isc else 'c++' + cflags = cflags_c if isc else cflags_cc + command = ' '.join((cc, defines, includes, cflags, + '-c', gyp.common.EncodePOSIXShellArgument(file))) + commands.append(dict(command=command, directory=output_dir, file=file)) + + +def GenerateOutput(target_list, target_dicts, data, params): + per_config_commands = {} + for qualified_target, target in target_dicts.iteritems(): + build_file, target_name, toolset = ( + gyp.common.ParseQualifiedTarget(qualified_target)) + if IsMac(params): + settings = data[build_file] + gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(settings, target) + cwd = os.path.dirname(build_file) + AddCommandsForTarget(cwd, target, params, per_config_commands) + + output_dir = params['generator_flags']['output_dir'] + for configuration_name, commands in per_config_commands.iteritems(): + filename = os.path.join(output_dir, + configuration_name, + 'compile_commands.json') + gyp.common.EnsureDirExists(filename) + fp = open(filename, 'w') + json.dump(commands, fp=fp, indent=0, check_circular=False) + + +def PerformBuild(data, configurations, params): + pass diff --git a/node_modules/npm-lifecycle/node_modules/nopt/.npmignore b/node_modules/npm-lifecycle/node_modules/nopt/.npmignore new file mode 100644 index 0000000000000..3c3629e647f5d --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/nopt/.npmignore @@ -0,0 +1 @@ +node_modules diff --git a/node_modules/npm-lifecycle/node_modules/nopt/.travis.yml b/node_modules/npm-lifecycle/node_modules/nopt/.travis.yml new file mode 100644 index 0000000000000..99f2bbf5068a8 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/nopt/.travis.yml @@ -0,0 +1,9 @@ +language: node_js +language: node_js +node_js: + - '0.8' + - '0.10' + - '0.12' + - 'iojs' +before_install: + - npm install -g npm@latest diff --git a/node_modules/npm-lifecycle/node_modules/nopt/LICENSE b/node_modules/npm-lifecycle/node_modules/nopt/LICENSE new file mode 100644 index 0000000000000..19129e315fe59 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/nopt/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +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/node_modules/npm-lifecycle/node_modules/nopt/README.md b/node_modules/npm-lifecycle/node_modules/nopt/README.md new file mode 100644 index 0000000000000..f21a4b31c5d48 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/nopt/README.md @@ -0,0 +1,211 @@ +If you want to write an option parser, and have it be good, there are +two ways to do it. The Right Way, and the Wrong Way. + +The Wrong Way is to sit down and write an option parser. We've all done +that. + +The Right Way is to write some complex configurable program with so many +options that you hit the limit of your frustration just trying to +manage them all, and defer it with duct-tape solutions until you see +exactly to the core of the problem, and finally snap and write an +awesome option parser. + +If you want to write an option parser, don't write an option parser. +Write a package manager, or a source control system, or a service +restarter, or an operating system. You probably won't end up with a +good one of those, but if you don't give up, and you are relentless and +diligent enough in your procrastination, you may just end up with a very +nice option parser. + +## USAGE + + // my-program.js + var nopt = require("nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + , "many1" : [String, Array] + , "many2" : [path] + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag"] + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + console.log(parsed) + +This would give you support for any of the following: + +```bash +$ node my-program.js --foo "blerp" --no-flag +{ "foo" : "blerp", "flag" : false } + +$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag +{ bar: 7, foo: "Mr. Hand", flag: true } + +$ node my-program.js --foo "blerp" -f -----p +{ foo: "blerp", flag: true, pick: true } + +$ node my-program.js -fp --foofoo +{ foo: "Mr. Foo", flag: true, pick: true } + +$ node my-program.js --foofoo -- -fp # -- stops the flag parsing. +{ foo: "Mr. Foo", argv: { remain: ["-fp"] } } + +$ node my-program.js --blatzk -fp # unknown opts are ok. +{ blatzk: true, flag: true, pick: true } + +$ node my-program.js --blatzk=1000 -fp # but you need to use = if they have a value +{ blatzk: 1000, flag: true, pick: true } + +$ node my-program.js --no-blatzk -fp # unless they start with "no-" +{ blatzk: false, flag: true, pick: true } + +$ node my-program.js --baz b/a/z # known paths are resolved. +{ baz: "/Users/isaacs/b/a/z" } + +# if Array is one of the types, then it can take many +# values, and will always be an array. The other types provided +# specify what types are allowed in the list. + +$ node my-program.js --many1 5 --many1 null --many1 foo +{ many1: ["5", "null", "foo"] } + +$ node my-program.js --many2 foo --many2 bar +{ many2: ["/path/to/foo", "path/to/bar"] } +``` + +Read the tests at the bottom of `lib/nopt.js` for more examples of +what this puppy can do. + +## Types + +The following types are supported, and defined on `nopt.typeDefs` + +* String: A normal string. No parsing is done. +* path: A file system path. Gets resolved against cwd if not absolute. +* url: A url. If it doesn't parse, it isn't accepted. +* Number: Must be numeric. +* Date: Must parse as a date. If it does, and `Date` is one of the options, + then it will return a Date object, not a string. +* Boolean: Must be either `true` or `false`. If an option is a boolean, + then it does not need a value, and its presence will imply `true` as + the value. To negate boolean flags, do `--no-whatever` or `--whatever + false` +* NaN: Means that the option is strictly not allowed. Any value will + fail. +* Stream: An object matching the "Stream" class in node. Valuable + for use when validating programmatically. (npm uses this to let you + supply any WriteStream on the `outfd` and `logfd` config options.) +* Array: If `Array` is specified as one of the types, then the value + will be parsed as a list of options. This means that multiple values + can be specified, and that the value will always be an array. + +If a type is an array of values not on this list, then those are +considered valid values. For instance, in the example above, the +`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`, +and any other value will be rejected. + +When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be +interpreted as their JavaScript equivalents. + +You can also mix types and values, or multiple types, in a list. For +instance `{ blah: [Number, null] }` would allow a value to be set to +either a Number or null. When types are ordered, this implies a +preference, and the first type that can be used to properly interpret +the value will be used. + +To define a new type, add it to `nopt.typeDefs`. Each item in that +hash is an object with a `type` member and a `validate` method. The +`type` member is an object that matches what goes in the type list. The +`validate` method is a function that gets called with `validate(data, +key, val)`. Validate methods should assign `data[key]` to the valid +value of `val` if it can be handled properly, or return boolean +`false` if it cannot. + +You can also call `nopt.clean(data, types, typeDefs)` to clean up a +config object and remove its invalid properties. + +## Error Handling + +By default, nopt outputs a warning to standard error when invalid values for +known options are found. You can change this behavior by assigning a method +to `nopt.invalidHandler`. This method will be called with +the offending `nopt.invalidHandler(key, val, types)`. + +If no `nopt.invalidHandler` is assigned, then it will console.error +its whining. If it is assigned to boolean `false` then the warning is +suppressed. + +## Abbreviations + +Yes, they are supported. If you define options like this: + +```javascript +{ "foolhardyelephants" : Boolean +, "pileofmonkeys" : Boolean } +``` + +Then this will work: + +```bash +node program.js --foolhar --pil +node program.js --no-f --pileofmon +# etc. +``` + +## Shorthands + +Shorthands are a hash of shorter option names to a snippet of args that +they expand to. + +If multiple one-character shorthands are all combined, and the +combination does not unambiguously match any other option or shorthand, +then they will be broken up into their constituent parts. For example: + +```json +{ "s" : ["--loglevel", "silent"] +, "g" : "--global" +, "f" : "--force" +, "p" : "--parseable" +, "l" : "--long" +} +``` + +```bash +npm ls -sgflp +# just like doing this: +npm ls --loglevel silent --global --force --long --parseable +``` + +## The Rest of the args + +The config object returned by nopt is given a special member called +`argv`, which is an object with the following fields: + +* `remain`: The remaining args after all the parsing has occurred. +* `original`: The args as they originally appeared. +* `cooked`: The args after flags and shorthands are expanded. + +## Slicing + +Node programs are called with more or less the exact argv as it appears +in C land, after the v8 and node-specific options have been plucked off. +As such, `argv[0]` is always `node` and `argv[1]` is always the +JavaScript program being run. + +That's usually not very useful to you. So they're sliced off by +default. If you want them, then you can pass in `0` as the last +argument, or any other number that you'd like to slice off the start of +the list. diff --git a/node_modules/npm-lifecycle/node_modules/nopt/bin/nopt.js b/node_modules/npm-lifecycle/node_modules/nopt/bin/nopt.js new file mode 100755 index 0000000000000..3232d4c570fdc --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/nopt/bin/nopt.js @@ -0,0 +1,54 @@ +#!/usr/bin/env node +var nopt = require("../lib/nopt") + , path = require("path") + , types = { num: Number + , bool: Boolean + , help: Boolean + , list: Array + , "num-list": [Number, Array] + , "str-list": [String, Array] + , "bool-list": [Boolean, Array] + , str: String + , clear: Boolean + , config: Boolean + , length: Number + , file: path + } + , shorthands = { s: [ "--str", "astring" ] + , b: [ "--bool" ] + , nb: [ "--no-bool" ] + , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] + , "?": ["--help"] + , h: ["--help"] + , H: ["--help"] + , n: [ "--num", "125" ] + , c: ["--config"] + , l: ["--length"] + , f: ["--file"] + } + , parsed = nopt( types + , shorthands + , process.argv + , 2 ) + +console.log("parsed", parsed) + +if (parsed.help) { + console.log("") + console.log("nopt cli tester") + console.log("") + console.log("types") + console.log(Object.keys(types).map(function M (t) { + var type = types[t] + if (Array.isArray(type)) { + return [t, type.map(function (type) { return type.name })] + } + return [t, type && type.name] + }).reduce(function (s, i) { + s[i[0]] = i[1] + return s + }, {})) + console.log("") + console.log("shorthands") + console.log(shorthands) +} diff --git a/node_modules/npm-lifecycle/node_modules/nopt/examples/my-program.js b/node_modules/npm-lifecycle/node_modules/nopt/examples/my-program.js new file mode 100755 index 0000000000000..142447e18e756 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/nopt/examples/my-program.js @@ -0,0 +1,30 @@ +#!/usr/bin/env node + +//process.env.DEBUG_NOPT = 1 + +// my-program.js +var nopt = require("../lib/nopt") + , Stream = require("stream").Stream + , path = require("path") + , knownOpts = { "foo" : [String, null] + , "bar" : [Stream, Number] + , "baz" : path + , "bloo" : [ "big", "medium", "small" ] + , "flag" : Boolean + , "pick" : Boolean + } + , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] + , "b7" : ["--bar", "7"] + , "m" : ["--bloo", "medium"] + , "p" : ["--pick"] + , "f" : ["--flag", "true"] + , "g" : ["--flag"] + , "s" : "--flag" + } + // everything is optional. + // knownOpts and shorthands default to {} + // arg list defaults to process.argv + // slice defaults to 2 + , parsed = nopt(knownOpts, shortHands, process.argv, 2) + +console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/node_modules/npm-lifecycle/node_modules/nopt/lib/nopt.js b/node_modules/npm-lifecycle/node_modules/nopt/lib/nopt.js new file mode 100644 index 0000000000000..97707e784243b --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/nopt/lib/nopt.js @@ -0,0 +1,415 @@ +// info about each config option. + +var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG + ? function () { console.error.apply(console, arguments) } + : function () {} + +var url = require("url") + , path = require("path") + , Stream = require("stream").Stream + , abbrev = require("abbrev") + +module.exports = exports = nopt +exports.clean = clean + +exports.typeDefs = + { String : { type: String, validate: validateString } + , Boolean : { type: Boolean, validate: validateBoolean } + , url : { type: url, validate: validateUrl } + , Number : { type: Number, validate: validateNumber } + , path : { type: path, validate: validatePath } + , Stream : { type: Stream, validate: validateStream } + , Date : { type: Date, validate: validateDate } + } + +function nopt (types, shorthands, args, slice) { + args = args || process.argv + types = types || {} + shorthands = shorthands || {} + if (typeof slice !== "number") slice = 2 + + debug(types, shorthands, args, slice) + + args = args.slice(slice) + var data = {} + , key + , remain = [] + , cooked = args + , original = args.slice(0) + + parse(args, data, remain, types, shorthands) + // now data is full + clean(data, types, exports.typeDefs) + data.argv = {remain:remain,cooked:cooked,original:original} + Object.defineProperty(data.argv, 'toString', { value: function () { + return this.original.map(JSON.stringify).join(" ") + }, enumerable: false }) + return data +} + +function clean (data, types, typeDefs) { + typeDefs = typeDefs || exports.typeDefs + var remove = {} + , typeDefault = [false, true, null, String, Array] + + Object.keys(data).forEach(function (k) { + if (k === "argv") return + var val = data[k] + , isArray = Array.isArray(val) + , type = types[k] + if (!isArray) val = [val] + if (!type) type = typeDefault + if (type === Array) type = typeDefault.concat(Array) + if (!Array.isArray(type)) type = [type] + + debug("val=%j", val) + debug("types=", type) + val = val.map(function (val) { + // if it's an unknown value, then parse false/true/null/numbers/dates + if (typeof val === "string") { + debug("string %j", val) + val = val.trim() + if ((val === "null" && ~type.indexOf(null)) + || (val === "true" && + (~type.indexOf(true) || ~type.indexOf(Boolean))) + || (val === "false" && + (~type.indexOf(false) || ~type.indexOf(Boolean)))) { + val = JSON.parse(val) + debug("jsonable %j", val) + } else if (~type.indexOf(Number) && !isNaN(val)) { + debug("convert to number", val) + val = +val + } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { + debug("convert to date", val) + val = new Date(val) + } + } + + if (!types.hasOwnProperty(k)) { + return val + } + + // allow `--no-blah` to set 'blah' to null if null is allowed + if (val === false && ~type.indexOf(null) && + !(~type.indexOf(false) || ~type.indexOf(Boolean))) { + val = null + } + + var d = {} + d[k] = val + debug("prevalidated val", d, val, types[k]) + if (!validate(d, k, val, types[k], typeDefs)) { + if (exports.invalidHandler) { + exports.invalidHandler(k, val, types[k], data) + } else if (exports.invalidHandler !== false) { + debug("invalid: "+k+"="+val, types[k]) + } + return remove + } + debug("validated val", d, val, types[k]) + return d[k] + }).filter(function (val) { return val !== remove }) + + if (!val.length) delete data[k] + else if (isArray) { + debug(isArray, data[k], val) + data[k] = val + } else data[k] = val[0] + + debug("k=%s val=%j", k, val, data[k]) + }) +} + +function validateString (data, k, val) { + data[k] = String(val) +} + +function validatePath (data, k, val) { + if (val === true) return false + if (val === null) return true + + val = String(val) + var homePattern = process.platform === 'win32' ? /^~(\/|\\)/ : /^~\// + if (val.match(homePattern) && process.env.HOME) { + val = path.resolve(process.env.HOME, val.substr(2)) + } + data[k] = path.resolve(String(val)) + return true +} + +function validateNumber (data, k, val) { + debug("validate Number %j %j %j", k, val, isNaN(val)) + if (isNaN(val)) return false + data[k] = +val +} + +function validateDate (data, k, val) { + debug("validate Date %j %j %j", k, val, Date.parse(val)) + var s = Date.parse(val) + if (isNaN(s)) return false + data[k] = new Date(val) +} + +function validateBoolean (data, k, val) { + if (val instanceof Boolean) val = val.valueOf() + else if (typeof val === "string") { + if (!isNaN(val)) val = !!(+val) + else if (val === "null" || val === "false") val = false + else val = true + } else val = !!val + data[k] = val +} + +function validateUrl (data, k, val) { + val = url.parse(String(val)) + if (!val.host) return false + data[k] = val.href +} + +function validateStream (data, k, val) { + if (!(val instanceof Stream)) return false + data[k] = val +} + +function validate (data, k, val, type, typeDefs) { + // arrays are lists of types. + if (Array.isArray(type)) { + for (var i = 0, l = type.length; i < l; i ++) { + if (type[i] === Array) continue + if (validate(data, k, val, type[i], typeDefs)) return true + } + delete data[k] + return false + } + + // an array of anything? + if (type === Array) return true + + // NaN is poisonous. Means that something is not allowed. + if (type !== type) { + debug("Poison NaN", k, val, type) + delete data[k] + return false + } + + // explicit list of values + if (val === type) { + debug("Explicitly allowed %j", val) + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + return true + } + + // now go through the list of typeDefs, validate against each one. + var ok = false + , types = Object.keys(typeDefs) + for (var i = 0, l = types.length; i < l; i ++) { + debug("test type %j %j %j", k, val, types[i]) + var t = typeDefs[types[i]] + if (t && + ((type && type.name && t.type && t.type.name) ? (type.name === t.type.name) : (type === t.type))) { + var d = {} + ok = false !== t.validate(d, k, val) + val = d[k] + if (ok) { + // if (isArray) (data[k] = data[k] || []).push(val) + // else data[k] = val + data[k] = val + break + } + } + } + debug("OK? %j (%j %j %j)", ok, k, val, types[i]) + + if (!ok) delete data[k] + return ok +} + +function parse (args, data, remain, types, shorthands) { + debug("parse", args, data, remain) + + var key = null + , abbrevs = abbrev(Object.keys(types)) + , shortAbbr = abbrev(Object.keys(shorthands)) + + for (var i = 0; i < args.length; i ++) { + var arg = args[i] + debug("arg", arg) + + if (arg.match(/^-{2,}$/)) { + // done with keys. + // the rest are args. + remain.push.apply(remain, args.slice(i + 1)) + args[i] = "--" + break + } + var hadEq = false + if (arg.charAt(0) === "-" && arg.length > 1) { + if (arg.indexOf("=") !== -1) { + hadEq = true + var v = arg.split("=") + arg = v.shift() + v = v.join("=") + args.splice.apply(args, [i, 1].concat([arg, v])) + } + + // see if it's a shorthand + // if so, splice and back up to re-parse it. + var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) + debug("arg=%j shRes=%j", arg, shRes) + if (shRes) { + debug(arg, shRes) + args.splice.apply(args, [i, 1].concat(shRes)) + if (arg !== shRes[0]) { + i -- + continue + } + } + arg = arg.replace(/^-+/, "") + var no = null + while (arg.toLowerCase().indexOf("no-") === 0) { + no = !no + arg = arg.substr(3) + } + + if (abbrevs[arg]) arg = abbrevs[arg] + + var isArray = types[arg] === Array || + Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1 + + // allow unknown things to be arrays if specified multiple times. + if (!types.hasOwnProperty(arg) && data.hasOwnProperty(arg)) { + if (!Array.isArray(data[arg])) + data[arg] = [data[arg]] + isArray = true + } + + var val + , la = args[i + 1] + + var isBool = typeof no === 'boolean' || + types[arg] === Boolean || + Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 || + (typeof types[arg] === 'undefined' && !hadEq) || + (la === "false" && + (types[arg] === null || + Array.isArray(types[arg]) && ~types[arg].indexOf(null))) + + if (isBool) { + // just set and move along + val = !no + // however, also support --bool true or --bool false + if (la === "true" || la === "false") { + val = JSON.parse(la) + la = null + if (no) val = !val + i ++ + } + + // also support "foo":[Boolean, "bar"] and "--foo bar" + if (Array.isArray(types[arg]) && la) { + if (~types[arg].indexOf(la)) { + // an explicit type + val = la + i ++ + } else if ( la === "null" && ~types[arg].indexOf(null) ) { + // null allowed + val = null + i ++ + } else if ( !la.match(/^-{2,}[^-]/) && + !isNaN(la) && + ~types[arg].indexOf(Number) ) { + // number + val = +la + i ++ + } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) { + // string + val = la + i ++ + } + } + + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + continue + } + + if (types[arg] === String && la === undefined) + la = "" + + if (la && la.match(/^-{2,}$/)) { + la = undefined + i -- + } + + val = la === undefined ? true : la + if (isArray) (data[arg] = data[arg] || []).push(val) + else data[arg] = val + + i ++ + continue + } + remain.push(arg) + } +} + +function resolveShort (arg, shorthands, shortAbbr, abbrevs) { + // handle single-char shorthands glommed together, like + // npm ls -glp, but only if there is one dash, and only if + // all of the chars are single-char shorthands, and it's + // not a match to some other abbrev. + arg = arg.replace(/^-+/, '') + + // if it's an exact known option, then don't go any further + if (abbrevs[arg] === arg) + return null + + // if it's an exact known shortopt, same deal + if (shorthands[arg]) { + // make it an array, if it's a list of words + if (shorthands[arg] && !Array.isArray(shorthands[arg])) + shorthands[arg] = shorthands[arg].split(/\s+/) + + return shorthands[arg] + } + + // first check to see if this arg is a set of single-char shorthands + var singles = shorthands.___singles + if (!singles) { + singles = Object.keys(shorthands).filter(function (s) { + return s.length === 1 + }).reduce(function (l,r) { + l[r] = true + return l + }, {}) + shorthands.___singles = singles + debug('shorthand singles', singles) + } + + var chrs = arg.split("").filter(function (c) { + return singles[c] + }) + + if (chrs.join("") === arg) return chrs.map(function (c) { + return shorthands[c] + }).reduce(function (l, r) { + return l.concat(r) + }, []) + + + // if it's an arg abbrev, and not a literal shorthand, then prefer the arg + if (abbrevs[arg] && !shorthands[arg]) + return null + + // if it's an abbr for a shorthand, then use that + if (shortAbbr[arg]) + arg = shortAbbr[arg] + + // make it an array, if it's a list of words + if (shorthands[arg] && !Array.isArray(shorthands[arg])) + shorthands[arg] = shorthands[arg].split(/\s+/) + + return shorthands[arg] +} diff --git a/node_modules/npm-lifecycle/node_modules/nopt/package.json b/node_modules/npm-lifecycle/node_modules/nopt/package.json new file mode 100644 index 0000000000000..76ed91f436451 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/nopt/package.json @@ -0,0 +1,57 @@ +{ + "_from": "nopt@2 || 3", + "_id": "nopt@3.0.6", + "_inBundle": false, + "_integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "_location": "/npm-lifecycle/nopt", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "nopt@2 || 3", + "name": "nopt", + "escapedName": "nopt", + "rawSpec": "2 || 3", + "saveSpec": null, + "fetchSpec": "2 || 3" + }, + "_requiredBy": [ + "/npm-lifecycle/node-gyp" + ], + "_resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "_shasum": "c6465dbf08abcd4db359317f79ac68a646b28ff9", + "_spec": "nopt@2 || 3", + "_where": "/home/hugh/Development/github.com/npm/cli/node_modules/npm-lifecycle/node_modules/node-gyp", + "author": { + "name": "Isaac Z. Schlueter", + "email": "i@izs.me", + "url": "http://blog.izs.me/" + }, + "bin": { + "nopt": "./bin/nopt.js" + }, + "bugs": { + "url": "https://github.com/npm/nopt/issues" + }, + "bundleDependencies": false, + "dependencies": { + "abbrev": "1" + }, + "deprecated": false, + "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", + "devDependencies": { + "tap": "^1.2.0" + }, + "homepage": "https://github.com/npm/nopt#readme", + "license": "ISC", + "main": "lib/nopt.js", + "name": "nopt", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/nopt.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "version": "3.0.6" +} diff --git a/node_modules/npm-lifecycle/node_modules/nopt/test/basic.js b/node_modules/npm-lifecycle/node_modules/nopt/test/basic.js new file mode 100644 index 0000000000000..d399de9209932 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/nopt/test/basic.js @@ -0,0 +1,273 @@ +var nopt = require("../") + , test = require('tap').test + + +test("passing a string results in a string", function (t) { + var parsed = nopt({ key: String }, {}, ["--key", "myvalue"], 0) + t.same(parsed.key, "myvalue") + t.end() +}) + +// https://github.com/npm/nopt/issues/31 +test("Empty String results in empty string, not true", function (t) { + var parsed = nopt({ empty: String }, {}, ["--empty"], 0) + t.same(parsed.empty, "") + t.end() +}) + +test("~ path is resolved to $HOME", function (t) { + var path = require("path") + if (!process.env.HOME) process.env.HOME = "/tmp" + var parsed = nopt({key: path}, {}, ["--key=~/val"], 0) + t.same(parsed.key, path.resolve(process.env.HOME, "val")) + t.end() +}) + +// https://github.com/npm/nopt/issues/24 +test("Unknown options are not parsed as numbers", function (t) { + var parsed = nopt({"parse-me": Number}, null, ['--leave-as-is=1.20', '--parse-me=1.20'], 0) + t.equal(parsed['leave-as-is'], '1.20') + t.equal(parsed['parse-me'], 1.2) + t.end() +}); + +// https://github.com/npm/nopt/issues/48 +test("Check types based on name of type", function (t) { + var parsed = nopt({"parse-me": {name: "Number"}}, null, ['--parse-me=1.20'], 0) + t.equal(parsed['parse-me'], 1.2) + t.end() +}) + + +test("Missing types are not parsed", function (t) { + var parsed = nopt({"parse-me": {}}, null, ['--parse-me=1.20'], 0) + //should only contain argv + t.equal(Object.keys(parsed).length, 1) + t.end() +}) + +test("Types passed without a name are not parsed", function (t) { + var parsed = nopt({"parse-me": {}}, {}, ['--parse-me=1.20'], 0) + //should only contain argv + t.equal(Object.keys(parsed).length, 1) + t.end() +}) + +test("other tests", function (t) { + + var util = require("util") + , Stream = require("stream") + , path = require("path") + , url = require("url") + + , shorthands = + { s : ["--loglevel", "silent"] + , d : ["--loglevel", "info"] + , dd : ["--loglevel", "verbose"] + , ddd : ["--loglevel", "silly"] + , noreg : ["--no-registry"] + , reg : ["--registry"] + , "no-reg" : ["--no-registry"] + , silent : ["--loglevel", "silent"] + , verbose : ["--loglevel", "verbose"] + , h : ["--usage"] + , H : ["--usage"] + , "?" : ["--usage"] + , help : ["--usage"] + , v : ["--version"] + , f : ["--force"] + , desc : ["--description"] + , "no-desc" : ["--no-description"] + , "local" : ["--no-global"] + , l : ["--long"] + , p : ["--parseable"] + , porcelain : ["--parseable"] + , g : ["--global"] + } + + , types = + { aoa: Array + , nullstream: [null, Stream] + , date: Date + , str: String + , browser : String + , cache : path + , color : ["always", Boolean] + , depth : Number + , description : Boolean + , dev : Boolean + , editor : path + , force : Boolean + , global : Boolean + , globalconfig : path + , group : [String, Number] + , gzipbin : String + , logfd : [Number, Stream] + , loglevel : ["silent","win","error","warn","info","verbose","silly"] + , long : Boolean + , "node-version" : [false, String] + , npaturl : url + , npat : Boolean + , "onload-script" : [false, String] + , outfd : [Number, Stream] + , parseable : Boolean + , pre: Boolean + , prefix: path + , proxy : url + , "rebuild-bundle" : Boolean + , registry : url + , searchopts : String + , searchexclude: [null, String] + , shell : path + , t: [Array, String] + , tag : String + , tar : String + , tmp : path + , "unsafe-perm" : Boolean + , usage : Boolean + , user : String + , username : String + , userconfig : path + , version : Boolean + , viewer: path + , _exit : Boolean + , path: path + } + + ; [["-v", {version:true}, []] + ,["---v", {version:true}, []] + ,["ls -s --no-reg connect -d", + {loglevel:"info",registry:null},["ls","connect"]] + ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] + ,["ls --registry blargle", {}, ["ls"]] + ,["--no-registry", {registry:null}, []] + ,["--no-color true", {color:false}, []] + ,["--no-color false", {color:true}, []] + ,["--no-color", {color:false}, []] + ,["--color false", {color:false}, []] + ,["--color --logfd 7", {logfd:7,color:true}, []] + ,["--color=true", {color:true}, []] + ,["--logfd=10", {logfd:10}, []] + ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]] + ,["--tmp=tmp -tar=gtar", + {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] + ,["--logfd x", {}, []] + ,["a -true -- -no-false", {true:true},["a","-no-false"]] + ,["a -no-false", {false:false},["a"]] + ,["a -no-no-true", {true:true}, ["a"]] + ,["a -no-no-no-false", {false:false}, ["a"]] + ,["---NO-no-No-no-no-no-nO-no-no"+ + "-No-no-no-no-no-no-no-no-no"+ + "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ + "-no-body-can-do-the-boogaloo-like-I-do" + ,{"body-can-do-the-boogaloo-like-I-do":false}, []] + ,["we are -no-strangers-to-love "+ + "--you-know=the-rules --and=so-do-i "+ + "---im-thinking-of=a-full-commitment "+ + "--no-you-would-get-this-from-any-other-guy "+ + "--no-gonna-give-you-up "+ + "-no-gonna-let-you-down=true "+ + "--no-no-gonna-run-around false "+ + "--desert-you=false "+ + "--make-you-cry false "+ + "--no-tell-a-lie "+ + "--no-no-and-hurt-you false" + ,{"strangers-to-love":false + ,"you-know":"the-rules" + ,"and":"so-do-i" + ,"you-would-get-this-from-any-other-guy":false + ,"gonna-give-you-up":false + ,"gonna-let-you-down":false + ,"gonna-run-around":false + ,"desert-you":false + ,"make-you-cry":false + ,"tell-a-lie":false + ,"and-hurt-you":false + },["we", "are"]] + ,["-t one -t two -t three" + ,{t: ["one", "two", "three"]} + ,[]] + ,["-t one -t null -t three four five null" + ,{t: ["one", "null", "three"]} + ,["four", "five", "null"]] + ,["-t foo" + ,{t:["foo"]} + ,[]] + ,["--no-t" + ,{t:["false"]} + ,[]] + ,["-no-no-t" + ,{t:["true"]} + ,[]] + ,["-aoa one -aoa null -aoa 100" + ,{aoa:["one", null, '100']} + ,[]] + ,["-str 100" + ,{str:"100"} + ,[]] + ,["--color always" + ,{color:"always"} + ,[]] + ,["--no-nullstream" + ,{nullstream:null} + ,[]] + ,["--nullstream false" + ,{nullstream:null} + ,[]] + ,["--notadate=2011-01-25" + ,{notadate: "2011-01-25"} + ,[]] + ,["--date 2011-01-25" + ,{date: new Date("2011-01-25")} + ,[]] + ,["-cl 1" + ,{config: true, length: 1} + ,[] + ,{config: Boolean, length: Number, clear: Boolean} + ,{c: "--config", l: "--length"}] + ,["--acount bla" + ,{"acount":true} + ,["bla"] + ,{account: Boolean, credentials: Boolean, options: String} + ,{a:"--account", c:"--credentials",o:"--options"}] + ,["--clear" + ,{clear:true} + ,[] + ,{clear:Boolean,con:Boolean,len:Boolean,exp:Boolean,add:Boolean,rep:Boolean} + ,{c:"--con",l:"--len",e:"--exp",a:"--add",r:"--rep"}] + ,["--file -" + ,{"file":"-"} + ,[] + ,{file:String} + ,{}] + ,["--file -" + ,{"file":true} + ,["-"] + ,{file:Boolean} + ,{}] + ,["--path" + ,{"path":null} + ,[]] + ,["--path ." + ,{"path":process.cwd()} + ,[]] + ].forEach(function (test) { + var argv = test[0].split(/\s+/) + , opts = test[1] + , rem = test[2] + , actual = nopt(test[3] || types, test[4] || shorthands, argv, 0) + , parsed = actual.argv + delete actual.argv + for (var i in opts) { + var e = JSON.stringify(opts[i]) + , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) + if (e && typeof e === "object") { + t.deepEqual(e, a) + } else { + t.equal(e, a) + } + } + t.deepEqual(rem, parsed.remain) + }) + t.end() +}) diff --git a/node_modules/npm-lifecycle/node_modules/semver/LICENSE b/node_modules/npm-lifecycle/node_modules/semver/LICENSE new file mode 100644 index 0000000000000..19129e315fe59 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/semver/LICENSE @@ -0,0 +1,15 @@ +The ISC License + +Copyright (c) Isaac Z. Schlueter and Contributors + +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/node_modules/npm-lifecycle/node_modules/semver/README.md b/node_modules/npm-lifecycle/node_modules/semver/README.md new file mode 100644 index 0000000000000..cbd956549dbb0 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/semver/README.md @@ -0,0 +1,350 @@ +semver(1) -- The semantic versioner for npm +=========================================== + +## Usage + + $ npm install semver + $ node + var semver = require('semver') + + semver.valid('1.2.3') // '1.2.3' + semver.valid('a.b.c') // null + semver.clean(' =v1.2.3 ') // '1.2.3' + semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true + semver.gt('1.2.3', '9.8.7') // false + semver.lt('1.2.3', '9.8.7') // true + +As a command-line utility: + + $ semver -h + + SemVer 5.1.0 + + A JavaScript implementation of the http://semver.org/ specification + Copyright Isaac Z. Schlueter + + Usage: semver [options] [ [...]] + Prints valid versions sorted by SemVer precedence + + Options: + -r --range + Print versions that match the specified range. + + -i --increment [] + Increment a version by the specified level. Level can + be one of: major, minor, patch, premajor, preminor, + prepatch, or prerelease. Default level is 'patch'. + Only one version may be specified. + + --preid + Identifier to be used to prefix premajor, preminor, + prepatch or prerelease version increments. + + -l --loose + Interpret versions and ranges loosely + + Program exits successfully if any valid version satisfies + all supplied ranges, and prints all satisfying versions. + + If no satisfying versions are found, then exits failure. + + Versions are printed in ascending order, so supplying + multiple versions to the utility will just sort them. + +## Versions + +A "version" is described by the `v2.0.0` specification found at +. + +A leading `"="` or `"v"` character is stripped off and ignored. + +## Ranges + +A `version range` is a set of `comparators` which specify versions +that satisfy the range. + +A `comparator` is composed of an `operator` and a `version`. The set +of primitive `operators` is: + +* `<` Less than +* `<=` Less than or equal to +* `>` Greater than +* `>=` Greater than or equal to +* `=` Equal. If no operator is specified, then equality is assumed, + so this operator is optional, but MAY be included. + +For example, the comparator `>=1.2.7` would match the versions +`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6` +or `1.1.0`. + +Comparators can be joined by whitespace to form a `comparator set`, +which is satisfied by the **intersection** of all of the comparators +it includes. + +A range is composed of one or more comparator sets, joined by `||`. A +version matches a range if and only if every comparator in at least +one of the `||`-separated comparator sets is satisfied by the version. + +For example, the range `>=1.2.7 <1.3.0` would match the versions +`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`, +or `1.1.0`. + +The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`, +`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`. + +### Prerelease Tags + +If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then +it will only be allowed to satisfy comparator sets if at least one +comparator with the same `[major, minor, patch]` tuple also has a +prerelease tag. + +For example, the range `>1.2.3-alpha.3` would be allowed to match the +version `1.2.3-alpha.7`, but it would *not* be satisfied by +`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater +than" `1.2.3-alpha.3` according to the SemVer sort rules. The version +range only accepts prerelease tags on the `1.2.3` version. The +version `3.4.5` *would* satisfy the range, because it does not have a +prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`. + +The purpose for this behavior is twofold. First, prerelease versions +frequently are updated very quickly, and contain many breaking changes +that are (by the author's design) not yet fit for public consumption. +Therefore, by default, they are excluded from range matching +semantics. + +Second, a user who has opted into using a prerelease version has +clearly indicated the intent to use *that specific* set of +alpha/beta/rc versions. By including a prerelease tag in the range, +the user is indicating that they are aware of the risk. However, it +is still not appropriate to assume that they have opted into taking a +similar risk on the *next* set of prerelease versions. + +#### Prerelease Identifiers + +The method `.inc` takes an additional `identifier` string argument that +will append the value of the string as a prerelease identifier: + +```javascript +> semver.inc('1.2.3', 'prerelease', 'beta') +'1.2.4-beta.0' +``` + +command-line example: + +```shell +$ semver 1.2.3 -i prerelease --preid beta +1.2.4-beta.0 +``` + +Which then can be used to increment further: + +```shell +$ semver 1.2.4-beta.0 -i prerelease +1.2.4-beta.1 +``` + +### Advanced Range Syntax + +Advanced range syntax desugars to primitive comparators in +deterministic ways. + +Advanced ranges may be combined in the same way as primitive +comparators using white space or `||`. + +#### Hyphen Ranges `X.Y.Z - A.B.C` + +Specifies an inclusive set. + +* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4` + +If a partial version is provided as the first version in the inclusive +range, then the missing pieces are replaced with zeroes. + +* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4` + +If a partial version is provided as the second version in the +inclusive range, then all versions that start with the supplied parts +of the tuple are accepted, but nothing that would be greater than the +provided tuple parts. + +* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0` +* `1.2.3 - 2` := `>=1.2.3 <3.0.0` + +#### X-Ranges `1.2.x` `1.X` `1.2.*` `*` + +Any of `X`, `x`, or `*` may be used to "stand in" for one of the +numeric values in the `[major, minor, patch]` tuple. + +* `*` := `>=0.0.0` (Any version satisfies) +* `1.x` := `>=1.0.0 <2.0.0` (Matching major version) +* `1.2.x` := `>=1.2.0 <1.3.0` (Matching major and minor versions) + +A partial version range is treated as an X-Range, so the special +character is in fact optional. + +* `""` (empty string) := `*` := `>=0.0.0` +* `1` := `1.x.x` := `>=1.0.0 <2.0.0` +* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0` + +#### Tilde Ranges `~1.2.3` `~1.2` `~1` + +Allows patch-level changes if a minor version is specified on the +comparator. Allows minor-level changes if not. + +* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0` +* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0` (Same as `1.2.x`) +* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0` (Same as `1.x`) +* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0` +* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0` (Same as `0.2.x`) +* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0` (Same as `0.x`) +* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0` Note that prereleases in + the `1.2.3` version will be allowed, if they are greater than or + equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but + `1.2.4-beta.2` would not, because it is a prerelease of a + different `[major, minor, patch]` tuple. + +#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4` + +Allows changes that do not modify the left-most non-zero digit in the +`[major, minor, patch]` tuple. In other words, this allows patch and +minor updates for versions `1.0.0` and above, patch updates for +versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`. + +Many authors treat a `0.x` version as if the `x` were the major +"breaking-change" indicator. + +Caret ranges are ideal when an author may make breaking changes +between `0.2.4` and `0.3.0` releases, which is a common practice. +However, it presumes that there will *not* be breaking changes between +`0.2.4` and `0.2.5`. It allows for changes that are presumed to be +additive (but non-breaking), according to commonly observed practices. + +* `^1.2.3` := `>=1.2.3 <2.0.0` +* `^0.2.3` := `>=0.2.3 <0.3.0` +* `^0.0.3` := `>=0.0.3 <0.0.4` +* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0` Note that prereleases in + the `1.2.3` version will be allowed, if they are greater than or + equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but + `1.2.4-beta.2` would not, because it is a prerelease of a + different `[major, minor, patch]` tuple. +* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4` Note that prereleases in the + `0.0.3` version *only* will be allowed, if they are greater than or + equal to `beta`. So, `0.0.3-pr.2` would be allowed. + +When parsing caret ranges, a missing `patch` value desugars to the +number `0`, but will allow flexibility within that value, even if the +major and minor versions are both `0`. + +* `^1.2.x` := `>=1.2.0 <2.0.0` +* `^0.0.x` := `>=0.0.0 <0.1.0` +* `^0.0` := `>=0.0.0 <0.1.0` + +A missing `minor` and `patch` values will desugar to zero, but also +allow flexibility within those values, even if the major version is +zero. + +* `^1.x` := `>=1.0.0 <2.0.0` +* `^0.x` := `>=0.0.0 <1.0.0` + +### Range Grammar + +Putting all this together, here is a Backus-Naur grammar for ranges, +for the benefit of parser authors: + +```bnf +range-set ::= range ( logical-or range ) * +logical-or ::= ( ' ' ) * '||' ( ' ' ) * +range ::= hyphen | simple ( ' ' simple ) * | '' +hyphen ::= partial ' - ' partial +simple ::= primitive | partial | tilde | caret +primitive ::= ( '<' | '>' | '>=' | '<=' | '=' | ) partial +partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? +xr ::= 'x' | 'X' | '*' | nr +nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) * +tilde ::= '~' partial +caret ::= '^' partial +qualifier ::= ( '-' pre )? ( '+' build )? +pre ::= parts +build ::= parts +parts ::= part ( '.' part ) * +part ::= nr | [-0-9A-Za-z]+ +``` + +## Functions + +All methods and classes take a final `loose` boolean argument that, if +true, will be more forgiving about not-quite-valid semver strings. +The resulting output will always be 100% strict, of course. + +Strict-mode Comparators and Ranges will be strict about the SemVer +strings that they parse. + +* `valid(v)`: Return the parsed version, or null if it's not valid. +* `inc(v, release)`: Return the version incremented by the release + type (`major`, `premajor`, `minor`, `preminor`, `patch`, + `prepatch`, or `prerelease`), or null if it's not valid + * `premajor` in one call will bump the version up to the next major + version and down to a prerelease of that major version. + `preminor`, and `prepatch` work the same way. + * If called from a non-prerelease version, the `prerelease` will work the + same as `prepatch`. It increments the patch version, then makes a + prerelease. If the input version is already a prerelease it simply + increments it. +* `prerelease(v)`: Returns an array of prerelease components, or null + if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]` +* `major(v)`: Return the major version number. +* `minor(v)`: Return the minor version number. +* `patch(v)`: Return the patch version number. + +### Comparison + +* `gt(v1, v2)`: `v1 > v2` +* `gte(v1, v2)`: `v1 >= v2` +* `lt(v1, v2)`: `v1 < v2` +* `lte(v1, v2)`: `v1 <= v2` +* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent, + even if they're not the exact same string. You already know how to + compare strings. +* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`. +* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call + the corresponding function above. `"==="` and `"!=="` do simple + string comparison, but are included for completeness. Throws if an + invalid comparison string is provided. +* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if + `v2` is greater. Sorts in ascending order if passed to `Array.sort()`. +* `rcompare(v1, v2)`: The reverse of compare. Sorts an array of versions + in descending order when passed to `Array.sort()`. +* `diff(v1, v2)`: Returns difference between two versions by the release type + (`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`), + or null if the versions are the same. + + +### Ranges + +* `validRange(range)`: Return the valid range or null if it's not valid +* `satisfies(version, range)`: Return true if the version satisfies the + range. +* `maxSatisfying(versions, range)`: Return the highest version in the list + that satisfies the range, or `null` if none of them do. +* `minSatisfying(versions, range)`: Return the lowest version in the list + that satisfies the range, or `null` if none of them do. +* `gtr(version, range)`: Return `true` if version is greater than all the + versions possible in the range. +* `ltr(version, range)`: Return `true` if version is less than all the + versions possible in the range. +* `outside(version, range, hilo)`: Return true if the version is outside + the bounds of the range in either the high or low direction. The + `hilo` argument must be either the string `'>'` or `'<'`. (This is + the function called by `gtr` and `ltr`.) + +Note that, since ranges may be non-contiguous, a version might not be +greater than a range, less than a range, *or* satisfy a range! For +example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9` +until `2.0.0`, so the version `1.2.10` would not be greater than the +range (because `2.0.1` satisfies, which is higher), nor less than the +range (since `1.2.8` satisfies, which is lower), and it also does not +satisfy the range. + +If you want to know if a version satisfies or does not satisfy a +range, use the `satisfies(version, range)` function. diff --git a/node_modules/npm-lifecycle/node_modules/semver/bin/semver b/node_modules/npm-lifecycle/node_modules/semver/bin/semver new file mode 100755 index 0000000000000..c5f2e857e8279 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/semver/bin/semver @@ -0,0 +1,133 @@ +#!/usr/bin/env node +// Standalone semver comparison program. +// Exits successfully and prints matching version(s) if +// any supplied version is valid and passes all tests. + +var argv = process.argv.slice(2) + , versions = [] + , range = [] + , gt = [] + , lt = [] + , eq = [] + , inc = null + , version = require("../package.json").version + , loose = false + , identifier = undefined + , semver = require("../semver") + , reverse = false + +main() + +function main () { + if (!argv.length) return help() + while (argv.length) { + var a = argv.shift() + var i = a.indexOf('=') + if (i !== -1) { + a = a.slice(0, i) + argv.unshift(a.slice(i + 1)) + } + switch (a) { + case "-rv": case "-rev": case "--rev": case "--reverse": + reverse = true + break + case "-l": case "--loose": + loose = true + break + case "-v": case "--version": + versions.push(argv.shift()) + break + case "-i": case "--inc": case "--increment": + switch (argv[0]) { + case "major": case "minor": case "patch": case "prerelease": + case "premajor": case "preminor": case "prepatch": + inc = argv.shift() + break + default: + inc = "patch" + break + } + break + case "--preid": + identifier = argv.shift() + break + case "-r": case "--range": + range.push(argv.shift()) + break + case "-h": case "--help": case "-?": + return help() + default: + versions.push(a) + break + } + } + + versions = versions.filter(function (v) { + return semver.valid(v, loose) + }) + if (!versions.length) return fail() + if (inc && (versions.length !== 1 || range.length)) + return failInc() + + for (var i = 0, l = range.length; i < l ; i ++) { + versions = versions.filter(function (v) { + return semver.satisfies(v, range[i], loose) + }) + if (!versions.length) return fail() + } + return success(versions) +} + +function failInc () { + console.error("--inc can only be used on a single version with no range") + fail() +} + +function fail () { process.exit(1) } + +function success () { + var compare = reverse ? "rcompare" : "compare" + versions.sort(function (a, b) { + return semver[compare](a, b, loose) + }).map(function (v) { + return semver.clean(v, loose) + }).map(function (v) { + return inc ? semver.inc(v, inc, loose, identifier) : v + }).forEach(function (v,i,_) { console.log(v) }) +} + +function help () { + console.log(["SemVer " + version + ,"" + ,"A JavaScript implementation of the http://semver.org/ specification" + ,"Copyright Isaac Z. Schlueter" + ,"" + ,"Usage: semver [options] [ [...]]" + ,"Prints valid versions sorted by SemVer precedence" + ,"" + ,"Options:" + ,"-r --range " + ," Print versions that match the specified range." + ,"" + ,"-i --increment []" + ," Increment a version by the specified level. Level can" + ," be one of: major, minor, patch, premajor, preminor," + ," prepatch, or prerelease. Default level is 'patch'." + ," Only one version may be specified." + ,"" + ,"--preid " + ," Identifier to be used to prefix premajor, preminor," + ," prepatch or prerelease version increments." + ,"" + ,"-l --loose" + ," Interpret versions and ranges loosely" + ,"" + ,"Program exits successfully if any valid version satisfies" + ,"all supplied ranges, and prints all satisfying versions." + ,"" + ,"If no satisfying versions are found, then exits failure." + ,"" + ,"Versions are printed in ascending order, so supplying" + ,"multiple versions to the utility will just sort them." + ].join("\n")) +} diff --git a/node_modules/npm-lifecycle/node_modules/semver/package.json b/node_modules/npm-lifecycle/node_modules/semver/package.json new file mode 100644 index 0000000000000..15592dc76bd93 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/semver/package.json @@ -0,0 +1,54 @@ +{ + "_from": "semver@~5.3.0", + "_id": "semver@5.3.0", + "_inBundle": false, + "_integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", + "_location": "/npm-lifecycle/semver", + "_phantomChildren": {}, + "_requested": { + "type": "range", + "registry": true, + "raw": "semver@~5.3.0", + "name": "semver", + "escapedName": "semver", + "rawSpec": "~5.3.0", + "saveSpec": null, + "fetchSpec": "~5.3.0" + }, + "_requiredBy": [ + "/npm-lifecycle/node-gyp" + ], + "_resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "_shasum": "9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f", + "_spec": "semver@~5.3.0", + "_where": "/home/hugh/Development/github.com/npm/cli/node_modules/npm-lifecycle/node_modules/node-gyp", + "bin": { + "semver": "./bin/semver" + }, + "bugs": { + "url": "https://github.com/npm/node-semver/issues" + }, + "bundleDependencies": false, + "deprecated": false, + "description": "The semantic version parser used by npm.", + "devDependencies": { + "tap": "^2.0.0" + }, + "files": [ + "bin", + "range.bnf", + "semver.js" + ], + "homepage": "https://github.com/npm/node-semver#readme", + "license": "ISC", + "main": "semver.js", + "name": "semver", + "repository": { + "type": "git", + "url": "git+https://github.com/npm/node-semver.git" + }, + "scripts": { + "test": "tap test/*.js" + }, + "version": "5.3.0" +} diff --git a/node_modules/npm-lifecycle/node_modules/semver/range.bnf b/node_modules/npm-lifecycle/node_modules/semver/range.bnf new file mode 100644 index 0000000000000..25ebd5c832548 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/semver/range.bnf @@ -0,0 +1,16 @@ +range-set ::= range ( logical-or range ) * +logical-or ::= ( ' ' ) * '||' ( ' ' ) * +range ::= hyphen | simple ( ' ' simple ) * | '' +hyphen ::= partial ' - ' partial +simple ::= primitive | partial | tilde | caret +primitive ::= ( '<' | '>' | '>=' | '<=' | '=' | ) partial +partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? +xr ::= 'x' | 'X' | '*' | nr +nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) * +tilde ::= '~' partial +caret ::= '^' partial +qualifier ::= ( '-' pre )? ( '+' build )? +pre ::= parts +build ::= parts +parts ::= part ( '.' part ) * +part ::= nr | [-0-9A-Za-z]+ diff --git a/node_modules/npm-lifecycle/node_modules/semver/semver.js b/node_modules/npm-lifecycle/node_modules/semver/semver.js new file mode 100644 index 0000000000000..5f1a3c5c9e5dc --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/semver/semver.js @@ -0,0 +1,1203 @@ +exports = module.exports = SemVer; + +// The debug function is excluded entirely from the minified version. +/* nomin */ var debug; +/* nomin */ if (typeof process === 'object' && + /* nomin */ process.env && + /* nomin */ process.env.NODE_DEBUG && + /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) + /* nomin */ debug = function() { + /* nomin */ var args = Array.prototype.slice.call(arguments, 0); + /* nomin */ args.unshift('SEMVER'); + /* nomin */ console.log.apply(console, args); + /* nomin */ }; +/* nomin */ else + /* nomin */ debug = function() {}; + +// Note: this is the semver.org version of the spec that it implements +// Not necessarily the package version of this code. +exports.SEMVER_SPEC_VERSION = '2.0.0'; + +var MAX_LENGTH = 256; +var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; + +// The actual regexps go on exports.re +var re = exports.re = []; +var src = exports.src = []; +var R = 0; + +// The following Regular Expressions can be used for tokenizing, +// validating, and parsing SemVer version strings. + +// ## Numeric Identifier +// A single `0`, or a non-zero digit followed by zero or more digits. + +var NUMERICIDENTIFIER = R++; +src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; +var NUMERICIDENTIFIERLOOSE = R++; +src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; + + +// ## Non-numeric Identifier +// Zero or more digits, followed by a letter or hyphen, and then zero or +// more letters, digits, or hyphens. + +var NONNUMERICIDENTIFIER = R++; +src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; + + +// ## Main Version +// Three dot-separated numeric identifiers. + +var MAINVERSION = R++; +src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')\\.' + + '(' + src[NUMERICIDENTIFIER] + ')'; + +var MAINVERSIONLOOSE = R++; +src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + + '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; + +// ## Pre-release Version Identifier +// A numeric identifier, or a non-numeric identifier. + +var PRERELEASEIDENTIFIER = R++; +src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + + '|' + src[NONNUMERICIDENTIFIER] + ')'; + +var PRERELEASEIDENTIFIERLOOSE = R++; +src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + + '|' + src[NONNUMERICIDENTIFIER] + ')'; + + +// ## Pre-release Version +// Hyphen, followed by one or more dot-separated pre-release version +// identifiers. + +var PRERELEASE = R++; +src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + + '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; + +var PRERELEASELOOSE = R++; +src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + + '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; + +// ## Build Metadata Identifier +// Any combination of digits, letters, or hyphens. + +var BUILDIDENTIFIER = R++; +src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; + +// ## Build Metadata +// Plus sign, followed by one or more period-separated build metadata +// identifiers. + +var BUILD = R++; +src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + + '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; + + +// ## Full Version String +// A main version, followed optionally by a pre-release version and +// build metadata. + +// Note that the only major, minor, patch, and pre-release sections of +// the version string are capturing groups. The build metadata is not a +// capturing group, because it should not ever be used in version +// comparison. + +var FULL = R++; +var FULLPLAIN = 'v?' + src[MAINVERSION] + + src[PRERELEASE] + '?' + + src[BUILD] + '?'; + +src[FULL] = '^' + FULLPLAIN + '$'; + +// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. +// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty +// common in the npm registry. +var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + + src[PRERELEASELOOSE] + '?' + + src[BUILD] + '?'; + +var LOOSE = R++; +src[LOOSE] = '^' + LOOSEPLAIN + '$'; + +var GTLT = R++; +src[GTLT] = '((?:<|>)?=?)'; + +// Something like "2.*" or "1.2.x". +// Note that "x.x" is a valid xRange identifer, meaning "any version" +// Only the first item is strictly required. +var XRANGEIDENTIFIERLOOSE = R++; +src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; +var XRANGEIDENTIFIER = R++; +src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; + +var XRANGEPLAIN = R++; +src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + + '(?:' + src[PRERELEASE] + ')?' + + src[BUILD] + '?' + + ')?)?'; + +var XRANGEPLAINLOOSE = R++; +src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + + '(?:' + src[PRERELEASELOOSE] + ')?' + + src[BUILD] + '?' + + ')?)?'; + +var XRANGE = R++; +src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; +var XRANGELOOSE = R++; +src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; + +// Tilde ranges. +// Meaning is "reasonably at or greater than" +var LONETILDE = R++; +src[LONETILDE] = '(?:~>?)'; + +var TILDETRIM = R++; +src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; +re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); +var tildeTrimReplace = '$1~'; + +var TILDE = R++; +src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; +var TILDELOOSE = R++; +src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; + +// Caret ranges. +// Meaning is "at least and backwards compatible with" +var LONECARET = R++; +src[LONECARET] = '(?:\\^)'; + +var CARETTRIM = R++; +src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; +re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); +var caretTrimReplace = '$1^'; + +var CARET = R++; +src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; +var CARETLOOSE = R++; +src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; + +// A simple gt/lt/eq thing, or just "" to indicate "any version" +var COMPARATORLOOSE = R++; +src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; +var COMPARATOR = R++; +src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; + + +// An expression to strip any whitespace between the gtlt and the thing +// it modifies, so that `> 1.2.3` ==> `>1.2.3` +var COMPARATORTRIM = R++; +src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + + '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; + +// this one has to use the /g flag +re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); +var comparatorTrimReplace = '$1$2$3'; + + +// Something like `1.2.3 - 1.2.4` +// Note that these all use the loose form, because they'll be +// checked against either the strict or loose comparator form +// later. +var HYPHENRANGE = R++; +src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAIN] + ')' + + '\\s*$'; + +var HYPHENRANGELOOSE = R++; +src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s+-\\s+' + + '(' + src[XRANGEPLAINLOOSE] + ')' + + '\\s*$'; + +// Star ranges basically just allow anything at all. +var STAR = R++; +src[STAR] = '(<|>)?=?\\s*\\*'; + +// Compile to actual regexp objects. +// All are flag-free, unless they were created above with a flag. +for (var i = 0; i < R; i++) { + debug(i, src[i]); + if (!re[i]) + re[i] = new RegExp(src[i]); +} + +exports.parse = parse; +function parse(version, loose) { + if (version instanceof SemVer) + return version; + + if (typeof version !== 'string') + return null; + + if (version.length > MAX_LENGTH) + return null; + + var r = loose ? re[LOOSE] : re[FULL]; + if (!r.test(version)) + return null; + + try { + return new SemVer(version, loose); + } catch (er) { + return null; + } +} + +exports.valid = valid; +function valid(version, loose) { + var v = parse(version, loose); + return v ? v.version : null; +} + + +exports.clean = clean; +function clean(version, loose) { + var s = parse(version.trim().replace(/^[=v]+/, ''), loose); + return s ? s.version : null; +} + +exports.SemVer = SemVer; + +function SemVer(version, loose) { + if (version instanceof SemVer) { + if (version.loose === loose) + return version; + else + version = version.version; + } else if (typeof version !== 'string') { + throw new TypeError('Invalid Version: ' + version); + } + + if (version.length > MAX_LENGTH) + throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') + + if (!(this instanceof SemVer)) + return new SemVer(version, loose); + + debug('SemVer', version, loose); + this.loose = loose; + var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); + + if (!m) + throw new TypeError('Invalid Version: ' + version); + + this.raw = version; + + // these are actually numbers + this.major = +m[1]; + this.minor = +m[2]; + this.patch = +m[3]; + + if (this.major > MAX_SAFE_INTEGER || this.major < 0) + throw new TypeError('Invalid major version') + + if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) + throw new TypeError('Invalid minor version') + + if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) + throw new TypeError('Invalid patch version') + + // numberify any prerelease numeric ids + if (!m[4]) + this.prerelease = []; + else + this.prerelease = m[4].split('.').map(function(id) { + if (/^[0-9]+$/.test(id)) { + var num = +id; + if (num >= 0 && num < MAX_SAFE_INTEGER) + return num; + } + return id; + }); + + this.build = m[5] ? m[5].split('.') : []; + this.format(); +} + +SemVer.prototype.format = function() { + this.version = this.major + '.' + this.minor + '.' + this.patch; + if (this.prerelease.length) + this.version += '-' + this.prerelease.join('.'); + return this.version; +}; + +SemVer.prototype.toString = function() { + return this.version; +}; + +SemVer.prototype.compare = function(other) { + debug('SemVer.compare', this.version, this.loose, other); + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); + + return this.compareMain(other) || this.comparePre(other); +}; + +SemVer.prototype.compareMain = function(other) { + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); + + return compareIdentifiers(this.major, other.major) || + compareIdentifiers(this.minor, other.minor) || + compareIdentifiers(this.patch, other.patch); +}; + +SemVer.prototype.comparePre = function(other) { + if (!(other instanceof SemVer)) + other = new SemVer(other, this.loose); + + // NOT having a prerelease is > having one + if (this.prerelease.length && !other.prerelease.length) + return -1; + else if (!this.prerelease.length && other.prerelease.length) + return 1; + else if (!this.prerelease.length && !other.prerelease.length) + return 0; + + var i = 0; + do { + var a = this.prerelease[i]; + var b = other.prerelease[i]; + debug('prerelease compare', i, a, b); + if (a === undefined && b === undefined) + return 0; + else if (b === undefined) + return 1; + else if (a === undefined) + return -1; + else if (a === b) + continue; + else + return compareIdentifiers(a, b); + } while (++i); +}; + +// preminor will bump the version up to the next minor release, and immediately +// down to pre-release. premajor and prepatch work the same way. +SemVer.prototype.inc = function(release, identifier) { + switch (release) { + case 'premajor': + this.prerelease.length = 0; + this.patch = 0; + this.minor = 0; + this.major++; + this.inc('pre', identifier); + break; + case 'preminor': + this.prerelease.length = 0; + this.patch = 0; + this.minor++; + this.inc('pre', identifier); + break; + case 'prepatch': + // If this is already a prerelease, it will bump to the next version + // drop any prereleases that might already exist, since they are not + // relevant at this point. + this.prerelease.length = 0; + this.inc('patch', identifier); + this.inc('pre', identifier); + break; + // If the input is a non-prerelease version, this acts the same as + // prepatch. + case 'prerelease': + if (this.prerelease.length === 0) + this.inc('patch', identifier); + this.inc('pre', identifier); + break; + + case 'major': + // If this is a pre-major version, bump up to the same major version. + // Otherwise increment major. + // 1.0.0-5 bumps to 1.0.0 + // 1.1.0 bumps to 2.0.0 + if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) + this.major++; + this.minor = 0; + this.patch = 0; + this.prerelease = []; + break; + case 'minor': + // If this is a pre-minor version, bump up to the same minor version. + // Otherwise increment minor. + // 1.2.0-5 bumps to 1.2.0 + // 1.2.1 bumps to 1.3.0 + if (this.patch !== 0 || this.prerelease.length === 0) + this.minor++; + this.patch = 0; + this.prerelease = []; + break; + case 'patch': + // If this is not a pre-release version, it will increment the patch. + // If it is a pre-release it will bump up to the same patch version. + // 1.2.0-5 patches to 1.2.0 + // 1.2.0 patches to 1.2.1 + if (this.prerelease.length === 0) + this.patch++; + this.prerelease = []; + break; + // This probably shouldn't be used publicly. + // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. + case 'pre': + if (this.prerelease.length === 0) + this.prerelease = [0]; + else { + var i = this.prerelease.length; + while (--i >= 0) { + if (typeof this.prerelease[i] === 'number') { + this.prerelease[i]++; + i = -2; + } + } + if (i === -1) // didn't increment anything + this.prerelease.push(0); + } + if (identifier) { + // 1.2.0-beta.1 bumps to 1.2.0-beta.2, + // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 + if (this.prerelease[0] === identifier) { + if (isNaN(this.prerelease[1])) + this.prerelease = [identifier, 0]; + } else + this.prerelease = [identifier, 0]; + } + break; + + default: + throw new Error('invalid increment argument: ' + release); + } + this.format(); + this.raw = this.version; + return this; +}; + +exports.inc = inc; +function inc(version, release, loose, identifier) { + if (typeof(loose) === 'string') { + identifier = loose; + loose = undefined; + } + + try { + return new SemVer(version, loose).inc(release, identifier).version; + } catch (er) { + return null; + } +} + +exports.diff = diff; +function diff(version1, version2) { + if (eq(version1, version2)) { + return null; + } else { + var v1 = parse(version1); + var v2 = parse(version2); + if (v1.prerelease.length || v2.prerelease.length) { + for (var key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return 'pre'+key; + } + } + } + return 'prerelease'; + } + for (var key in v1) { + if (key === 'major' || key === 'minor' || key === 'patch') { + if (v1[key] !== v2[key]) { + return key; + } + } + } + } +} + +exports.compareIdentifiers = compareIdentifiers; + +var numeric = /^[0-9]+$/; +function compareIdentifiers(a, b) { + var anum = numeric.test(a); + var bnum = numeric.test(b); + + if (anum && bnum) { + a = +a; + b = +b; + } + + return (anum && !bnum) ? -1 : + (bnum && !anum) ? 1 : + a < b ? -1 : + a > b ? 1 : + 0; +} + +exports.rcompareIdentifiers = rcompareIdentifiers; +function rcompareIdentifiers(a, b) { + return compareIdentifiers(b, a); +} + +exports.major = major; +function major(a, loose) { + return new SemVer(a, loose).major; +} + +exports.minor = minor; +function minor(a, loose) { + return new SemVer(a, loose).minor; +} + +exports.patch = patch; +function patch(a, loose) { + return new SemVer(a, loose).patch; +} + +exports.compare = compare; +function compare(a, b, loose) { + return new SemVer(a, loose).compare(b); +} + +exports.compareLoose = compareLoose; +function compareLoose(a, b) { + return compare(a, b, true); +} + +exports.rcompare = rcompare; +function rcompare(a, b, loose) { + return compare(b, a, loose); +} + +exports.sort = sort; +function sort(list, loose) { + return list.sort(function(a, b) { + return exports.compare(a, b, loose); + }); +} + +exports.rsort = rsort; +function rsort(list, loose) { + return list.sort(function(a, b) { + return exports.rcompare(a, b, loose); + }); +} + +exports.gt = gt; +function gt(a, b, loose) { + return compare(a, b, loose) > 0; +} + +exports.lt = lt; +function lt(a, b, loose) { + return compare(a, b, loose) < 0; +} + +exports.eq = eq; +function eq(a, b, loose) { + return compare(a, b, loose) === 0; +} + +exports.neq = neq; +function neq(a, b, loose) { + return compare(a, b, loose) !== 0; +} + +exports.gte = gte; +function gte(a, b, loose) { + return compare(a, b, loose) >= 0; +} + +exports.lte = lte; +function lte(a, b, loose) { + return compare(a, b, loose) <= 0; +} + +exports.cmp = cmp; +function cmp(a, op, b, loose) { + var ret; + switch (op) { + case '===': + if (typeof a === 'object') a = a.version; + if (typeof b === 'object') b = b.version; + ret = a === b; + break; + case '!==': + if (typeof a === 'object') a = a.version; + if (typeof b === 'object') b = b.version; + ret = a !== b; + break; + case '': case '=': case '==': ret = eq(a, b, loose); break; + case '!=': ret = neq(a, b, loose); break; + case '>': ret = gt(a, b, loose); break; + case '>=': ret = gte(a, b, loose); break; + case '<': ret = lt(a, b, loose); break; + case '<=': ret = lte(a, b, loose); break; + default: throw new TypeError('Invalid operator: ' + op); + } + return ret; +} + +exports.Comparator = Comparator; +function Comparator(comp, loose) { + if (comp instanceof Comparator) { + if (comp.loose === loose) + return comp; + else + comp = comp.value; + } + + if (!(this instanceof Comparator)) + return new Comparator(comp, loose); + + debug('comparator', comp, loose); + this.loose = loose; + this.parse(comp); + + if (this.semver === ANY) + this.value = ''; + else + this.value = this.operator + this.semver.version; + + debug('comp', this); +} + +var ANY = {}; +Comparator.prototype.parse = function(comp) { + var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; + var m = comp.match(r); + + if (!m) + throw new TypeError('Invalid comparator: ' + comp); + + this.operator = m[1]; + if (this.operator === '=') + this.operator = ''; + + // if it literally is just '>' or '' then allow anything. + if (!m[2]) + this.semver = ANY; + else + this.semver = new SemVer(m[2], this.loose); +}; + +Comparator.prototype.toString = function() { + return this.value; +}; + +Comparator.prototype.test = function(version) { + debug('Comparator.test', version, this.loose); + + if (this.semver === ANY) + return true; + + if (typeof version === 'string') + version = new SemVer(version, this.loose); + + return cmp(version, this.operator, this.semver, this.loose); +}; + + +exports.Range = Range; +function Range(range, loose) { + if ((range instanceof Range) && range.loose === loose) + return range; + + if (!(this instanceof Range)) + return new Range(range, loose); + + this.loose = loose; + + // First, split based on boolean or || + this.raw = range; + this.set = range.split(/\s*\|\|\s*/).map(function(range) { + return this.parseRange(range.trim()); + }, this).filter(function(c) { + // throw out any that are not relevant for whatever reason + return c.length; + }); + + if (!this.set.length) { + throw new TypeError('Invalid SemVer Range: ' + range); + } + + this.format(); +} + +Range.prototype.format = function() { + this.range = this.set.map(function(comps) { + return comps.join(' ').trim(); + }).join('||').trim(); + return this.range; +}; + +Range.prototype.toString = function() { + return this.range; +}; + +Range.prototype.parseRange = function(range) { + var loose = this.loose; + range = range.trim(); + debug('range', range, loose); + // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` + var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; + range = range.replace(hr, hyphenReplace); + debug('hyphen replace', range); + // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` + range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); + debug('comparator trim', range, re[COMPARATORTRIM]); + + // `~ 1.2.3` => `~1.2.3` + range = range.replace(re[TILDETRIM], tildeTrimReplace); + + // `^ 1.2.3` => `^1.2.3` + range = range.replace(re[CARETTRIM], caretTrimReplace); + + // normalize spaces + range = range.split(/\s+/).join(' '); + + // At this point, the range is completely trimmed and + // ready to be split into comparators. + + var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; + var set = range.split(' ').map(function(comp) { + return parseComparator(comp, loose); + }).join(' ').split(/\s+/); + if (this.loose) { + // in loose mode, throw out any that are not valid comparators + set = set.filter(function(comp) { + return !!comp.match(compRe); + }); + } + set = set.map(function(comp) { + return new Comparator(comp, loose); + }); + + return set; +}; + +// Mostly just for testing and legacy API reasons +exports.toComparators = toComparators; +function toComparators(range, loose) { + return new Range(range, loose).set.map(function(comp) { + return comp.map(function(c) { + return c.value; + }).join(' ').trim().split(' '); + }); +} + +// comprised of xranges, tildes, stars, and gtlt's at this point. +// already replaced the hyphen ranges +// turn into a set of JUST comparators. +function parseComparator(comp, loose) { + debug('comp', comp); + comp = replaceCarets(comp, loose); + debug('caret', comp); + comp = replaceTildes(comp, loose); + debug('tildes', comp); + comp = replaceXRanges(comp, loose); + debug('xrange', comp); + comp = replaceStars(comp, loose); + debug('stars', comp); + return comp; +} + +function isX(id) { + return !id || id.toLowerCase() === 'x' || id === '*'; +} + +// ~, ~> --> * (any, kinda silly) +// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 +// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 +// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 +// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 +// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 +function replaceTildes(comp, loose) { + return comp.trim().split(/\s+/).map(function(comp) { + return replaceTilde(comp, loose); + }).join(' '); +} + +function replaceTilde(comp, loose) { + var r = loose ? re[TILDELOOSE] : re[TILDE]; + return comp.replace(r, function(_, M, m, p, pr) { + debug('tilde', comp, _, M, m, p, pr); + var ret; + + if (isX(M)) + ret = ''; + else if (isX(m)) + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; + else if (isX(p)) + // ~1.2 == >=1.2.0 <1.3.0 + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; + else if (pr) { + debug('replaceTilde pr', pr); + if (pr.charAt(0) !== '-') + pr = '-' + pr; + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + (+m + 1) + '.0'; + } else + // ~1.2.3 == >=1.2.3 <1.3.0 + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0'; + + debug('tilde return', ret); + return ret; + }); +} + +// ^ --> * (any, kinda silly) +// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 +// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 +// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 +// ^1.2.3 --> >=1.2.3 <2.0.0 +// ^1.2.0 --> >=1.2.0 <2.0.0 +function replaceCarets(comp, loose) { + return comp.trim().split(/\s+/).map(function(comp) { + return replaceCaret(comp, loose); + }).join(' '); +} + +function replaceCaret(comp, loose) { + debug('caret', comp, loose); + var r = loose ? re[CARETLOOSE] : re[CARET]; + return comp.replace(r, function(_, M, m, p, pr) { + debug('caret', comp, _, M, m, p, pr); + var ret; + + if (isX(M)) + ret = ''; + else if (isX(m)) + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; + else if (isX(p)) { + if (M === '0') + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; + else + ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'; + } else if (pr) { + debug('replaceCaret pr', pr); + if (pr.charAt(0) !== '-') + pr = '-' + pr; + if (M === '0') { + if (m === '0') + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + m + '.' + (+p + 1); + else + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + M + '.' + (+m + 1) + '.0'; + } else + ret = '>=' + M + '.' + m + '.' + p + pr + + ' <' + (+M + 1) + '.0.0'; + } else { + debug('no pr'); + if (M === '0') { + if (m === '0') + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + m + '.' + (+p + 1); + else + ret = '>=' + M + '.' + m + '.' + p + + ' <' + M + '.' + (+m + 1) + '.0'; + } else + ret = '>=' + M + '.' + m + '.' + p + + ' <' + (+M + 1) + '.0.0'; + } + + debug('caret return', ret); + return ret; + }); +} + +function replaceXRanges(comp, loose) { + debug('replaceXRanges', comp, loose); + return comp.split(/\s+/).map(function(comp) { + return replaceXRange(comp, loose); + }).join(' '); +} + +function replaceXRange(comp, loose) { + comp = comp.trim(); + var r = loose ? re[XRANGELOOSE] : re[XRANGE]; + return comp.replace(r, function(ret, gtlt, M, m, p, pr) { + debug('xRange', comp, ret, gtlt, M, m, p, pr); + var xM = isX(M); + var xm = xM || isX(m); + var xp = xm || isX(p); + var anyX = xp; + + if (gtlt === '=' && anyX) + gtlt = ''; + + if (xM) { + if (gtlt === '>' || gtlt === '<') { + // nothing is allowed + ret = '<0.0.0'; + } else { + // nothing is forbidden + ret = '*'; + } + } else if (gtlt && anyX) { + // replace X with 0 + if (xm) + m = 0; + if (xp) + p = 0; + + if (gtlt === '>') { + // >1 => >=2.0.0 + // >1.2 => >=1.3.0 + // >1.2.3 => >= 1.2.4 + gtlt = '>='; + if (xm) { + M = +M + 1; + m = 0; + p = 0; + } else if (xp) { + m = +m + 1; + p = 0; + } + } else if (gtlt === '<=') { + // <=0.7.x is actually <0.8.0, since any 0.7.x should + // pass. Similarly, <=7.x is actually <8.0.0, etc. + gtlt = '<'; + if (xm) + M = +M + 1; + else + m = +m + 1; + } + + ret = gtlt + M + '.' + m + '.' + p; + } else if (xm) { + ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; + } else if (xp) { + ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; + } + + debug('xRange return', ret); + + return ret; + }); +} + +// Because * is AND-ed with everything else in the comparator, +// and '' means "any version", just remove the *s entirely. +function replaceStars(comp, loose) { + debug('replaceStars', comp, loose); + // Looseness is ignored here. star is always as loose as it gets! + return comp.trim().replace(re[STAR], ''); +} + +// This function is passed to string.replace(re[HYPHENRANGE]) +// M, m, patch, prerelease, build +// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 +// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do +// 1.2 - 3.4 => >=1.2.0 <3.5.0 +function hyphenReplace($0, + from, fM, fm, fp, fpr, fb, + to, tM, tm, tp, tpr, tb) { + + if (isX(fM)) + from = ''; + else if (isX(fm)) + from = '>=' + fM + '.0.0'; + else if (isX(fp)) + from = '>=' + fM + '.' + fm + '.0'; + else + from = '>=' + from; + + if (isX(tM)) + to = ''; + else if (isX(tm)) + to = '<' + (+tM + 1) + '.0.0'; + else if (isX(tp)) + to = '<' + tM + '.' + (+tm + 1) + '.0'; + else if (tpr) + to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; + else + to = '<=' + to; + + return (from + ' ' + to).trim(); +} + + +// if ANY of the sets match ALL of its comparators, then pass +Range.prototype.test = function(version) { + if (!version) + return false; + + if (typeof version === 'string') + version = new SemVer(version, this.loose); + + for (var i = 0; i < this.set.length; i++) { + if (testSet(this.set[i], version)) + return true; + } + return false; +}; + +function testSet(set, version) { + for (var i = 0; i < set.length; i++) { + if (!set[i].test(version)) + return false; + } + + if (version.prerelease.length) { + // Find the set of versions that are allowed to have prereleases + // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 + // That should allow `1.2.3-pr.2` to pass. + // However, `1.2.4-alpha.notready` should NOT be allowed, + // even though it's within the range set by the comparators. + for (var i = 0; i < set.length; i++) { + debug(set[i].semver); + if (set[i].semver === ANY) + continue; + + if (set[i].semver.prerelease.length > 0) { + var allowed = set[i].semver; + if (allowed.major === version.major && + allowed.minor === version.minor && + allowed.patch === version.patch) + return true; + } + } + + // Version has a -pre, but it's not one of the ones we like. + return false; + } + + return true; +} + +exports.satisfies = satisfies; +function satisfies(version, range, loose) { + try { + range = new Range(range, loose); + } catch (er) { + return false; + } + return range.test(version); +} + +exports.maxSatisfying = maxSatisfying; +function maxSatisfying(versions, range, loose) { + return versions.filter(function(version) { + return satisfies(version, range, loose); + }).sort(function(a, b) { + return rcompare(a, b, loose); + })[0] || null; +} + +exports.minSatisfying = minSatisfying; +function minSatisfying(versions, range, loose) { + return versions.filter(function(version) { + return satisfies(version, range, loose); + }).sort(function(a, b) { + return compare(a, b, loose); + })[0] || null; +} + +exports.validRange = validRange; +function validRange(range, loose) { + try { + // Return '*' instead of '' so that truthiness works. + // This will throw if it's invalid anyway + return new Range(range, loose).range || '*'; + } catch (er) { + return null; + } +} + +// Determine if version is less than all the versions possible in the range +exports.ltr = ltr; +function ltr(version, range, loose) { + return outside(version, range, '<', loose); +} + +// Determine if version is greater than all the versions possible in the range. +exports.gtr = gtr; +function gtr(version, range, loose) { + return outside(version, range, '>', loose); +} + +exports.outside = outside; +function outside(version, range, hilo, loose) { + version = new SemVer(version, loose); + range = new Range(range, loose); + + var gtfn, ltefn, ltfn, comp, ecomp; + switch (hilo) { + case '>': + gtfn = gt; + ltefn = lte; + ltfn = lt; + comp = '>'; + ecomp = '>='; + break; + case '<': + gtfn = lt; + ltefn = gte; + ltfn = gt; + comp = '<'; + ecomp = '<='; + break; + default: + throw new TypeError('Must provide a hilo val of "<" or ">"'); + } + + // If it satisifes the range it is not outside + if (satisfies(version, range, loose)) { + return false; + } + + // From now on, variable terms are as if we're in "gtr" mode. + // but note that everything is flipped for the "ltr" function. + + for (var i = 0; i < range.set.length; ++i) { + var comparators = range.set[i]; + + var high = null; + var low = null; + + comparators.forEach(function(comparator) { + if (comparator.semver === ANY) { + comparator = new Comparator('>=0.0.0') + } + high = high || comparator; + low = low || comparator; + if (gtfn(comparator.semver, high.semver, loose)) { + high = comparator; + } else if (ltfn(comparator.semver, low.semver, loose)) { + low = comparator; + } + }); + + // If the edge version comparator has a operator then our version + // isn't outside it + if (high.operator === comp || high.operator === ecomp) { + return false; + } + + // If the lowest version comparator has an operator and our version + // is less than it then it isn't higher than the range + if ((!low.operator || low.operator === comp) && + ltefn(version, low.semver)) { + return false; + } else if (low.operator === ecomp && ltfn(version, low.semver)) { + return false; + } + } + return true; +} + +exports.prerelease = prerelease; +function prerelease(version, loose) { + var parsed = parse(version, loose); + return (parsed && parsed.prerelease.length) ? parsed.prerelease : null; +} diff --git a/node_modules/node-gyp/node_modules/tar/.travis.yml b/node_modules/npm-lifecycle/node_modules/tar/.travis.yml similarity index 100% rename from node_modules/node-gyp/node_modules/tar/.travis.yml rename to node_modules/npm-lifecycle/node_modules/tar/.travis.yml diff --git a/node_modules/node-gyp/node_modules/tar/LICENSE b/node_modules/npm-lifecycle/node_modules/tar/LICENSE similarity index 100% rename from node_modules/node-gyp/node_modules/tar/LICENSE rename to node_modules/npm-lifecycle/node_modules/tar/LICENSE diff --git a/node_modules/node-gyp/node_modules/tar/README.md b/node_modules/npm-lifecycle/node_modules/tar/README.md similarity index 100% rename from node_modules/node-gyp/node_modules/tar/README.md rename to node_modules/npm-lifecycle/node_modules/tar/README.md diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/base.css b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/base.css new file mode 100644 index 0000000000000..417c7adc95f1d --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/base.css @@ -0,0 +1,212 @@ +body, html { + margin:0; padding: 0; + height: 100%; +} +body { + font-family: Helvetica Neue, Helvetica, Arial; + font-size: 14px; + color:#333; +} +.small { font-size: 12px; } +*, *:after, *:before { + -webkit-box-sizing:border-box; + -moz-box-sizing:border-box; + box-sizing:border-box; + } +h1 { font-size: 20px; margin: 0;} +h2 { font-size: 14px; } +pre { + font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; + margin: 0; + padding: 0; + -moz-tab-size: 2; + -o-tab-size: 2; + tab-size: 2; +} +a { color:#0074D9; text-decoration:none; } +a:hover { text-decoration:underline; } +.strong { font-weight: bold; } +.space-top1 { padding: 10px 0 0 0; } +.pad2y { padding: 20px 0; } +.pad1y { padding: 10px 0; } +.pad2x { padding: 0 20px; } +.pad2 { padding: 20px; } +.pad1 { padding: 10px; } +.space-left2 { padding-left:55px; } +.space-right2 { padding-right:20px; } +.center { text-align:center; } +.clearfix { display:block; } +.clearfix:after { + content:''; + display:block; + height:0; + clear:both; + visibility:hidden; + } +.fl { float: left; } +@media only screen and (max-width:640px) { + .col3 { width:100%; max-width:100%; } + .hide-mobile { display:none!important; } +} + +.quiet { + color: #7f7f7f; + color: rgba(0,0,0,0.5); +} +.quiet a { opacity: 0.7; } + +.fraction { + font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; + font-size: 10px; + color: #555; + background: #E8E8E8; + padding: 4px 5px; + border-radius: 3px; + vertical-align: middle; +} + +div.path a:link, div.path a:visited { color: #333; } +table.coverage { + border-collapse: collapse; + margin: 10px 0 0 0; + padding: 0; +} + +table.coverage td { + margin: 0; + padding: 0; + vertical-align: top; +} +table.coverage td.line-count { + text-align: right; + padding: 0 5px 0 20px; +} +table.coverage td.line-coverage { + text-align: right; + padding-right: 10px; + min-width:20px; +} + +table.coverage td span.cline-any { + display: inline-block; + padding: 0 5px; + width: 100%; +} +.missing-if-branch { + display: inline-block; + margin-right: 5px; + border-radius: 3px; + position: relative; + padding: 0 4px; + background: #333; + color: yellow; +} + +.skip-if-branch { + display: none; + margin-right: 10px; + position: relative; + padding: 0 4px; + background: #ccc; + color: white; +} +.missing-if-branch .typ, .skip-if-branch .typ { + color: inherit !important; +} +.coverage-summary { + border-collapse: collapse; + width: 100%; +} +.coverage-summary tr { border-bottom: 1px solid #bbb; } +.keyline-all { border: 1px solid #ddd; } +.coverage-summary td, .coverage-summary th { padding: 10px; } +.coverage-summary tbody { border: 1px solid #bbb; } +.coverage-summary td { border-right: 1px solid #bbb; } +.coverage-summary td:last-child { border-right: none; } +.coverage-summary th { + text-align: left; + font-weight: normal; + white-space: nowrap; +} +.coverage-summary th.file { border-right: none !important; } +.coverage-summary th.pct { } +.coverage-summary th.pic, +.coverage-summary th.abs, +.coverage-summary td.pct, +.coverage-summary td.abs { text-align: right; } +.coverage-summary td.file { white-space: nowrap; } +.coverage-summary td.pic { min-width: 120px !important; } +.coverage-summary tfoot td { } + +.coverage-summary .sorter { + height: 10px; + width: 7px; + display: inline-block; + margin-left: 0.5em; + background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; +} +.coverage-summary .sorted .sorter { + background-position: 0 -20px; +} +.coverage-summary .sorted-desc .sorter { + background-position: 0 -10px; +} +.status-line { height: 10px; } +/* dark red */ +.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } +.low .chart { border:1px solid #C21F39 } +/* medium red */ +.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } +/* light red */ +.low, .cline-no { background:#FCE1E5 } +/* light green */ +.high, .cline-yes { background:rgb(230,245,208) } +/* medium green */ +.cstat-yes { background:rgb(161,215,106) } +/* dark green */ +.status-line.high, .high .cover-fill { background:rgb(77,146,33) } +.high .chart { border:1px solid rgb(77,146,33) } + + +.medium .chart { border:1px solid #666; } +.medium .cover-fill { background: #666; } + +.cbranch-no { background: yellow !important; color: #111; } + +.cstat-skip { background: #ddd; color: #111; } +.fstat-skip { background: #ddd; color: #111 !important; } +.cbranch-skip { background: #ddd !important; color: #111; } + +span.cline-neutral { background: #eaeaea; } +.medium { background: #eaeaea; } + +.cover-fill, .cover-empty { + display:inline-block; + height: 12px; +} +.chart { + line-height: 0; +} +.cover-empty { + background: white; +} +.cover-full { + border-right: none !important; +} +pre.prettyprint { + border: none !important; + padding: 0 !important; + margin: 0 !important; +} +.com { color: #999 !important; } +.ignore-none { color: #999; font-weight: normal; } + +.wrapper { + min-height: 100%; + height: auto !important; + height: 100%; + margin: 0 auto -48px; +} +.footer, .push { + height: 48px; +} diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/index.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/index.html new file mode 100644 index 0000000000000..27224804e1082 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/index.html @@ -0,0 +1,106 @@ + + + + Code coverage report for All files + + + + + + + +
    +
    +

    + All files +

    +
    +
    + 99.94% + Statements + 1795/1796 +
    +
    + 99.67% + Branches + 1224/1228 +
    +
    + 100% + Functions + 271/271 +
    +
    + 99.94% + Lines + 1748/1749 +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FileStatementsBranchesFunctionsLines
    tar
    100%13/13100%0/0100%0/0100%13/13
    tar/lib
    99.94%1782/178399.67%1224/1228100%271/27199.94%1735/1736
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.css b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.css new file mode 100644 index 0000000000000..b317a7cda31a4 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.css @@ -0,0 +1 @@ +.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.js b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.js new file mode 100644 index 0000000000000..ef51e03866898 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.js @@ -0,0 +1 @@ +window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/sort-arrow-sprite.png b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/sort-arrow-sprite.png new file mode 100644 index 0000000000000000000000000000000000000000..03f704a609c6fd0dbfdac63466a7d7c958b5cbf3 GIT binary patch literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jii$m5978H@?Fn+^JD|Y9yzj{W`447Gxa{7*dM7nnnD-Lb z6^}Hx2)'; + } + } + return cols; + } + // attaches a data attribute to every tr element with an object + // of data values keyed by column name + function loadRowData(tableRow) { + var tableCols = tableRow.querySelectorAll('td'), + colNode, + col, + data = {}, + i, + val; + for (i = 0; i < tableCols.length; i += 1) { + colNode = tableCols[i]; + col = cols[i]; + val = colNode.getAttribute('data-value'); + if (col.type === 'number') { + val = Number(val); + } + data[col.key] = val; + } + return data; + } + // loads all row data + function loadData() { + var rows = getTableBody().querySelectorAll('tr'), + i; + + for (i = 0; i < rows.length; i += 1) { + rows[i].data = loadRowData(rows[i]); + } + } + // sorts the table using the data for the ith column + function sortByIndex(index, desc) { + var key = cols[index].key, + sorter = function (a, b) { + a = a.data[key]; + b = b.data[key]; + return a < b ? -1 : a > b ? 1 : 0; + }, + finalSorter = sorter, + tableBody = document.querySelector('.coverage-summary tbody'), + rowNodes = tableBody.querySelectorAll('tr'), + rows = [], + i; + + if (desc) { + finalSorter = function (a, b) { + return -1 * sorter(a, b); + }; + } + + for (i = 0; i < rowNodes.length; i += 1) { + rows.push(rowNodes[i]); + tableBody.removeChild(rowNodes[i]); + } + + rows.sort(finalSorter); + + for (i = 0; i < rows.length; i += 1) { + tableBody.appendChild(rows[i]); + } + } + // removes sort indicators for current column being sorted + function removeSortIndicators() { + var col = getNthColumn(currentSort.index), + cls = col.className; + + cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); + col.className = cls; + } + // adds sort indicators for current column being sorted + function addSortIndicators() { + getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted'; + } + // adds event listeners for all sorter widgets + function enableUI() { + var i, + el, + ithSorter = function ithSorter(i) { + var col = cols[i]; + + return function () { + var desc = col.defaultDescSort; + + if (currentSort.index === i) { + desc = !currentSort.desc; + } + sortByIndex(i, desc); + removeSortIndicators(); + currentSort.index = i; + currentSort.desc = desc; + addSortIndicators(); + }; + }; + for (i =0 ; i < cols.length; i += 1) { + if (cols[i].sortable) { + // add the click event handler on the th so users + // dont have to click on those tiny arrows + el = getNthColumn(i).querySelector('.sorter').parentElement; + if (el.addEventListener) { + el.addEventListener('click', ithSorter(i)); + } else { + el.attachEvent('onclick', ithSorter(i)); + } + } + } + } + // adds sorting functionality to the UI + return function () { + if (!getTable()) { + return; + } + cols = loadColumns(); + loadData(cols); + addSortIndicators(); + enableUI(); + }; +})(); + +window.addEventListener('load', addSorting); diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.html new file mode 100644 index 0000000000000..9c917bdeb14ba --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.html @@ -0,0 +1,93 @@ + + + + Code coverage report for tar + + + + + + + +
    +
    +

    + All files tar +

    +
    +
    + 100% + Statements + 13/13 +
    +
    + 100% + Branches + 0/0 +
    +
    + 100% + Functions + 0/0 +
    +
    + 100% + Lines + 13/13 +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FileStatementsBranchesFunctionsLines
    index.js
    100%13/13100%0/0100%0/0100%13/13
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.js.html new file mode 100644 index 0000000000000..f04c992346340 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.js.html @@ -0,0 +1,119 @@ + + + + Code coverage report for tar/index.js + + + + + + + +
    +
    +

    + All files / tar index.js +

    +
    +
    + 100% + Statements + 13/13 +
    +
    + 100% + Branches + 0/0 +
    +
    + 100% + Functions + 0/0 +
    +
    + 100% + Lines + 13/13 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19  +  +  +1x +1x +1x +1x +1x +  +  +1x +1x +1x +1x +1x +1x +1x +1x + 
    'use strict'
    + 
    +// high-level commands
    +exports.c = exports.create = require('./lib/create.js')
    +exports.r = exports.replace = require('./lib/replace.js')
    +exports.t = exports.list = require('./lib/list.js')
    +exports.u = exports.update = require('./lib/update.js')
    +exports.x = exports.extract = require('./lib/extract.js')
    + 
    +// classes
    +exports.Pack = require('./lib/pack.js')
    +exports.Unpack = require('./lib/unpack.js')
    +exports.Parse = require('./lib/parse.js')
    +exports.ReadEntry = require('./lib/read-entry.js')
    +exports.WriteEntry = require('./lib/write-entry.js')
    +exports.Header = require('./lib/header.js')
    +exports.Pax = require('./lib/pax.js')
    +exports.types = require('./lib/types.js')
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/create.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/create.js.html new file mode 100644 index 0000000000000..2f01c7e302a1e --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/create.js.html @@ -0,0 +1,380 @@ + + + + Code coverage report for tar/lib/create.js + + + + + + + +
    +
    +

    + All files / tar/lib create.js +

    +
    +
    + 100% + Statements + 59/59 +
    +
    + 100% + Branches + 35/35 +
    +
    + 100% + Functions + 12/12 +
    +
    + 100% + Lines + 59/59 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106  +  +  +2x +  +2x +2x +2x +2x +2x +  +2x +15x +1x +  +15x +1x +  +15x +2x +  +13x +  +13x +  +13x +1x +  +12x +1x +  +11x +  +  +  +  +  +2x +4x +4x +  +  +4x +4x +  +  +2x +4x +4x +  +  +4x +  +4x +4x +4x +4x +  +  +4x +  +4x +  +  +2x +5x +7x +3x +  +  +  +7x +  +  +4x +  +4x +  +  +2x +9x +8x +8x +3x +  +  +7x +3x +  +5x +  +6x +  +  +2x +1x +1x +1x +  +  +2x +2x +2x +2x +  + 
    'use strict'
    + 
    +// tar -c
    +const hlo = require('./high-level-opt.js')
    + 
    +const Pack = require('./pack.js')
    +const fs = require('fs')
    +const fsm = require('fs-minipass')
    +const t = require('./list.js')
    +const path = require('path')
    + 
    +const c = module.exports = (opt_, files, cb) => {
    +  if (typeof files === 'function')
    +    cb = files
    + 
    +  if (Array.isArray(opt_))
    +    files = opt_, opt_ = {}
    + 
    +  if (!files || !Array.isArray(files) || !files.length)
    +    throw new TypeError('no files or directories specified')
    + 
    +  files = Array.from(files)
    + 
    +  const opt = hlo(opt_)
    + 
    +  if (opt.sync && typeof cb === 'function')
    +    throw new TypeError('callback not supported for sync tar functions')
    + 
    +  if (!opt.file && typeof cb === 'function')
    +    throw new TypeError('callback only supported with file option')
    + 
    +  return opt.file && opt.sync ? createFileSync(opt, files)
    +    : opt.file ? createFile(opt, files, cb)
    +    : opt.sync ? createSync(opt, files)
    +    : create(opt, files)
    +}
    + 
    +const createFileSync = (opt, files) => {
    +  const p = new Pack.Sync(opt)
    +  const stream = new fsm.WriteStreamSync(opt.file, {
    +    mode: opt.mode || 0o666
    +  })
    +  p.pipe(stream)
    +  addFilesSync(p, files)
    +}
    + 
    +const createFile = (opt, files, cb) => {
    +  const p = new Pack(opt)
    +  const stream = new fsm.WriteStream(opt.file, {
    +    mode: opt.mode || 0o666
    +  })
    +  p.pipe(stream)
    + 
    +  const promise = new Promise((res, rej) => {
    +    stream.on('error', rej)
    +    stream.on('close', res)
    +    p.on('error', rej)
    +  })
    + 
    +  addFilesAsync(p, files)
    + 
    +  return cb ? promise.then(cb, cb) : promise
    +}
    + 
    +const addFilesSync = (p, files) => {
    +  files.forEach(file => {
    +    if (file.charAt(0) === '@')
    +      t({
    +        file: path.resolve(p.cwd, file.substr(1)),
    +        sync: true,
    +        noResume: true,
    +        onentry: entry => p.add(entry)
    +      })
    +    else
    +      p.add(file)
    +  })
    +  p.end()
    +}
    + 
    +const addFilesAsync = (p, files) => {
    +  while (files.length) {
    +    const file = files.shift()
    +    if (file.charAt(0) === '@')
    +      return t({
    +        file: path.resolve(p.cwd, file.substr(1)),
    +        noResume: true,
    +        onentry: entry => p.add(entry)
    +      }).then(_ => addFilesAsync(p, files))
    +    else
    +      p.add(file)
    +  }
    +  p.end()
    +}
    + 
    +const createSync = (opt, files) => {
    +  const p = new Pack.Sync(opt)
    +  addFilesSync(p, files)
    +  return p
    +}
    + 
    +const create = (opt, files) => {
    +  const p = new Pack(opt)
    +  addFilesAsync(p, files)
    +  return p
    +}
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/extract.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/extract.js.html new file mode 100644 index 0000000000000..96245c73d9f66 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/extract.js.html @@ -0,0 +1,401 @@ + + + + Code coverage report for tar/lib/extract.js + + + + + + + +
    +
    +

    + All files / tar/lib extract.js +

    +
    +
    + 100% + Statements + 61/61 +
    +
    + 100% + Branches + 45/45 +
    +
    + 100% + Functions + 12/12 +
    +
    + 100% + Lines + 60/60 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113  +  +  +2x +2x +2x +2x +2x +  +2x +21x +1x +20x +1x +  +21x +3x +  +21x +13x +  +8x +  +21x +  +21x +2x +  +19x +1x +  +18x +7x +  +18x +  +  +  +  +  +  +  +2x +13x +7x +  +7x +87x +87x +  +  +  +87x +87x +  +  +7x +9x +9x +  +  +2x +6x +  +6x +6x +  +6x +  +  +5x +5x +  +  +  +4x +  +  +2x +9x +9x +  +9x +9x +9x +9x +  +  +  +9x +9x +1x +  +8x +  +  +  +8x +8x +  +  +  +9x +  +  +2x +1x +  +  +2x +2x +  + 
    'use strict'
    + 
    +// tar -x
    +const hlo = require('./high-level-opt.js')
    +const Unpack = require('./unpack.js')
    +const fs = require('fs')
    +const fsm = require('fs-minipass')
    +const path = require('path')
    + 
    +const x = module.exports = (opt_, files, cb) => {
    +  if (typeof opt_ === 'function')
    +    cb = opt_, files = null, opt_ = {}
    +  else if (Array.isArray(opt_))
    +    files = opt_, opt_ = {}
    + 
    +  if (typeof files === 'function')
    +    cb = files, files = null
    + 
    +  if (!files)
    +    files = []
    +  else
    +    files = Array.from(files)
    + 
    +  const opt = hlo(opt_)
    + 
    +  if (opt.sync && typeof cb === 'function')
    +    throw new TypeError('callback not supported for sync tar functions')
    + 
    +  if (!opt.file && typeof cb === 'function')
    +    throw new TypeError('callback only supported with file option')
    + 
    +  if (files.length)
    +    filesFilter(opt, files)
    + 
    +  return opt.file && opt.sync ? extractFileSync(opt)
    +    : opt.file ? extractFile(opt, cb)
    +    : opt.sync ? extractSync(opt)
    +    : extract(opt)
    +}
    + 
    +// construct a filter that limits the file entries listed
    +// include child entries if a dir is included
    +const filesFilter = (opt, files) => {
    +  const map = new Map(files.map(f => [f.replace(/\/+$/, ''), true]))
    +  const filter = opt.filter
    + 
    +  const mapHas = (file, r) => {
    +    const root = r || path.parse(file).root || '.'
    +    const ret = file === root ? false
    +      : map.has(file) ? map.get(file)
    +      : mapHas(path.dirname(file), root)
    + 
    +    map.set(file, ret)
    +    return ret
    +  }
    + 
    +  opt.filter = filter
    +    ? (file, entry) => filter(file, entry) && mapHas(file.replace(/\/+$/, ''))
    +    : file => mapHas(file.replace(/\/+$/, ''))
    +}
    + 
    +const extractFileSync = opt => {
    +  const u = new Unpack.Sync(opt)
    + 
    +  const file = opt.file
    +  let threw = true
    +  let fd
    +  const stat = fs.statSync(file)
    +  // This trades a zero-byte read() syscall for a stat
    +  // However, it will usually result in less memory allocation
    +  const readSize = opt.maxReadSize || 16*1024*1024
    +  const stream = new fsm.ReadStreamSync(file, {
    +    readSize: readSize,
    +    size: stat.size
    +  })
    +  stream.pipe(u)
    +}
    + 
    +const extractFile = (opt, cb) => {
    +  const u = new Unpack(opt)
    +  const readSize = opt.maxReadSize || 16*1024*1024
    + 
    +  const file = opt.file
    +  const p = new Promise((resolve, reject) => {
    +    u.on('error', reject)
    +    u.on('close', resolve)
    + 
    +    // This trades a zero-byte read() syscall for a stat
    +    // However, it will usually result in less memory allocation
    +    fs.stat(file, (er, stat) => {
    +      if (er)
    +        reject(er)
    +      else {
    +        const stream = new fsm.ReadStream(file, {
    +          readSize: readSize,
    +          size: stat.size
    +        })
    +        stream.on('error', reject)
    +        stream.pipe(u)
    +      }
    +    })
    +  })
    +  return cb ? p.then(cb, cb) : p
    +}
    + 
    +const extractSync = opt => {
    +  return new Unpack.Sync(opt)
    +}
    + 
    +const extract = opt => {
    +  return new Unpack(opt)
    +}
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/header.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/header.js.html new file mode 100644 index 0000000000000..69770d09869e7 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/header.js.html @@ -0,0 +1,881 @@ + + + + Code coverage report for tar/lib/header.js + + + + + + + +
    +
    +

    + All files / tar/lib header.js +

    +
    +
    + 100% + Statements + 161/161 +
    +
    + 100% + Branches + 120/120 +
    +
    + 100% + Functions + 20/20 +
    +
    + 100% + Lines + 159/159 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273  +  +  +  +  +  +13x +13x +13x +  +13x +  +  +  +13121x +13121x +13121x +  +13121x +13121x +13121x +13121x +13121x +13121x +13121x +13121x +13121x +13121x +13121x +13121x +13121x +13121x +13121x +13121x +  +13121x +6393x +6728x +6726x +  +  +  +6393x +2795x +  +6393x +1x +  +6392x +6392x +6392x +6392x +6392x +6392x +6392x +  +  +6392x +6392x +1990x +6392x +2x +  +  +  +  +  +  +6392x +1594x +  +6392x +6392x +4275x +4275x +4275x +4275x +4275x +  +2x +2x +  +4273x +4273x +295x +4273x +4273x +  +  +  +6392x +6392x +946016x +  +6392x +2275552x +  +6392x +6392x +1860x +  +  +  +6719x +6600x +6600x +  +  +6719x +6717x +  +6719x +1x +  +6718x +6718x +6718x +6718x +6718x +  +6718x +6718x +6718x +6718x +6718x +6718x +6718x +6718x +6718x +6718x +6718x +6718x +6718x +6718x +6718x +2x +  +6716x +6716x +6716x +  +  +6718x +6718x +994264x +  +6718x +2391608x +  +6718x +6718x +6718x +  +6718x +  +  +  +6728x +73451x +66740x +  +  +  +  +8178x +  +  +  +4x +  +  +  +6723x +6719x +  +4x +  +  +  +13x +6718x +6718x +6718x +  +6718x +  +6718x +6683x +  +  +35x +35x +  +35x +  +49x +  +21x +  +  +28x +  +13x +  +  +  +15x +15x +  +  +  +  +35x +1x +  +6718x +  +  +13x +32001x +  +13x +14938x +  +14938x +  +13x +55448x +  +  +55411x +  +13x +55411x +  +  +  +  +13x +  +  +  +  +13x +66910x +  +  +  +  +13x +66615x +  +13x +66615x +  +13x +66615x +  +  +13x +20150x +  +  +  +13x +  +13x +40308x +  +  +  +13x + 
    'use strict'
    +// parse a 512-byte header block to a data object, or vice-versa
    +// encode returns `true` if a pax extended header is needed, because
    +// the data could not be faithfully encoded in a simple header.
    +// (Also, check header.needPax to see if it needs a pax header.)
    + 
    +const types = require('./types.js')
    +const pathModule = require('path')
    +const large = require('./large-numbers.js')
    + 
    +const TYPE = Symbol('type')
    + 
    +class Header {
    +  constructor (data, off) {
    +    this.cksumValid = false
    +    this.needPax = false
    +    this.nullBlock = false
    + 
    +    this.block = null
    +    this.path = null
    +    this.mode = null
    +    this.uid = null
    +    this.gid = null
    +    this.size = null
    +    this.mtime = null
    +    this.cksum = null
    +    this[TYPE] = '0'
    +    this.linkpath = null
    +    this.uname = null
    +    this.gname = null
    +    this.devmaj = 0
    +    this.devmin = 0
    +    this.atime = null
    +    this.ctime = null
    + 
    +    if (Buffer.isBuffer(data)) {
    +      this.decode(data, off || 0)
    +    } else if (data)
    +      this.set(data)
    +  }
    + 
    +  decode (buf, off) {
    +    if (!off)
    +      off = 0
    + 
    +    if (!buf || !(buf.length >= off + 512))
    +      throw new Error('need 512 bytes for header')
    + 
    +    this.path = decString(buf, off, 100)
    +    this.mode = decNumber(buf, off + 100, 8)
    +    this.uid = decNumber(buf, off + 108, 8)
    +    this.gid = decNumber(buf, off + 116, 8)
    +    this.size = decNumber(buf, off + 124, 12)
    +    this.mtime = decDate(buf, off + 136, 12)
    +    this.cksum = decNumber(buf, off + 148, 12)
    + 
    +    // old tar versions marked dirs as a file with a trailing /
    +    this[TYPE] = decString(buf, off + 156, 1)
    +    if (this[TYPE] === '')
    +      this[TYPE] = '0'
    +    if (this[TYPE] === '0' && this.path.substr(-1) === '/')
    +      this[TYPE] = '5'
    + 
    +    // tar implementations sometimes incorrectly put the stat(dir).size
    +    // as the size in the tarball, even though Directory entries are
    +    // not able to have any body at all.  In the very rare chance that
    +    // it actually DOES have a body, we weren't going to do anything with
    +    // it anyway, and it'll just be a warning about an invalid header.
    +    if (this[TYPE] === '5')
    +      this.size = 0
    + 
    +    this.linkpath = decString(buf, off + 157, 100)
    +    if (buf.slice(off + 257, off + 265).toString() === 'ustar\u000000') {
    +      this.uname = decString(buf, off + 265, 32)
    +      this.gname = decString(buf, off + 297, 32)
    +      this.devmaj = decNumber(buf, off + 329, 8)
    +      this.devmin = decNumber(buf, off + 337, 8)
    +      if (buf[off + 475] !== 0) {
    +        // definitely a prefix, definitely >130 chars.
    +        const prefix = decString(buf, off + 345, 155)
    +        this.path = prefix + '/' + this.path
    +      } else {
    +        const prefix = decString(buf, off + 345, 130)
    +        if (prefix)
    +          this.path = prefix + '/' + this.path
    +        this.atime = decDate(buf, off + 476, 12)
    +        this.ctime = decDate(buf, off + 488, 12)
    +      }
    +    }
    + 
    +    let sum = 8 * 0x20
    +    for (let i = off; i < off + 148; i++) {
    +      sum += buf[i]
    +    }
    +    for (let i = off + 156; i < off + 512; i++) {
    +      sum += buf[i]
    +    }
    +    this.cksumValid = sum === this.cksum
    +    if (this.cksum === null && sum === 8 * 0x20)
    +      this.nullBlock = true
    +  }
    + 
    +  encode (buf, off) {
    +    if (!buf) {
    +      buf = this.block = Buffer.alloc(512)
    +      off = 0
    +    }
    + 
    +    if (!off)
    +      off = 0
    + 
    +    if (!(buf.length >= off + 512))
    +      throw new Error('need 512 bytes for header')
    + 
    +    const prefixSize = this.ctime || this.atime ? 130 : 155
    +    const split = splitPrefix(this.path || '', prefixSize)
    +    const path = split[0]
    +    const prefix = split[1]
    +    this.needPax = split[2]
    + 
    +    this.needPax = encString(buf, off, 100, path) || this.needPax
    +    this.needPax = encNumber(buf, off + 100, 8, this.mode) || this.needPax
    +    this.needPax = encNumber(buf, off + 108, 8, this.uid) || this.needPax
    +    this.needPax = encNumber(buf, off + 116, 8, this.gid) || this.needPax
    +    this.needPax = encNumber(buf, off + 124, 12, this.size) || this.needPax
    +    this.needPax = encDate(buf, off + 136, 12, this.mtime) || this.needPax
    +    buf[off + 156] = this[TYPE].charCodeAt(0)
    +    this.needPax = encString(buf, off + 157, 100, this.linkpath) || this.needPax
    +    buf.write('ustar\u000000', off + 257, 8)
    +    this.needPax = encString(buf, off + 265, 32, this.uname) || this.needPax
    +    this.needPax = encString(buf, off + 297, 32, this.gname) || this.needPax
    +    this.needPax = encNumber(buf, off + 329, 8, this.devmaj) || this.needPax
    +    this.needPax = encNumber(buf, off + 337, 8, this.devmin) || this.needPax
    +    this.needPax = encString(buf, off + 345, prefixSize, prefix) || this.needPax
    +    if (buf[off + 475] !== 0)
    +      this.needPax = encString(buf, off + 345, 155, prefix) || this.needPax
    +    else {
    +      this.needPax = encString(buf, off + 345, 130, prefix) || this.needPax
    +      this.needPax = encDate(buf, off + 476, 12, this.atime) || this.needPax
    +      this.needPax = encDate(buf, off + 488, 12, this.ctime) || this.needPax
    +    }
    + 
    +    let sum = 8 * 0x20
    +    for (let i = off; i < off + 148; i++) {
    +      sum += buf[i]
    +    }
    +    for (let i = off + 156; i < off + 512; i++) {
    +      sum += buf[i]
    +    }
    +    this.cksum = sum
    +    encNumber(buf, off + 148, 8, this.cksum)
    +    this.cksumValid = true
    + 
    +    return this.needPax
    +  }
    + 
    +  set (data) {
    +    for (let i in data) {
    +      if (data[i] !== null && data[i] !== undefined)
    +        this[i] = data[i]
    +    }
    +  }
    + 
    +  get type () {
    +    return types.name.get(this[TYPE]) || this[TYPE]
    +  }
    + 
    +  get typeKey () {
    +    return this[TYPE]
    +  }
    + 
    +  set type (type) {
    +    if (types.code.has(type))
    +      this[TYPE] = types.code.get(type)
    +    else
    +      this[TYPE] = type
    +  }
    +}
    + 
    +const splitPrefix = (p, prefixSize) => {
    +  const pathSize = 100
    +  let pp = p
    +  let prefix = ''
    +  let ret
    +  const root = pathModule.parse(p).root || '.'
    + 
    +  if (Buffer.byteLength(pp) < pathSize)
    +    ret = [pp, prefix, false]
    +  else {
    +    // first set prefix to the dir, and path to the base
    +    prefix = pathModule.dirname(pp)
    +    pp = pathModule.basename(pp)
    + 
    +    do {
    +      // both fit!
    +      if (Buffer.byteLength(pp) <= pathSize &&
    +          Buffer.byteLength(prefix) <= prefixSize)
    +        ret = [pp, prefix, false]
    + 
    +      // prefix fits in prefix, but path doesn't fit in path
    +      else if (Buffer.byteLength(pp) > pathSize &&
    +          Buffer.byteLength(prefix) <= prefixSize)
    +        ret = [pp.substr(0, pathSize - 1), prefix, true]
    + 
    +      else {
    +        // make path take a bit from prefix
    +        pp = pathModule.join(pathModule.basename(prefix), pp)
    +        prefix = pathModule.dirname(prefix)
    +      }
    +    } while (prefix !== root && !ret)
    + 
    +    // at this point, found no resolution, just truncate
    +    if (!ret)
    +      ret = [p.substr(0, pathSize - 1), '', true]
    +  }
    +  return ret
    +}
    + 
    +const decString = (buf, off, size) =>
    +  buf.slice(off, off + size).toString('utf8').replace(/\0.*/, '')
    + 
    +const decDate = (buf, off, size) =>
    +  numToDate(decNumber(buf, off, size))
    + 
    +const numToDate = num => num === null ? null : new Date(num * 1000)
    + 
    +const decNumber = (buf, off, size) =>
    +  buf[off] & 0x80 ? large.parse(buf.slice(off, off + size))
    +    : decSmallNumber(buf, off, size)
    + 
    +const nanNull = value => isNaN(value) ? null : value
    + 
    +const decSmallNumber = (buf, off, size) =>
    +  nanNull(parseInt(
    +    buf.slice(off, off + size)
    +      .toString('utf8').replace(/\0.*$/, '').trim(), 8))
    + 
    +// the maximum encodable as a null-terminated octal, by field size
    +const MAXNUM = {
    +  12: 0o77777777777,
    +  8 : 0o7777777
    +}
    + 
    +const encNumber = (buf, off, size, number) =>
    +  number === null ? false :
    +  number > MAXNUM[size] || number < 0
    +    ? (large.encode(number, buf.slice(off, off + size)), true)
    +    : (encSmallNumber(buf, off, size, number), false)
    + 
    +const encSmallNumber = (buf, off, size, number) =>
    +  buf.write(octalString(number, size), off, size, 'ascii')
    + 
    +const octalString = (number, size) =>
    +  padOctal(Math.floor(number).toString(8), size)
    + 
    +const padOctal = (string, size) =>
    +  (string.length === size - 1 ? string
    +  : new Array(size - string.length - 1).join('0') + string + ' ') + '\0'
    + 
    +const encDate = (buf, off, size, date) =>
    +  date === null ? false :
    +  encNumber(buf, off, size, date.getTime() / 1000)
    + 
    +// enough to fill the longest string we've got
    +const NULLS = new Array(156).join('\0')
    +// pad with nulls, return true if it's longer or non-ascii
    +const encString = (buf, off, size, string) =>
    +  string === null ? false :
    +  (buf.write(string + NULLS, off, size, 'utf8'),
    +   string.length !== Buffer.byteLength(string) || string.length > size)
    + 
    +module.exports = Header
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/high-level-opt.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/high-level-opt.js.html new file mode 100644 index 0000000000000..0a59596f75769 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/high-level-opt.js.html @@ -0,0 +1,152 @@ + + + + Code coverage report for tar/lib/high-level-opt.js + + + + + + + +
    +
    +

    + All files / tar/lib high-level-opt.js +

    +
    +
    + 100% + Statements + 5/5 +
    +
    + 100% + Branches + 4/4 +
    +
    + 100% + Functions + 3/3 +
    +
    + 100% + Lines + 3/3 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30  +  +  +  +7x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +469x +  +469x + 
    'use strict'
    + 
    +// turn tar(1) style args like `C` into the more verbose things like `cwd`
    + 
    +const argmap = new Map([
    +  ['C', 'cwd'],
    +  ['f', 'file'],
    +  ['z', 'gzip'],
    +  ['P', 'preservePaths'],
    +  ['U', 'unlink'],
    +  ['strip-components', 'strip'],
    +  ['stripComponents', 'strip'],
    +  ['keep-newer', 'newer'],
    +  ['keepNewer', 'newer'],
    +  ['keep-newer-files', 'newer'],
    +  ['keepNewerFiles', 'newer'],
    +  ['k', 'keep'],
    +  ['keep-existing', 'keep'],
    +  ['keepExisting', 'keep'],
    +  ['m', 'noMtime'],
    +  ['no-mtime', 'noMtime'],
    +  ['p', 'preserveOwner'],
    +  ['L', 'follow'],
    +  ['h', 'follow']
    +])
    + 
    +const parse = module.exports = opt => opt ? Object.keys(opt).map(k => [
    +  argmap.has(k) ? argmap.get(k) : k, opt[k]
    +]).reduce((set, kv) => (set[kv[0]] = kv[1], set), Object.create(null)) : {}
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/index.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/index.html new file mode 100644 index 0000000000000..1f908d1e77c71 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/index.html @@ -0,0 +1,314 @@ + + + + Code coverage report for tar/lib + + + + + + + +
    +
    +

    + All files tar/lib +

    +
    +
    + 99.94% + Statements + 1782/1783 +
    +
    + 99.67% + Branches + 1224/1228 +
    +
    + 100% + Functions + 271/271 +
    +
    + 99.94% + Lines + 1735/1736 +
    +
    +
    +
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    FileStatementsBranchesFunctionsLines
    create.js
    100%59/59100%35/35100%12/12100%59/59
    extract.js
    100%61/61100%45/45100%12/12100%60/60
    header.js
    100%161/161100%120/120100%20/20100%159/159
    high-level-opt.js
    100%5/5100%4/4100%3/3100%3/3
    large-numbers.js
    100%59/59100%20/20100%8/8100%57/57
    list.js
    100%80/80100%53/53100%14/14100%77/77
    mkdir.js
    100%130/130100%91/91100%15/15100%128/128
    pack.js
    100%228/228100%123/123100%44/44100%222/222
    parse.js
    100%242/242100%155/155100%24/24100%236/236
    pax.js
    100%62/62100%75/75100%9/9100%60/60
    read-entry.js
    100%53/53100%36/36100%3/3100%51/51
    replace.js
    100%131/131100%70/70100%18/18100%128/128
    types.js
    100%3/3100%0/0100%1/1100%2/2
    unpack.js
    100%254/254100%194/194100%44/44100%247/247
    update.js
    100%20/20100%15/15100%4/4100%20/20
    warn-mixin.js
    100%9/9100%4/4100%2/2100%8/8
    winchars.js
    100%12/12100%0/0100%7/7100%8/8
    write-entry.js
    99.53%213/21497.87%184/188100%31/3199.53%210/211
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/large-numbers.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/large-numbers.js.html new file mode 100644 index 0000000000000..5b8610f9b52f3 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/large-numbers.js.html @@ -0,0 +1,341 @@ + + + + Code coverage report for tar/lib/large-numbers.js + + + + + + + +
    +
    +

    + All files / tar/lib large-numbers.js +

    +
    +
    + 100% + Statements + 59/59 +
    +
    + 100% + Branches + 20/20 +
    +
    + 100% + Functions + 8/8 +
    +
    + 100% + Lines + 57/57 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93  +  +  +  +  +  +14x +17x +17x +6x +  +11x +17x +  +  +14x +11x +11x +86x +31x +  +55x +55x +  +  +  +  +14x +6x +6x +6x +6x +  +60x +42x +  +18x +18x +  +60x +48x +12x +6x +  +6x +6x +  +  +  +  +14x +47x +47x +47x +  +  +  +14x +6x +6x +6x +6x +60x +  +60x +48x +12x +6x +  +6x +6x +  +60x +12x +  +6x +  +  +14x +41x +41x +41x +266x +266x +161x +  +41x +  +  +96x +  +14x + 
    'use strict'
    +// Tar can encode large and negative numbers using a leading byte of
    +// 0xff for negative, and 0x80 for positive.  The trailing byte in the
    +// section will always be 0x20, or in some implementations 0x00.
    +// this module encodes and decodes these things.
    + 
    +const encode = exports.encode = (num, buf) => {
    +  buf[buf.length - 1] = 0x20
    +  if (num < 0)
    +    encodeNegative(num, buf)
    +  else
    +    encodePositive(num, buf)
    +  return buf
    +}
    + 
    +const encodePositive = (num, buf) => {
    +  buf[0] = 0x80
    +  for (var i = buf.length - 2; i > 0; i--) {
    +    if (num === 0)
    +      buf[i] = 0
    +    else {
    +      buf[i] = num % 0x100
    +      num = Math.floor(num / 0x100)
    +    }
    +  }
    +}
    + 
    +const encodeNegative = (num, buf) => {
    +  buf[0] = 0xff
    +  var flipped = false
    +  num = num * -1
    +  for (var i = buf.length - 2; i > 0; i--) {
    +    var byte
    +    if (num === 0)
    +      byte = 0
    +    else {
    +      byte = num % 0x100
    +      num = Math.floor(num / 0x100)
    +    }
    +    if (flipped)
    +      buf[i] = onesComp(byte)
    +    else if (byte === 0)
    +      buf[i] = 0
    +    else {
    +      flipped = true
    +      buf[i] = twosComp(byte)
    +    }
    +  }
    +}
    + 
    +const parse = exports.parse = (buf) => {
    +  var post = buf[buf.length - 1]
    +  var pre = buf[0]
    +  return pre === 0x80 ? pos(buf.slice(1, buf.length - 1))
    +   : twos(buf.slice(1, buf.length - 1))
    +}
    + 
    +const twos = (buf) => {
    +  var len = buf.length
    +  var sum = 0
    +  var flipped = false
    +  for (var i = len - 1; i > -1; i--) {
    +    var byte = buf[i]
    +    var f
    +    if (flipped)
    +      f = onesComp(byte)
    +    else if (byte === 0)
    +      f = byte
    +    else {
    +      flipped = true
    +      f = twosComp(byte)
    +    }
    +    if (f !== 0)
    +      sum += f * Math.pow(256, len - i - 1)
    +  }
    +  return sum * -1
    +}
    + 
    +const pos = (buf) => {
    +  var len = buf.length
    +  var sum = 0
    +  for (var i = len - 1; i > -1; i--) {
    +    var byte = buf[i]
    +    if (byte !== 0)
    +      sum += byte * Math.pow(256, len - i - 1)
    +  }
    +  return sum
    +}
    + 
    +const onesComp = byte => (0xff ^ byte) & 0xff
    + 
    +const twosComp = byte => ((0xff ^ byte) + 1) & 0xff
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/list.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/list.js.html new file mode 100644 index 0000000000000..4e6e34e6543a0 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/list.js.html @@ -0,0 +1,449 @@ + + + + Code coverage report for tar/lib/list.js + + + + + + + +
    +
    +

    + All files / tar/lib list.js +

    +
    +
    + 100% + Statements + 80/80 +
    +
    + 100% + Branches + 53/53 +
    +
    + 100% + Functions + 14/14 +
    +
    + 100% + Lines + 77/77 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129  +  +  +  +  +  +5x +5x +5x +5x +5x +  +5x +34x +1x +33x +1x +  +34x +5x +  +34x +31x +  +3x +  +34x +  +34x +1x +  +33x +1x +  +32x +3x +  +32x +22x +  +32x +  +  +  +  +5x +22x +22x +255x +255x +72x +  +  +  +  +5x +6x +3x +  +3x +125x +125x +  +  +  +125x +125x +  +  +3x +32x +64x +  +  +5x +13x +13x +13x +  +13x +13x +12x +12x +10x +  +2x +2x +2x +2x +28x +27x +27x +  +1x +  +11x +  +13x +1x +  +  +  +5x +16x +16x +  +16x +16x +16x +16x +  +16x +16x +2x +  +14x +  +  +  +14x +14x +  +  +  +16x +  +  +16x + 
    'use strict'
    + 
    +// XXX: This shares a lot in common with extract.js
    +// maybe some DRY opportunity here?
    + 
    +// tar -t
    +const hlo = require('./high-level-opt.js')
    +const Parser = require('./parse.js')
    +const fs = require('fs')
    +const fsm = require('fs-minipass')
    +const path = require('path')
    + 
    +const t = module.exports = (opt_, files, cb) => {
    +  if (typeof opt_ === 'function')
    +    cb = opt_, files = null, opt_ = {}
    +  else if (Array.isArray(opt_))
    +    files = opt_, opt_ = {}
    + 
    +  if (typeof files === 'function')
    +    cb = files, files = null
    + 
    +  if (!files)
    +    files = []
    +  else
    +    files = Array.from(files)
    + 
    +  const opt = hlo(opt_)
    + 
    +  if (opt.sync && typeof cb === 'function')
    +    throw new TypeError('callback not supported for sync tar functions')
    + 
    +  if (!opt.file && typeof cb === 'function')
    +    throw new TypeError('callback only supported with file option')
    + 
    +  if (files.length)
    +    filesFilter(opt, files)
    + 
    +  if (!opt.noResume)
    +    onentryFunction(opt)
    + 
    +  return opt.file && opt.sync ? listFileSync(opt)
    +    : opt.file ? listFile(opt, cb)
    +    : list(opt)
    +}
    + 
    +const onentryFunction = opt => {
    +  const onentry = opt.onentry
    +  opt.onentry = onentry ? e => {
    +    onentry(e)
    +    e.resume()
    +  } : e => e.resume()
    +}
    + 
    +// construct a filter that limits the file entries listed
    +// include child entries if a dir is included
    +const filesFilter = (opt, files) => {
    +  const map = new Map(files.map(f => [f.replace(/\/+$/, ''), true]))
    +  const filter = opt.filter
    + 
    +  const mapHas = (file, r) => {
    +    const root = r || path.parse(file).root || '.'
    +    const ret = file === root ? false
    +      : map.has(file) ? map.get(file)
    +      : mapHas(path.dirname(file), root)
    + 
    +    map.set(file, ret)
    +    return ret
    +  }
    + 
    +  opt.filter = filter
    +    ? (file, entry) => filter(file, entry) && mapHas(file.replace(/\/+$/, ''))
    +    : file => mapHas(file.replace(/\/+$/, ''))
    +}
    + 
    +const listFileSync = opt => {
    +  const p = list(opt)
    +  const file = opt.file
    +  let threw = true
    +  let fd
    +  try {
    +    const stat = fs.statSync(file)
    +    const readSize = opt.maxReadSize || 16*1024*1024
    +    if (stat.size < readSize) {
    +      p.end(fs.readFileSync(file))
    +    } else {
    +      let pos = 0
    +      const buf = Buffer.allocUnsafe(readSize)
    +      fd = fs.openSync(file, 'r')
    +      while (pos < stat.size) {
    +        let bytesRead = fs.readSync(fd, buf, 0, readSize, pos)
    +        pos += bytesRead
    +        p.write(buf.slice(0, bytesRead))
    +      }
    +      p.end()
    +    }
    +    threw = false
    +  } finally {
    +    if (threw && fd)
    +      try { fs.closeSync(fd) } catch (er) {}
    +  }
    +}
    + 
    +const listFile = (opt, cb) => {
    +  const parse = new Parser(opt)
    +  const readSize = opt.maxReadSize || 16*1024*1024
    + 
    +  const file = opt.file
    +  const p = new Promise((resolve, reject) => {
    +    parse.on('error', reject)
    +    parse.on('end', resolve)
    + 
    +    fs.stat(file, (er, stat) => {
    +      if (er)
    +        reject(er)
    +      else {
    +        const stream = new fsm.ReadStream(file, {
    +          readSize: readSize,
    +          size: stat.size
    +        })
    +        stream.on('error', reject)
    +        stream.pipe(parse)
    +      }
    +    })
    +  })
    +  return cb ? p.then(cb, cb) : p
    +}
    + 
    +const list = opt => new Parser(opt)
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/mkdir.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/mkdir.js.html new file mode 100644 index 0000000000000..afeb931676293 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/mkdir.js.html @@ -0,0 +1,686 @@ + + + + Code coverage report for tar/lib/mkdir.js + + + + + + + +
    +
    +

    + All files / tar/lib mkdir.js +

    +
    +
    + 100% + Statements + 130/130 +
    +
    + 100% + Branches + 91/91 +
    +
    + 100% + Functions + 15/15 +
    +
    + 100% + Lines + 128/128 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208  +  +  +  +  +  +3x +3x +3x +3x +  +  +  +4x +4x +4x +  +  +  +8x +  +  +  +  +  +12x +12x +12x +  +  +  +36x +  +  +  +3x +  +  +451x +451x +451x +  +451x +451x +451x +  +  +  +451x +451x +451x +451x +  +451x +457x +15x +  +442x +442x +6x +436x +1x +  +435x +  +  +  +451x +272x +  +179x +40x +40x +2x +40x +  +  +139x +8x +  +131x +131x +131x +  +  +3x +1062x +119x +943x +943x +943x +723x +220x +  +  +222x +222x +36x +  +4x +  +32x +32x +4x +28x +22x +6x +3x +3x +1x +2x +  +3x +2x +  +1x +  +  +186x +186x +  +  +  +3x +  +  +276x +276x +276x +  +276x +276x +276x +  +  +  +276x +276x +276x +276x +  +276x +266x +266x +6x +266x +1x +266x +  +  +276x +128x +  +148x +34x +34x +34x +34x +  +1x +  +34x +2x +  +32x +32x +  +  +114x +7x +  +107x +107x +107x +107x +  +  +  +792x +608x +  +184x +184x +169x +169x +  +15x +  +4x +  +11x +9x +4x +4x +5x +2x +2x +2x +2x +2x +3x +2x +  +  +  +99x +  + 
    'use strict'
    +// wrapper around mkdirp for tar's needs.
    + 
    +// TODO: This should probably be a class, not functionally
    +// passing around state in a gazillion args.
    + 
    +const mkdirp = require('mkdirp')
    +const fs = require('fs')
    +const path = require('path')
    +const chownr = require('chownr')
    + 
    +class SymlinkError extends Error {
    +  constructor (symlink, path) {
    +    super('Cannot extract through symbolic link')
    +    this.path = path
    +    this.symlink = symlink
    +  }
    + 
    +  get name () {
    +    return 'SylinkError'
    +  }
    +}
    + 
    +class CwdError extends Error {
    +  constructor (path, code) {
    +    super(code + ': Cannot cd into \'' + path + '\'')
    +    this.path = path
    +    this.code = code
    +  }
    + 
    +  get name () {
    +    return 'CwdError'
    +  }
    +}
    + 
    +const mkdir = module.exports = (dir, opt, cb) => {
    +  // if there's any overlap between mask and mode,
    +  // then we'll need an explicit chmod
    +  const umask = opt.umask
    +  const mode = opt.mode | 0o0700
    +  const needChmod = (mode & umask) !== 0
    + 
    +  const uid = opt.uid
    +  const gid = opt.gid
    +  const doChown = typeof uid === 'number' &&
    +    typeof gid === 'number' &&
    +    ( uid !== opt.processUid || gid !== opt.processGid )
    + 
    +  const preserve = opt.preserve
    +  const unlink = opt.unlink
    +  const cache = opt.cache
    +  const cwd = opt.cwd
    + 
    +  const done = (er, created) => {
    +    if (er)
    +      cb(er)
    +    else {
    +      cache.set(dir, true)
    +      if (created && doChown)
    +        chownr(created, uid, gid, er => done(er))
    +      else if (needChmod)
    +        fs.chmod(dir, mode, cb)
    +      else
    +        cb()
    +    }
    +  }
    + 
    +  if (cache && cache.get(dir) === true)
    +    return done()
    + 
    +  if (dir === cwd)
    +    return fs.lstat(dir, (er, st) => {
    +      if (er || !st.isDirectory())
    +        er = new CwdError(dir, er && er.code || 'ENOTDIR')
    +      done(er)
    +    })
    + 
    +  if (preserve)
    +    return mkdirp(dir, mode, done)
    + 
    +  const sub = path.relative(cwd, dir)
    +  const parts = sub.split(/\/|\\/)
    +  mkdir_(cwd, parts, mode, cache, unlink, cwd, null, done)
    +}
    + 
    +const mkdir_ = (base, parts, mode, cache, unlink, cwd, created, cb) => {
    +  if (!parts.length)
    +    return cb(null, created)
    +  const p = parts.shift()
    +  const part = base + '/' + p
    +  if (cache.get(part))
    +    return mkdir_(part, parts, mode, cache, unlink, cwd, created, cb)
    +  fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb))
    +}
    + 
    +const onmkdir = (part, parts, mode, cache, unlink, cwd, created, cb) => er => {
    +  if (er) {
    +    if (er.path && path.dirname(er.path) === cwd &&
    +        (er.code === 'ENOTDIR' || er.code === 'ENOENT'))
    +      return cb(new CwdError(cwd, er.code))
    + 
    +    fs.lstat(part, (statEr, st) => {
    +      if (statEr)
    +        cb(statEr)
    +      else if (st.isDirectory())
    +        mkdir_(part, parts, mode, cache, unlink, cwd, created, cb)
    +      else if (unlink)
    +        fs.unlink(part, er => {
    +          if (er)
    +            return cb(er)
    +          fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb))
    +        })
    +      else if (st.isSymbolicLink())
    +        return cb(new SymlinkError(part, part + '/' + parts.join('/')))
    +      else
    +        cb(er)
    +    })
    +  } else {
    +    created = created || part
    +    mkdir_(part, parts, mode, cache, unlink, cwd, created, cb)
    +  }
    +}
    + 
    +const mkdirSync = module.exports.sync = (dir, opt) => {
    +  // if there's any overlap between mask and mode,
    +  // then we'll need an explicit chmod
    +  const umask = opt.umask
    +  const mode = opt.mode | 0o0700
    +  const needChmod = (mode & umask) !== 0
    + 
    +  const uid = opt.uid
    +  const gid = opt.gid
    +  const doChown = typeof uid === 'number' &&
    +    typeof gid === 'number' &&
    +    ( uid !== opt.processUid || gid !== opt.processGid )
    + 
    +  const preserve = opt.preserve
    +  const unlink = opt.unlink
    +  const cache = opt.cache
    +  const cwd = opt.cwd
    + 
    +  const done = (created) => {
    +    cache.set(dir, true)
    +    if (created && doChown)
    +      chownr.sync(created, uid, gid)
    +    if (needChmod)
    +      fs.chmodSync(dir, mode)
    +    cache.set(dir, true)
    +  }
    + 
    +  if (cache && cache.get(dir) === true)
    +    return done()
    + 
    +  if (dir === cwd) {
    +    let ok = false
    +    let code = 'ENOTDIR'
    +    try {
    +      ok = fs.lstatSync(dir).isDirectory()
    +    } catch (er) {
    +      code = er.code
    +    } finally {
    +      if (!ok)
    +        throw new CwdError(dir, code)
    +    }
    +    done()
    +    return
    +  }
    + 
    +  if (preserve)
    +    return done(mkdirp.sync(dir, mode))
    + 
    +  const sub = path.relative(cwd, dir)
    +  const parts = sub.split(/\/|\\/)
    +  let created = null
    +  for (let p = parts.shift(), part = cwd;
    +       p && (part += '/' + p);
    +       p = parts.shift()) {
    + 
    +    if (cache.get(part))
    +      continue
    + 
    +    try {
    +      fs.mkdirSync(part, mode)
    +      created = created || part
    +      cache.set(part, true)
    +    } catch (er) {
    +      if (er.path && path.dirname(er.path) === cwd &&
    +          (er.code === 'ENOTDIR' || er.code === 'ENOENT'))
    +        return new CwdError(cwd, er.code)
    + 
    +      const st = fs.lstatSync(part)
    +      if (st.isDirectory()) {
    +        cache.set(part, true)
    +        continue
    +      } else if (unlink) {
    +        fs.unlinkSync(part)
    +        fs.mkdirSync(part, mode)
    +        created = created || part
    +        cache.set(part, true)
    +        continue
    +      } else if (st.isSymbolicLink())
    +        return new SymlinkError(part, part + '/' + parts.join('/'))
    +    }
    +  }
    + 
    +  return done(created)
    +}
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pack.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pack.js.html new file mode 100644 index 0000000000000..d46f96d8fcbd4 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pack.js.html @@ -0,0 +1,1268 @@ + + + + Code coverage report for tar/lib/pack.js + + + + + + + +
    +
    +

    + All files / tar/lib pack.js +

    +
    +
    + 100% + Statements + 228/228 +
    +
    + 100% + Branches + 123/123 +
    +
    + 100% + Functions + 44/44 +
    +
    + 100% + Lines + 222/222 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402  +  +  +  +  +  +  +  +  +  +  +  +  +6566x +6566x +6566x +6566x +6566x +6566x +6566x +6566x +  +  +  +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +5x +  +5x +5x +5x +  +5x +  +122x +122x +122x +122x +122x +122x +122x +122x +122x +122x +122x +122x +122x +122x +3x +  +122x +122x +5x +4x +5x +503x +5x +146x +219x +  +117x +  +122x +122x +122x +122x +  +  +6507x +  +122x +122x +122x +122x +122x +  +  +  +106x +  +  +  +107x +103x +  +  +  +100x +21x +99x +99x +99x +  +  +  +128x +1x +  +127x +27x +  +100x +123x +  +  +  +27x +27x +1x +  +  +27x +2x +  +25x +25x +25x +25x +25x +  +  +27x +  +  +  +6541x +6541x +34x +  +6541x +6541x +  +  +  +6453x +6453x +6453x +6453x +6453x +6453x +6453x +1x +  +6452x +  +  +  +  +6538x +6538x +  +  +6538x +24x +  +6538x +  +  +  +821x +821x +821x +821x +821x +821x +1x +820x +  +  +  +  +858x +858x +858x +  +  +  +20596x +9093x +  +11503x +11503x +  +  +38739x +38735x +25x +25x +25x +  +  +  +11499x +  +11499x +96x +4x +  +92x +92x +  +  +  +  +  +25863x +  +  +  +6533x +6533x +6533x +  +  +  +38739x +6156x +  +32583x +18770x +4954x +18770x +  +  +13813x +6541x +4x +  +6537x +  +13811x +6453x +  +  +7358x +24x +  +7334x +860x +2x +  +858x +859x +821x +  +  +  +6512x +6511x +1x +1x +  +  +6510x +1581x +  +  +  +6537x +  +1x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6512x +6512x +6512x +6508x +1x +  +2x +  +  +  +  +248x +158x +  +  +  +  +6448x +  +6448x +820x +6393x +  +  +  +6393x +6393x +  +  +6448x +6448x +  +6448x +6336x +11830x +156x +  +  +112x +199x +53x +  +  +  +  +265x +214x +265x +  +  +  +  +  +47x +47x +  +  +  +  +  +  +  +84x +84x +  +  +  +37x +  +  +  +  +87x +87x +  +87x +38x +48x +  +  +  +  +48x +48x +  +  +87x +31x +39x +  +  +56x +106x +  +  +  +  +5x +  +5x + 
    'use strict'
    + 
    +// A readable tar stream creator
    +// Technically, this is a transform stream that you write paths into,
    +// and tar format comes out of.
    +// The `add()` method is like `write()` but returns this,
    +// and end() return `this` as well, so you can
    +// do `new Pack(opt).add('files').add('dir').end().pipe(output)
    +// You could also do something like:
    +// streamOfPaths().pipe(new Pack()).pipe(new fs.WriteStream('out.tar'))
    + 
    +class PackJob {
    +  constructor (path, absolute) {
    +    this.path = path || './'
    +    this.absolute = absolute
    +    this.entry = null
    +    this.stat = null
    +    this.readdir = null
    +    this.pending = false
    +    this.ignore = false
    +    this.piped = false
    +  }
    +}
    + 
    +const MiniPass = require('minipass')
    +const zlib = require('minizlib')
    +const ReadEntry = require('./read-entry.js')
    +const WriteEntry = require('./write-entry.js')
    +const WriteEntrySync = WriteEntry.Sync
    +const WriteEntryTar = WriteEntry.Tar
    +const Yallist = require('yallist')
    +const EOF = Buffer.alloc(1024)
    +const ONSTAT = Symbol('onStat')
    +const ENDED = Symbol('ended')
    +const QUEUE = Symbol('queue')
    +const CURRENT = Symbol('current')
    +const PROCESS = Symbol('process')
    +const PROCESSING = Symbol('processing')
    +const PROCESSJOB = Symbol('processJob')
    +const JOBS = Symbol('jobs')
    +const JOBDONE = Symbol('jobDone')
    +const ADDFSENTRY = Symbol('addFSEntry')
    +const ADDTARENTRY = Symbol('addTarEntry')
    +const STAT = Symbol('stat')
    +const READDIR = Symbol('readdir')
    +const ONREADDIR = Symbol('onreaddir')
    +const PIPE = Symbol('pipe')
    +const ENTRY = Symbol('entry')
    +const ENTRYOPT = Symbol('entryOpt')
    +const WRITEENTRYCLASS = Symbol('writeEntryClass')
    +const WRITE = Symbol('write')
    +const ONDRAIN = Symbol('ondrain')
    + 
    +const fs = require('fs')
    +const path = require('path')
    +const warner = require('./warn-mixin.js')
    + 
    +const Pack = warner(class Pack extends MiniPass {
    +  constructor (opt) {
    +    super(opt)
    +    opt = opt || Object.create(null)
    +    this.opt = opt
    +    this.cwd = opt.cwd || process.cwd()
    +    this.maxReadSize = opt.maxReadSize
    +    this.preservePaths = !!opt.preservePaths
    +    this.strict = !!opt.strict
    +    this.noPax = !!opt.noPax
    +    this.prefix = (opt.prefix || '').replace(/(\\|\/)+$/, '')
    +    this.linkCache = opt.linkCache || new Map()
    +    this.statCache = opt.statCache || new Map()
    +    this.readdirCache = opt.readdirCache || new Map()
    +    this[WRITEENTRYCLASS] = WriteEntry
    +    if (typeof opt.onwarn === 'function')
    +      this.on('warn', opt.onwarn)
    + 
    +    this.zip = null
    +    if (opt.gzip) {
    +      if (typeof opt.gzip !== 'object')
    +        opt.gzip = {}
    +      this.zip = new zlib.Gzip(opt.gzip)
    +      this.zip.on('data', chunk => super.write(chunk))
    +      this.zip.on('end', _ => super.end())
    +      this.zip.on('drain', _ => this[ONDRAIN]())
    +      this.on('resume', _ => this.zip.resume())
    +    } else
    +      this.on('drain', this[ONDRAIN])
    + 
    +    this.portable = !!opt.portable
    +    this.noDirRecurse = !!opt.noDirRecurse
    +    this.follow = !!opt.follow
    +    this.noMtime = !!opt.noMtime
    + 
    + 
    +    this.filter = typeof opt.filter === 'function' ? opt.filter : _ => true
    + 
    +    this[QUEUE] = new Yallist
    +    this[JOBS] = 0
    +    this.jobs = +opt.jobs || 4
    +    this[PROCESSING] = false
    +    this[ENDED] = false
    +  }
    + 
    +  [WRITE] (chunk) {
    +    return super.write(chunk)
    +  }
    + 
    +  add (path) {
    +    this.write(path)
    +    return this
    +  }
    + 
    +  end (path) {
    +    if (path)
    +      this.write(path)
    +    this[ENDED] = true
    +    this[PROCESS]()
    +    return this
    +  }
    + 
    +  write (path) {
    +    if (this[ENDED])
    +      throw new Error('write after end')
    + 
    +    if (path instanceof ReadEntry)
    +      this[ADDTARENTRY](path)
    +    else
    +      this[ADDFSENTRY](path)
    +    return this.flowing
    +  }
    + 
    +  [ADDTARENTRY] (p) {
    +    const absolute = path.resolve(this.cwd, p.path)
    +    if (this.prefix)
    +      p.path = this.prefix + '/' + p.path.replace(/^\.(\/+|$)/, '')
    + 
    +    // in this case, we don't have to wait for the stat
    +    if (!this.filter(p.path, p))
    +      p.resume()
    +    else {
    +      const job = new PackJob(p.path, absolute, false)
    +      job.entry = new WriteEntryTar(p, this[ENTRYOPT](job))
    +      job.entry.on('end', _ => this[JOBDONE](job))
    +      this[JOBS] += 1
    +      this[QUEUE].push(job)
    +    }
    + 
    +    this[PROCESS]()
    +  }
    + 
    +  [ADDFSENTRY] (p) {
    +    const absolute = path.resolve(this.cwd, p)
    +    if (this.prefix)
    +      p = this.prefix + '/' + p.replace(/^\.(\/+|$)/, '')
    + 
    +    this[QUEUE].push(new PackJob(p, absolute))
    +    this[PROCESS]()
    +  }
    + 
    +  [STAT] (job) {
    +    job.pending = true
    +    this[JOBS] += 1
    +    const stat = this.follow ? 'stat' : 'lstat'
    +    fs[stat](job.absolute, (er, stat) => {
    +      job.pending = false
    +      this[JOBS] -= 1
    +      if (er)
    +        this.emit('error', er)
    +      else
    +        this[ONSTAT](job, stat)
    +    })
    +  }
    + 
    +  [ONSTAT] (job, stat) {
    +    this.statCache.set(job.absolute, stat)
    +    job.stat = stat
    + 
    +    // now we have the stat, we can filter it.
    +    if (!this.filter(job.path, stat))
    +      job.ignore = true
    + 
    +    this[PROCESS]()
    +  }
    + 
    +  [READDIR] (job) {
    +    job.pending = true
    +    this[JOBS] += 1
    +    fs.readdir(job.absolute, (er, entries) => {
    +      job.pending = false
    +      this[JOBS] -= 1
    +      if (er)
    +        return this.emit('error', er)
    +      this[ONREADDIR](job, entries)
    +    })
    +  }
    + 
    +  [ONREADDIR] (job, entries) {
    +    this.readdirCache.set(job.absolute, entries)
    +    job.readdir = entries
    +    this[PROCESS]()
    +  }
    + 
    +  [PROCESS] () {
    +    if (this[PROCESSING])
    +      return
    + 
    +    this[PROCESSING] = true
    +    for (let w = this[QUEUE].head;
    +         w !== null && this[JOBS] < this.jobs;
    +         w = w.next) {
    +      this[PROCESSJOB](w.value)
    +      if (w.value.ignore) {
    +        const p = w.next
    +        this[QUEUE].removeNode(w)
    +        w.next = p
    +      }
    +    }
    + 
    +    this[PROCESSING] = false
    + 
    +    if (this[ENDED] && !this[QUEUE].length && this[JOBS] === 0) {
    +      if (this.zip)
    +        this.zip.end(EOF)
    +      else {
    +        super.write(EOF)
    +        super.end()
    +      }
    +    }
    +  }
    + 
    +  get [CURRENT] () {
    +    return this[QUEUE] && this[QUEUE].head && this[QUEUE].head.value
    +  }
    + 
    +  [JOBDONE] (job) {
    +    this[QUEUE].shift()
    +    this[JOBS] -= 1
    +    this[PROCESS]()
    +  }
    + 
    +  [PROCESSJOB] (job) {
    +    if (job.pending)
    +      return
    + 
    +    if (job.entry) {
    +      if (job === this[CURRENT] && !job.piped)
    +        this[PIPE](job)
    +      return
    +    }
    + 
    +    if (!job.stat) {
    +      if (this.statCache.has(job.absolute))
    +        this[ONSTAT](job, this.statCache.get(job.absolute))
    +      else
    +        this[STAT](job)
    +    }
    +    if (!job.stat)
    +      return
    + 
    +    // filtered out!
    +    if (job.ignore)
    +      return
    + 
    +    if (!this.noDirRecurse && job.stat.isDirectory() && !job.readdir) {
    +      if (this.readdirCache.has(job.absolute))
    +        this[ONREADDIR](job, this.readdirCache.get(job.absolute))
    +      else
    +        this[READDIR](job)
    +      if (!job.readdir)
    +        return
    +    }
    + 
    +    // we know it doesn't have an entry, because that got checked above
    +    job.entry = this[ENTRY](job)
    +    if (!job.entry) {
    +      job.ignore = true
    +      return
    +    }
    + 
    +    if (job === this[CURRENT] && !job.piped)
    +      this[PIPE](job)
    +  }
    + 
    +  [ENTRYOPT] (job) {
    +    return {
    +      onwarn: (msg, data) => {
    +        this.warn(msg, data)
    +      },
    +      noPax: this.noPax,
    +      cwd: this.cwd,
    +      absolute: job.absolute,
    +      preservePaths: this.preservePaths,
    +      maxReadSize: this.maxReadSize,
    +      strict: this.strict,
    +      portable: this.portable,
    +      linkCache: this.linkCache,
    +      statCache: this.statCache,
    +      noMtime: this.noMtime
    +    }
    +  }
    + 
    +  [ENTRY] (job) {
    +    this[JOBS] += 1
    +    try {
    +      return new this[WRITEENTRYCLASS](job.path, this[ENTRYOPT](job))
    +        .on('end', () => this[JOBDONE](job))
    +        .on('error', er => this.emit('error', er))
    +    } catch (er) {
    +      this.emit('error', er)
    +    }
    +  }
    + 
    +  [ONDRAIN] () {
    +    if (this[CURRENT] && this[CURRENT].entry)
    +      this[CURRENT].entry.resume()
    +  }
    + 
    +  // like .pipe() but using super, because our write() is special
    +  [PIPE] (job) {
    +    job.piped = true
    + 
    +    if (job.readdir)
    +      job.readdir.forEach(entry => {
    +        const p = this.prefix ?
    +          job.path.slice(this.prefix.length + 1) || './'
    +          : job.path
    + 
    +        const base = p === './' ? '' : p.replace(/\/*$/, '/')
    +        this[ADDFSENTRY](base + entry)
    +      })
    + 
    +    const source = job.entry
    +    const zip = this.zip
    + 
    +    if (zip)
    +      source.on('data', chunk => {
    +        if (!zip.write(chunk))
    +          source.pause()
    +      })
    +    else
    +      source.on('data', chunk => {
    +        if (!super.write(chunk))
    +          source.pause()
    +      })
    +  }
    + 
    +  pause () {
    +    if (this.zip)
    +      this.zip.pause()
    +    return super.pause()
    +  }
    +})
    + 
    +class PackSync extends Pack {
    +  constructor (opt) {
    +    super(opt)
    +    this[WRITEENTRYCLASS] = WriteEntrySync
    +  }
    + 
    +  // pause/resume are no-ops in sync streams.
    +  pause () {}
    +  resume () {}
    + 
    +  [STAT] (job) {
    +    const stat = this.follow ? 'statSync' : 'lstatSync'
    +    this[ONSTAT](job, fs[stat](job.absolute))
    +  }
    + 
    +  [READDIR] (job, stat) {
    +    this[ONREADDIR](job, fs.readdirSync(job.absolute))
    +  }
    + 
    +  // gotta get it all in this tick
    +  [PIPE] (job) {
    +    const source = job.entry
    +    const zip = this.zip
    + 
    +    if (job.readdir)
    +      job.readdir.forEach(entry => {
    +        const p = this.prefix ?
    +          job.path.slice(this.prefix.length + 1) || './'
    +          : job.path
    + 
    + 
    +        const base = p === './' ? '' : p.replace(/\/*$/, '/')
    +        this[ADDFSENTRY](base + entry)
    +      })
    + 
    +    if (zip)
    +      source.on('data', chunk => {
    +        zip.write(chunk)
    +      })
    +    else
    +      source.on('data', chunk => {
    +        super[WRITE](chunk)
    +      })
    +  }
    +}
    + 
    +Pack.Sync = PackSync
    + 
    +module.exports = Pack
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/parse.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/parse.js.html new file mode 100644 index 0000000000000..1d505abe68199 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/parse.js.html @@ -0,0 +1,1310 @@ + + + + Code coverage report for tar/lib/parse.js + + + + + + + +
    +
    +

    + All files / tar/lib parse.js +

    +
    +
    + 100% + Statements + 242/242 +
    +
    + 100% + Branches + 155/155 +
    +
    + 100% + Functions + 24/24 +
    +
    + 100% + Lines + 236/236 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +9x +9x +9x +9x +9x +9x +9x +9x +9x +  +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +9x +  +2032x +  +9x +  +742x +742x +  +742x +134x +  +608x +589x +589x +589x +589x +  +  +742x +742x +742x +  +  +742x +742x +  +742x +742x +742x +742x +742x +742x +742x +742x +742x +742x +742x +742x +36x +742x +34x +  +  +  +6101x +  +6101x +1834x +4267x +160x +4107x +40x +  +4067x +4067x +40x +4027x +40x +  +3987x +  +3987x +759x +260x +260x +260x +499x +455x +475x +455x +  +  +  +3228x +3228x +3228x +1070x +1070x +  +2158x +1028x +  +1130x +1130x +  +  +2158x +1675x +1675x +  +483x +  +  +  +  +  +  +  +4299x +  +4299x +1653x +1653x +2646x +490x +  +2156x +2156x +2150x +1288x +1288x +  +  +  +4293x +  +  +  +2947x +  +2941x +  +  +  +  +  +  +  +2478x +2478x +2478x +2468x +516x +  +10x +  +  +  +  +  +2194x +2194x +2194x +  +  +2194x +  +2194x +2121x +2121x +2121x +  +  +2194x +  +  +  +475x +475x +  +  +475x +455x +  +475x +  +  +  +4328x +3815x +  +513x +  +  +  +455x +455x +  +  +351x +351x +  +  +44x +44x +  +  +  +40x +40x +40x +  +  +20x +20x +20x +  +  +  +  +  +  +  +2x +2x +2x +  +  +  +669590x +1x +  +  +669589x +944x +224x +224x +  +944x +224x +224x +  +720x +947x +493x +  +720x +227x +227x +227x +20164x +227x +2x +227x +226x +226x +  +227x +  +  +  +669138x +669138x +33586x +  +635552x +669132x +  +  +  +669132x +  +  +  +  +669132x +63x +  +669132x +  +  +  +652869x +652866x +  +  +  +3449x +709x +709x +709x +2x +2x +  +2x +1x +2x +  +709x +  +  +  +  +655942x +10x +655932x +381x +  +655551x +655551x +652859x +652859x +652859x +652859x +  +2692x +  +  +655545x +2x +2x +2x +  +655545x +  +  +655936x +3068x +  +  +  +  +  +655553x +655553x +655553x +8295x +  +6101x +6095x +6095x +  +  +  +1719x +1719x +  +  +475x +475x +  +  +  +  +  +  +  +655547x +652863x +1x +  +652862x +  +  +  +  +718x +717x +113x +  +604x +604x +  +  +  +  + 
    'use strict'
    + 
    +// this[BUFFER] is the remainder of a chunk if we're waiting for
    +// the full 512 bytes of a header to come in.  We will Buffer.concat()
    +// it to the next write(), which is a mem copy, but a small one.
    +//
    +// this[QUEUE] is a Yallist of entries that haven't been emitted
    +// yet this can only get filled up if the user keeps write()ing after
    +// a write() returns false, or does a write() with more than one entry
    +//
    +// We don't buffer chunks, we always parse them and either create an
    +// entry, or push it into the active entry.  The ReadEntry class knows
    +// to throw data away if .ignore=true
    +//
    +// Shift entry off the buffer when it emits 'end', and emit 'entry' for
    +// the next one in the list.
    +//
    +// At any time, we're pushing body chunks into the entry at WRITEENTRY,
    +// and waiting for 'end' on the entry at READENTRY
    +//
    +// ignored entries get .resume() called on them straight away
    + 
    +const warner = require('./warn-mixin.js')
    +const path = require('path')
    +const Header = require('./header.js')
    +const EE = require('events')
    +const Yallist = require('yallist')
    +const maxMetaEntrySize = 1024 * 1024
    +const Entry = require('./read-entry.js')
    +const Pax = require('./pax.js')
    +const zlib = require('minizlib')
    + 
    +const gzipHeader = new Buffer([0x1f, 0x8b])
    +const STATE = Symbol('state')
    +const WRITEENTRY = Symbol('writeEntry')
    +const READENTRY = Symbol('readEntry')
    +const NEXTENTRY = Symbol('nextEntry')
    +const PROCESSENTRY = Symbol('processEntry')
    +const EX = Symbol('extendedHeader')
    +const GEX = Symbol('globalExtendedHeader')
    +const META = Symbol('meta')
    +const EMITMETA = Symbol('emitMeta')
    +const BUFFER = Symbol('buffer')
    +const QUEUE = Symbol('queue')
    +const ENDED = Symbol('ended')
    +const EMITTEDEND = Symbol('emittedEnd')
    +const EMIT = Symbol('emit')
    +const UNZIP = Symbol('unzip')
    +const CONSUMECHUNK = Symbol('consumeChunk')
    +const CONSUMECHUNKSUB = Symbol('consumeChunkSub')
    +const CONSUMEBODY = Symbol('consumeBody')
    +const CONSUMEMETA = Symbol('consumeMeta')
    +const CONSUMEHEADER = Symbol('consumeHeader')
    +const CONSUMING = Symbol('consuming')
    +const BUFFERCONCAT = Symbol('bufferConcat')
    +const MAYBEEND = Symbol('maybeEnd')
    +const WRITING = Symbol('writing')
    +const ABORTED = Symbol('aborted')
    +const DONE = Symbol('onDone')
    + 
    +const noop = _ => true
    + 
    +module.exports = warner(class Parser extends EE {
    +  constructor (opt) {
    +    opt = opt || {}
    +    super(opt)
    + 
    +    if (opt.ondone)
    +      this.on(DONE, opt.ondone)
    +    else
    +      this.on(DONE, _ => {
    +        this.emit('prefinish')
    +        this.emit('finish')
    +        this.emit('end')
    +        this.emit('close')
    +      })
    + 
    +    this.strict = !!opt.strict
    +    this.maxMetaEntrySize = opt.maxMetaEntrySize || maxMetaEntrySize
    +    this.filter = typeof opt.filter === 'function' ? opt.filter : noop
    + 
    +    // have to set this so that streams are ok piping into it
    +    this.writable = true
    +    this.readable = false
    + 
    +    this[QUEUE] = new Yallist()
    +    this[BUFFER] = null
    +    this[READENTRY] = null
    +    this[WRITEENTRY] = null
    +    this[STATE] = 'begin'
    +    this[META] = ''
    +    this[EX] = null
    +    this[GEX] = null
    +    this[ENDED] = false
    +    this[UNZIP] = null
    +    this[ABORTED] = false
    +    if (typeof opt.onwarn === 'function')
    +      this.on('warn', opt.onwarn)
    +    if (typeof opt.onentry === 'function')
    +      this.on('entry', opt.onentry)
    +  }
    + 
    +  [CONSUMEHEADER] (chunk, position) {
    +    const header = new Header(chunk, position)
    + 
    +    if (header.nullBlock)
    +      this[EMIT]('nullBlock')
    +    else if (!header.cksumValid)
    +      this.warn('invalid entry', header)
    +    else if (!header.path)
    +      this.warn('invalid: path is required', header)
    +    else {
    +      const type = header.type
    +      if (/^(Symbolic)?Link$/.test(type) && !header.linkpath)
    +        this.warn('invalid: linkpath required', header)
    +      else if (!/^(Symbolic)?Link$/.test(type) && header.linkpath)
    +        this.warn('invalid: linkpath forbidden', header)
    +      else {
    +        const entry = this[WRITEENTRY] = new Entry(header, this[EX], this[GEX])
    + 
    +        if (entry.meta) {
    +          if (entry.size > this.maxMetaEntrySize) {
    +            entry.ignore = true
    +            this[EMIT]('ignoredEntry', entry)
    +            this[STATE] = 'ignore'
    +          } else if (entry.size > 0) {
    +            this[META] = ''
    +            entry.on('data', c => this[META] += c)
    +            this[STATE] = 'meta'
    +          }
    +        } else {
    + 
    +          this[EX] = null
    +          entry.ignore = entry.ignore || !this.filter(entry.path, entry)
    +          if (entry.ignore) {
    +            this[EMIT]('ignoredEntry', entry)
    +            this[STATE] = entry.remain ? 'ignore' : 'begin'
    +          } else {
    +            if (entry.remain)
    +              this[STATE] = 'body'
    +            else {
    +              this[STATE] = 'begin'
    +              entry.end()
    +            }
    + 
    +            if (!this[READENTRY]) {
    +              this[QUEUE].push(entry)
    +              this[NEXTENTRY]()
    +            } else
    +              this[QUEUE].push(entry)
    +          }
    +        }
    +      }
    +    }
    +  }
    + 
    +  [PROCESSENTRY] (entry) {
    +    let go = true
    + 
    +    if (!entry) {
    +      this[READENTRY] = null
    +      go = false
    +    } else if (Array.isArray(entry))
    +      this.emit.apply(this, entry)
    +    else {
    +      this[READENTRY] = entry
    +      this.emit('entry', entry)
    +      if (!entry.emittedEnd) {
    +        entry.on('end', _ => this[NEXTENTRY]())
    +        go = false
    +      }
    +    }
    + 
    +    return go
    +  }
    + 
    +  [NEXTENTRY] () {
    +    do {} while (this[PROCESSENTRY](this[QUEUE].shift()))
    + 
    +    if (!this[QUEUE].length) {
    +      // At this point, there's nothing in the queue, but we may have an
    +      // entry which is being consumed (readEntry).
    +      // If we don't, then we definitely can handle more data.
    +      // If we do, and either it's flowing, or it has never had any data
    +      // written to it, then it needs more.
    +      // The only other possibility is that it has returned false from a
    +      // write() call, so we wait for the next drain to continue.
    +      const re = this[READENTRY]
    +      const drainNow = !re || re.flowing || re.size === re.remain
    +      if (drainNow) {
    +        if (!this[WRITING])
    +          this.emit('drain')
    +      } else
    +        re.once('drain', _ => this.emit('drain'))
    +     }
    +  }
    + 
    +  [CONSUMEBODY] (chunk, position) {
    +    // write up to but no  more than writeEntry.blockRemain
    +    const entry = this[WRITEENTRY]
    +    const br = entry.blockRemain
    +    const c = (br >= chunk.length && position === 0) ? chunk
    +      : chunk.slice(position, position + br)
    + 
    +    entry.write(c)
    + 
    +    if (!entry.blockRemain) {
    +      this[STATE] = 'begin'
    +      this[WRITEENTRY] = null
    +      entry.end()
    +    }
    + 
    +    return c.length
    +  }
    + 
    +  [CONSUMEMETA] (chunk, position) {
    +    const entry = this[WRITEENTRY]
    +    const ret = this[CONSUMEBODY](chunk, position)
    + 
    +    // if we finished, then the entry is reset
    +    if (!this[WRITEENTRY])
    +      this[EMITMETA](entry)
    + 
    +    return ret
    +  }
    + 
    +  [EMIT] (ev, data, extra) {
    +    if (!this[QUEUE].length && !this[READENTRY])
    +      this.emit(ev, data, extra)
    +    else
    +      this[QUEUE].push([ev, data, extra])
    +  }
    + 
    +  [EMITMETA] (entry) {
    +    this[EMIT]('meta', this[META])
    +    switch (entry.type) {
    +      case 'ExtendedHeader':
    +      case 'OldExtendedHeader':
    +        this[EX] = Pax.parse(this[META], this[EX], false)
    +        break
    + 
    +      case 'GlobalExtendedHeader':
    +        this[GEX] = Pax.parse(this[META], this[GEX], true)
    +        break
    + 
    +      case 'NextFileHasLongPath':
    +      case 'OldGnuLongPath':
    +        this[EX] = this[EX] || Object.create(null)
    +        this[EX].path = this[META].replace(/\0.*/, '')
    +        break
    + 
    +      case 'NextFileHasLongLinkpath':
    +        this[EX] = this[EX] || Object.create(null)
    +        this[EX].linkpath = this[META].replace(/\0.*/, '')
    +        break
    + 
    +      /* istanbul ignore next */
    +      default: throw new Error('unknown meta: ' + entry.type)
    +    }
    +  }
    + 
    +  abort (msg, error) {
    +    this[ABORTED] = true
    +    this.warn(msg, error)
    +    this.emit('abort')
    +  }
    + 
    +  write (chunk) {
    +    if (this[ABORTED])
    +      return
    + 
    +    // first write, might be gzipped
    +    if (this[UNZIP] === null && chunk) {
    +      if (this[BUFFER]) {
    +        chunk = Buffer.concat([this[BUFFER], chunk])
    +        this[BUFFER] = null
    +      }
    +      if (chunk.length < gzipHeader.length) {
    +        this[BUFFER] = chunk
    +        return true
    +      }
    +      for (let i = 0; this[UNZIP] === null && i < gzipHeader.length; i++) {
    +        if (chunk[i] !== gzipHeader[i])
    +          this[UNZIP] = false
    +      }
    +      if (this[UNZIP] === null) {
    +        const ended = this[ENDED]
    +        this[ENDED] = false
    +        this[UNZIP] = new zlib.Unzip()
    +        this[UNZIP].on('data', chunk => this[CONSUMECHUNK](chunk))
    +        this[UNZIP].on('error', er =>
    +          this.abort('zlib error: ' + er.message, er))
    +        this[UNZIP].on('end', _ => {
    +          this[ENDED] = true
    +          this[CONSUMECHUNK]()
    +        })
    +        return ended ? this[UNZIP].end(chunk) : this[UNZIP].write(chunk)
    +      }
    +    }
    + 
    +    this[WRITING] = true
    +    if (this[UNZIP])
    +      this[UNZIP].write(chunk)
    +    else
    +      this[CONSUMECHUNK](chunk)
    +    this[WRITING] = false
    + 
    +    // return false if there's a queue, or if the current entry isn't flowing
    +    const ret =
    +      this[QUEUE].length ? false :
    +      this[READENTRY] ? this[READENTRY].flowing :
    +      true
    + 
    +    // if we have no queue, then that means a clogged READENTRY
    +    if (!ret && !this[QUEUE].length)
    +      this[READENTRY].once('drain', _ => this.emit('drain'))
    + 
    +    return ret
    +  }
    + 
    +  [BUFFERCONCAT] (c) {
    +    if (c && !this[ABORTED])
    +      this[BUFFER] = this[BUFFER] ? Buffer.concat([this[BUFFER], c]) : c
    +  }
    + 
    +  [MAYBEEND] () {
    +    if (this[ENDED] && !this[EMITTEDEND] && !this[ABORTED]) {
    +      this[EMITTEDEND] = true
    +      const entry = this[WRITEENTRY]
    +      if (entry && entry.blockRemain) {
    +        const have = this[BUFFER] ? this[BUFFER].length : 0
    +        this.warn('Truncated input (needed ' + entry.blockRemain +
    +                  ' more bytes, only ' + have + ' available)', entry)
    +        if (this[BUFFER])
    +          entry.write(this[BUFFER])
    +        entry.end()
    +      }
    +      this[EMIT](DONE)
    +    }
    +  }
    + 
    +  [CONSUMECHUNK] (chunk) {
    +    if (this[CONSUMING]) {
    +      this[BUFFERCONCAT](chunk)
    +    } else if (!chunk && !this[BUFFER]) {
    +      this[MAYBEEND]()
    +    } else {
    +      this[CONSUMING] = true
    +      if (this[BUFFER]) {
    +        this[BUFFERCONCAT](chunk)
    +        const c = this[BUFFER]
    +        this[BUFFER] = null
    +        this[CONSUMECHUNKSUB](c)
    +      } else {
    +        this[CONSUMECHUNKSUB](chunk)
    +      }
    + 
    +      while (this[BUFFER] && this[BUFFER].length >= 512 && !this[ABORTED]) {
    +        const c = this[BUFFER]
    +        this[BUFFER] = null
    +        this[CONSUMECHUNKSUB](c)
    +      }
    +      this[CONSUMING] = false
    +    }
    + 
    +    if (!this[BUFFER] || this[ENDED])
    +      this[MAYBEEND]()
    +  }
    + 
    +  [CONSUMECHUNKSUB] (chunk) {
    +    // we know that we are in CONSUMING mode, so anything written goes into
    +    // the buffer.  Advance the position and put any remainder in the buffer.
    +    let position = 0
    +    let length = chunk.length
    +    while (position + 512 <= length && !this[ABORTED]) {
    +      switch (this[STATE]) {
    +        case 'begin':
    +          this[CONSUMEHEADER](chunk, position)
    +          position += 512
    +          break
    + 
    +        case 'ignore':
    +        case 'body':
    +          position += this[CONSUMEBODY](chunk, position)
    +          break
    + 
    +        case 'meta':
    +          position += this[CONSUMEMETA](chunk, position)
    +          break
    + 
    +        /* istanbul ignore next */
    +        default:
    +          throw new Error('invalid state: ' + this[STATE])
    +      }
    +    }
    + 
    +    if (position < length) {
    +      if (this[BUFFER])
    +        this[BUFFER] = Buffer.concat([chunk.slice(position), this[BUFFER]])
    +      else
    +        this[BUFFER] = chunk.slice(position)
    +    }
    +  }
    + 
    +  end (chunk) {
    +    if (!this[ABORTED]) {
    +      if (this[UNZIP])
    +        this[UNZIP].end(chunk)
    +      else {
    +        this[ENDED] = true
    +        this.write(chunk)
    +      }
    +    }
    +  }
    +})
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pax.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pax.js.html new file mode 100644 index 0000000000000..ed0e937a1290d --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pax.js.html @@ -0,0 +1,500 @@ + + + + Code coverage report for tar/lib/pax.js + + + + + + + +
    +
    +

    + All files / tar/lib pax.js +

    +
    +
    + 100% + Statements + 62/62 +
    +
    + 100% + Branches + 75/75 +
    +
    + 100% + Functions + 9/9 +
    +
    + 100% + Lines + 60/60 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146  +11x +11x +  +  +  +435x +435x +435x +435x +435x +435x +435x +435x +435x +435x +435x +435x +435x +435x +435x +435x +  +  +  +34x +34x +1x +  +33x +  +  +33x +33x +  +  +33x +16896x +  +  +33x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +33x +  +  +33x +8949x +  +  +33x +  +  +  +34x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +510x +204x +306x +  +306x +  +  +  +306x +  +  +  +306x +306x +30x +306x +306x +  +  +  +401x +  +11x +401x +  +11x +401x +  +  +  +  +11x +2259x +  +  +  +2259x +5x +  +2254x +2254x +2254x +2254x +1x +  +2253x +2253x +  +  +  +2253x +  +  +11x + 
    'use strict'
    +const Header = require('./header.js')
    +const path = require('path')
    + 
    +class Pax {
    +  constructor (obj, global) {
    +    this.atime = obj.atime || null
    +    this.charset = obj.charset || null
    +    this.comment = obj.comment || null
    +    this.ctime = obj.ctime || null
    +    this.gid = obj.gid || null
    +    this.gname = obj.gname || null
    +    this.linkpath = obj.linkpath || null
    +    this.mtime = obj.mtime || null
    +    this.path = obj.path || null
    +    this.size = obj.size || null
    +    this.uid = obj.uid || null
    +    this.uname = obj.uname || null
    +    this.dev = obj.dev || null
    +    this.ino = obj.ino || null
    +    this.nlink = obj.nlink || null
    +    this.global = global || false
    +  }
    + 
    +  encode () {
    +    const body = this.encodeBody()
    +    if (body === '')
    +      return null
    + 
    +    const bodyLen = Buffer.byteLength(body)
    +    // round up to 512 bytes
    +    // add 512 for header
    +    const bufLen = 512 * Math.ceil(1 + bodyLen / 512)
    +    const buf = Buffer.allocUnsafe(bufLen)
    + 
    +    // 0-fill the header section, it might not hit every field
    +    for (let i = 0; i < 512; i++) {
    +      buf[i] = 0
    +    }
    + 
    +    new Header({
    +      // XXX split the path
    +      // then the path should be PaxHeader + basename, but less than 99,
    +      // prepend with the dirname
    +      path: ('PaxHeader/' + path.basename(this.path)).slice(0, 99),
    +      mode: this.mode || 0o644,
    +      uid: this.uid || null,
    +      gid: this.gid || null,
    +      size: bodyLen,
    +      mtime: this.mtime || null,
    +      type: this.global ? 'GlobalExtendedHeader' : 'ExtendedHeader',
    +      linkpath: '',
    +      uname: this.uname || '',
    +      gname: this.gname || '',
    +      devmaj: 0,
    +      devmin: 0,
    +      atime: this.atime || null,
    +      ctime: this.ctime || null
    +    }).encode(buf)
    + 
    +    buf.write(body, 512, bodyLen, 'utf8')
    + 
    +    // null pad after the body
    +    for (let i = bodyLen + 512; i < buf.length; i++) {
    +      buf[i] = 0
    +    }
    + 
    +    return buf
    +  }
    + 
    +  encodeBody () {
    +    return (
    +      this.encodeField('path') +
    +      this.encodeField('ctime') +
    +      this.encodeField('atime') +
    +      this.encodeField('dev') +
    +      this.encodeField('ino') +
    +      this.encodeField('nlink') +
    +      this.encodeField('charset') +
    +      this.encodeField('comment') +
    +      this.encodeField('gid') +
    +      this.encodeField('gname') +
    +      this.encodeField('linkpath') +
    +      this.encodeField('mtime') +
    +      this.encodeField('size') +
    +      this.encodeField('uid') +
    +      this.encodeField('uname')
    +    )
    +  }
    + 
    +  encodeField (field) {
    +    if (this[field] === null || this[field] === undefined)
    +      return ''
    +    const v = this[field] instanceof Date ? this[field].getTime() / 1000
    +      : this[field]
    +    const s = ' ' +
    +      (field === 'dev' || field === 'ino' || field === 'nlink'
    +       ? 'SCHILY.' : '') +
    +      field + '=' + v + '\n'
    +    const byteLen = Buffer.byteLength(s)
    +    // the digits includes the length of the digits in ascii base-10
    +    // so if it's 9 characters, then adding 1 for the 9 makes it 10
    +    // which makes it 11 chars.
    +    let digits = Math.floor(Math.log(byteLen) / Math.log(10)) + 1
    +    if (byteLen + digits >= Math.pow(10, digits))
    +      digits += 1
    +    const len = digits + byteLen
    +    return len + s
    +  }
    +}
    + 
    +Pax.parse = (string, ex, g) => new Pax(merge(parseKV(string), ex), g)
    + 
    +const merge = (a, b) =>
    +  b ? Object.keys(a).reduce((s, k) => (s[k] = a[k], s), b) : a
    + 
    +const parseKV = string =>
    +  string
    +    .replace(/\n$/, '')
    +    .split('\n')
    +    .reduce(parseKVLine, Object.create(null))
    + 
    +const parseKVLine = (set, line) => {
    +  const n = parseInt(line, 10)
    + 
    +  // XXX Values with \n in them will fail this.
    +  // Refactor to not be a naive line-by-line parse.
    +  if (n !== Buffer.byteLength(line) + 1)
    +    return set
    + 
    +  line = line.substr((n + ' ').length)
    +  const kv = line.split('=')
    +  const k = kv.shift().replace(/^SCHILY\.(dev|ino|nlink)/, '$1')
    +  if (!k)
    +    return set
    + 
    +  const v = kv.join('=')
    +  set[k] = /^([A-Z]+\.)?([mac]|birth|creation)time$/.test(k)
    +    ?  new Date(v * 1000)
    +    : /^[0-9]+$/.test(v) ? +v
    +    : v
    +  return set
    +}
    + 
    +module.exports = Pax
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/read-entry.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/read-entry.js.html new file mode 100644 index 0000000000000..9fca327a291bf --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/read-entry.js.html @@ -0,0 +1,347 @@ + + + + Code coverage report for tar/lib/read-entry.js + + + + + + + +
    +
    +

    + All files / tar/lib read-entry.js +

    +
    +
    + 100% + Statements + 53/53 +
    +
    + 100% + Branches + 36/36 +
    +
    + 100% + Functions + 3/3 +
    +
    + 100% + Lines + 51/51 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95  +11x +11x +  +11x +11x +  +4004x +4004x +4004x +4004x +4004x +4004x +4004x +4004x +4004x +4004x +4004x +  +  +  +  +  +  +  +  +  +  +3241x +  +  +  +  +  +  +  +760x +760x +  +  +  +  +3x +  +  +4004x +4004x +4004x +3720x +4004x +4004x +4004x +4004x +4004x +4004x +4004x +4004x +4004x +4004x +4004x +  +4004x +4004x +  +  +  +2222x +2222x +2x +  +2220x +2220x +2220x +2220x +2220x +673x +  +1547x +132x +  +  +1415x +  +  +  +457x +  +  +6384x +  +2657x +  +  +  + 
    'use strict'
    +const types = require('./types.js')
    +const MiniPass = require('minipass')
    + 
    +const SLURP = Symbol('slurp')
    +module.exports = class ReadEntry extends MiniPass {
    +  constructor (header, ex, gex) {
    +    super()
    +    this.extended = ex
    +    this.globalExtended = gex
    +    this.header = header
    +    this.startBlockSize = 512 * Math.ceil(header.size / 512)
    +    this.blockRemain = this.startBlockSize
    +    this.remain = header.size
    +    this.type = header.type
    +    this.meta = false
    +    this.ignore = false
    +    switch (this.type) {
    +      case 'File':
    +      case 'OldFile':
    +      case 'Link':
    +      case 'SymbolicLink':
    +      case 'CharacterDevice':
    +      case 'BlockDevice':
    +      case 'Directory':
    +      case 'FIFO':
    +      case 'ContiguousFile':
    +      case 'GNUDumpDir':
    +        break
    + 
    +      case 'NextFileHasLongLinkpath':
    +      case 'NextFileHasLongPath':
    +      case 'OldGnuLongPath':
    +      case 'GlobalExtendedHeader':
    +      case 'ExtendedHeader':
    +      case 'OldExtendedHeader':
    +        this.meta = true
    +        break
    + 
    +      // NOTE: gnutar and bsdtar treat unrecognized types as 'File'
    +      // it may be worth doing the same, but with a warning.
    +      default:
    +        this.ignore = true
    +    }
    + 
    +    this.path = header.path
    +    this.mode = header.mode
    +    if (this.mode)
    +      this.mode = this.mode & 0o7777
    +    this.uid = header.uid
    +    this.gid = header.gid
    +    this.uname = header.uname
    +    this.gname = header.gname
    +    this.size = header.size
    +    this.mtime = header.mtime
    +    this.atime = header.atime
    +    this.ctime = header.ctime
    +    this.linkpath = header.linkpath
    +    this.uname = header.uname
    +    this.gname = header.gname
    + 
    +    if (ex) this[SLURP](ex)
    +    if (gex) this[SLURP](gex, true)
    +  }
    + 
    +  write (data) {
    +    const writeLen = data.length
    +    if (writeLen > this.blockRemain)
    +      throw new Error('writing more to entry than is appropriate')
    + 
    +    const r = this.remain
    +    const br = this.blockRemain
    +    this.remain = Math.max(0, r - writeLen)
    +    this.blockRemain = Math.max(0, br - writeLen)
    +    if (this.ignore)
    +      return true
    + 
    +    if (r >= writeLen)
    +      return super.write(data)
    + 
    +    // r < writeLen
    +    return super.write(data.slice(0, r))
    +  }
    + 
    +  [SLURP] (ex, global) {
    +    for (let k in ex) {
    +      // we slurp in everything except for the path attribute in
    +      // a global extended header, because that's weird.
    +      if (ex[k] !== null && ex[k] !== undefined &&
    +          !(global && k === 'path'))
    +        this[k] = ex[k]
    +    }
    +  }
    +}
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/replace.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/replace.js.html new file mode 100644 index 0000000000000..e764c04fbfc45 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/replace.js.html @@ -0,0 +1,722 @@ + + + + Code coverage report for tar/lib/replace.js + + + + + + + +
    +
    +

    + All files / tar/lib replace.js +

    +
    +
    + 100% + Statements + 131/131 +
    +
    + 100% + Branches + 70/70 +
    +
    + 100% + Functions + 18/18 +
    +
    + 100% + Lines + 128/128 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220  +  +  +3x +3x +3x +3x +3x +3x +3x +  +  +  +  +  +  +  +3x +  +3x +70x +  +70x +1x +  +69x +1x +  +68x +1x +  +67x +  +67x +  +  +  +3x +26x +  +26x +  +  +  +26x +26x +26x +  +4x +2x +  +2x +  +  +24x +22x +  +22x +61x +63x +  +  +  +61x +2x +  +59x +2x +  +  +55x +55x +8x +47x +47x +2x +  +  +45x +45x +28x +  +18x +  +18x +  +26x +8x +  +  +  +3x +18x +  +  +  +18x +18x +  +  +3x +41x +41x +  +41x +37x +37x +4x +  +33x +  +  +37x +37x +8x +  +29x +29x +29x +112x +2x +110x +110x +6x +  +  +  +  +104x +2x +  +  +102x +4x +  +98x +98x +13x +  +85x +85x +4x +  +81x +81x +4x +  +77x +46x +77x +77x +  +29x +  +  +41x +41x +41x +41x +45x +4x +4x +  +  +41x +2x +  +39x +39x +2x +37x +37x +4x +33x +  +  +  +33x +33x +33x +33x +  +  +  +41x +  +  +41x +  +  +3x +18x +19x +1x +  +  +  +3x +  +  +18x +  +18x +  +  +3x +34x +33x +33x +1x +  +  +3x +1x +  +32x +  +33x +  + 
    'use strict'
    + 
    +// tar -r
    +const hlo = require('./high-level-opt.js')
    +const Pack = require('./pack.js')
    +const Parse = require('./parse.js')
    +const fs = require('fs')
    +const fsm = require('fs-minipass')
    +const t = require('./list.js')
    +const path = require('path')
    + 
    +// starting at the head of the file, read a Header
    +// If the checksum is invalid, that's our position to start writing
    +// If it is, jump forward by the specified size (round up to 512)
    +// and try again.
    +// Write the new Pack stream starting there.
    + 
    +const Header = require('./header.js')
    + 
    +const r = module.exports = (opt_, files, cb) => {
    +  const opt = hlo(opt_)
    + 
    +  if (!opt.file)
    +    throw new TypeError('file is required')
    + 
    +  if (opt.gzip)
    +    throw new TypeError('cannot append to compressed archives')
    + 
    +  if (!files || !Array.isArray(files) || !files.length)
    +    throw new TypeError('no files or directories specified')
    + 
    +  files = Array.from(files)
    + 
    +  return opt.sync ? replaceSync(opt, files)
    +    : replace(opt, files, cb)
    +}
    + 
    +const replaceSync = (opt, files) => {
    +  const p = new Pack.Sync(opt)
    + 
    +  let threw = true
    +  let fd
    +  let position
    + 
    +  try {
    +    try {
    +      fd = fs.openSync(opt.file, 'r+')
    +    } catch (er) {
    +      if (er.code === 'ENOENT')
    +        fd = fs.openSync(opt.file, 'w+')
    +      else
    +        throw er
    +    }
    + 
    +    const st = fs.fstatSync(fd)
    +    const headBuf = Buffer.alloc(512)
    + 
    +    POSITION: for (position = 0; position < st.size; position += 512) {
    +      for (let bufPos = 0, bytes = 0; bufPos < 512; bufPos += bytes) {
    +        bytes = fs.readSync(
    +          fd, headBuf, bufPos, headBuf.length - bufPos, position + bufPos
    +        )
    + 
    +        if (position === 0 && headBuf[0] === 0x1f && headBuf[1] === 0x8b)
    +          throw new Error('cannot append to compressed archives')
    + 
    +        if (!bytes)
    +          break POSITION
    +      }
    + 
    +      let h = new Header(headBuf)
    +      if (!h.cksumValid)
    +        break
    +      let entryBlockSize = 512 * Math.ceil(h.size / 512)
    +      if (position + entryBlockSize + 512 > st.size)
    +        break
    +      // the 512 for the header we just parsed will be added as well
    +      // also jump ahead all the blocks for the body
    +      position += entryBlockSize
    +      if (opt.mtimeCache)
    +        opt.mtimeCache.set(h.path, h.mtime)
    +    }
    +    threw = false
    + 
    +    streamSync(opt, p, position, fd, files)
    +  } finally {
    +    if (threw)
    +      try { fs.closeSync(fd) } catch (er) {}
    +  }
    +}
    + 
    +const streamSync = (opt, p, position, fd, files) => {
    +  const stream = new fsm.WriteStreamSync(opt.file, {
    +    fd: fd,
    +    start: position
    +  })
    +  p.pipe(stream)
    +  addFilesSync(p, files)
    +}
    + 
    +const replace = (opt, files, cb) => {
    +  files = Array.from(files)
    +  const p = new Pack(opt)
    + 
    +  const getPos = (fd, size, cb_) => {
    +    const cb = (er, pos) => {
    +      if (er)
    +        fs.close(fd, _ => cb_(er))
    +      else
    +        cb_(null, pos)
    +    }
    + 
    +    let position = 0
    +    if (size === 0)
    +      return cb(null, 0)
    + 
    +    let bufPos = 0
    +    const headBuf = Buffer.alloc(512)
    +    const onread = (er, bytes) => {
    +      if (er)
    +        return cb(er)
    +      bufPos += bytes
    +      if (bufPos < 512 && bytes)
    +        return fs.read(
    +          fd, headBuf, bufPos, headBuf.length - bufPos,
    +          position + bufPos, onread
    +        )
    + 
    +      if (position === 0 && headBuf[0] === 0x1f && headBuf[1] === 0x8b)
    +        return cb(new Error('cannot append to compressed archives'))
    + 
    +      // truncated header
    +      if (bufPos < 512)
    +        return cb(null, position)
    + 
    +      const h = new Header(headBuf)
    +      if (!h.cksumValid)
    +        return cb(null, position)
    + 
    +      const entryBlockSize = 512 * Math.ceil(h.size / 512)
    +      if (position + entryBlockSize + 512 > size)
    +        return cb(null, position)
    + 
    +      position += entryBlockSize + 512
    +      if (position >= size)
    +        return cb(null, position)
    + 
    +      if (opt.mtimeCache)
    +        opt.mtimeCache.set(h.path, h.mtime)
    +      bufPos = 0
    +      fs.read(fd, headBuf, 0, 512, position, onread)
    +    }
    +    fs.read(fd, headBuf, 0, 512, position, onread)
    +  }
    + 
    +  const promise = new Promise((resolve, reject) => {
    +    p.on('error', reject)
    +    let flag = 'r+'
    +    const onopen = (er, fd) => {
    +      if (er && er.code === 'ENOENT' && flag === 'r+') {
    +        flag = 'w+'
    +        return fs.open(opt.file, flag, onopen)
    +      }
    + 
    +      if (er)
    +        return reject(er)
    + 
    +      fs.fstat(fd, (er, st) => {
    +        if (er)
    +          return reject(er)
    +        getPos(fd, st.size, (er, position) => {
    +          if (er)
    +            return reject(er)
    +          const stream = new fsm.WriteStream(opt.file, {
    +            fd: fd,
    +            start: position
    +          })
    +          p.pipe(stream)
    +          stream.on('error', reject)
    +          stream.on('close', resolve)
    +          addFilesAsync(p, files)
    +        })
    +      })
    +    }
    +    fs.open(opt.file, flag, onopen)
    +  })
    + 
    +  return cb ? promise.then(cb, cb) : promise
    +}
    + 
    +const addFilesSync = (p, files) => {
    +  files.forEach(file => {
    +    if (file.charAt(0) === '@')
    +      t({
    +        file: path.resolve(p.cwd, file.substr(1)),
    +        sync: true,
    +        noResume: true,
    +        onentry: entry => p.add(entry)
    +      })
    +    else
    +      p.add(file)
    +  })
    +  p.end()
    +}
    + 
    +const addFilesAsync = (p, files) => {
    +  while (files.length) {
    +    const file = files.shift()
    +    if (file.charAt(0) === '@')
    +      return t({
    +        file: path.resolve(p.cwd, file.substr(1)),
    +        noResume: true,
    +        onentry: entry => p.add(entry)
    +      }).then(_ => addFilesAsync(p, files))
    +    else
    +      p.add(file)
    +  }
    +  p.end()
    +}
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/types.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/types.js.html new file mode 100644 index 0000000000000..ad8de07618248 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/types.js.html @@ -0,0 +1,197 @@ + + + + Code coverage report for tar/lib/types.js + + + + + + + +
    +
    +

    + All files / tar/lib types.js +

    +
    +
    + 100% + Statements + 3/3 +
    +
    + 100% + Branches + 0/0 +
    +
    + 100% + Functions + 1/1 +
    +
    + 100% + Lines + 2/2 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45  +  +14x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +294x + 
    'use strict'
    +// map types from key to human-friendly name
    +exports.name = new Map([
    +  ['0', 'File'],
    +  // same as File
    +  ['', 'OldFile'],
    +  ['1', 'Link'],
    +  ['2', 'SymbolicLink'],
    +  // Devices and FIFOs aren't fully supported
    +  // they are parsed, but skipped when unpacking
    +  ['3', 'CharacterDevice'],
    +  ['4', 'BlockDevice'],
    +  ['5', 'Directory'],
    +  ['6', 'FIFO'],
    +  // same as File
    +  ['7', 'ContiguousFile'],
    +  // pax headers
    +  ['g', 'GlobalExtendedHeader'],
    +  ['x', 'ExtendedHeader'],
    +  // vendor-specific stuff
    +  // skip
    +  ['A', 'SolarisACL'],
    +  // like 5, but with data, which should be skipped
    +  ['D', 'GNUDumpDir'],
    +  // metadata only, skip
    +  ['I', 'Inode'],
    +  // data = link path of next file
    +  ['K', 'NextFileHasLongLinkpath'],
    +  // data = path of next file
    +  ['L', 'NextFileHasLongPath'],
    +  // skip
    +  ['M', 'ContinuationFile'],
    +  // like L
    +  ['N', 'OldGnuLongPath'],
    +  // skip
    +  ['S', 'SparseFile'],
    +  // skip
    +  ['V', 'TapeVolumeHeader'],
    +  // like x
    +  ['X', 'OldExtendedHeader']
    +])
    + 
    +// map the other direction
    +exports.code = new Map(Array.from(exports.name).map(kv => [kv[1], kv[0]]))
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/unpack.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/unpack.js.html new file mode 100644 index 0000000000000..240a6fa310f66 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/unpack.js.html @@ -0,0 +1,1604 @@ + + + + Code coverage report for tar/lib/unpack.js + + + + + + + +
    +
    +

    + All files / tar/lib unpack.js +

    +
    +
    + 100% + Statements + 254/254 +
    +
    + 100% + Branches + 194/194 +
    +
    + 100% + Functions + 44/44 +
    +
    + 100% + Lines + 247/247 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402 +403 +404 +405 +406 +407 +408 +409 +410 +411 +412 +413 +414 +415 +416 +417 +418 +419 +420 +421 +422 +423 +424 +425 +426 +427 +428 +429 +430 +431 +432 +433 +434 +435 +436 +437 +438 +439 +440 +441 +442 +443 +444 +445 +446 +447 +448 +449 +450 +451 +452 +453 +454 +455 +456 +457 +458 +459 +460 +461 +462 +463 +464 +465 +466 +467 +468 +469 +470 +471 +472 +473 +474 +475 +476 +477 +478 +479 +480 +481 +482 +483 +484 +485 +486 +487 +488 +489 +490 +491 +492 +493 +494 +495 +496 +497 +498 +499 +500 +501 +502 +503 +504 +505 +506 +507 +508 +509 +510 +511 +512 +513 +514  +  +3x +3x +3x +3x +3x +3x +3x +3x +3x +  +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +3x +  +  +3x +60x +  +  +  +  +  +134x +4x +  +134x +109x +109x +  +  +134x +  +134x +134x +  +134x +134x +  +134x +  +134x +  +9x +2x +7x +1x +  +6x +6x +6x +  +125x +125x +125x +  +  +  +131x +119x +  +12x +  +131x +  +131x +  +  +  +131x +  +  +131x +  +  +131x +  +  +131x +  +  +  +  +131x +  +  +  +131x +  +131x +131x +131x +131x +  +131x +131x +571x +  +  +  +473x +98x +98x +98x +98x +  +  +  +  +571x +144x +144x +9x +135x +  +  +562x +545x +545x +2x +2x +  +  +  +  +543x +2x +2x +2x +  +  +  +  +560x +3x +3x +  +  +  +560x +2x +  +558x +  +560x +  +  +  +571x +11x +  +560x +  +560x +  +  +179x +140x +  +  +  +  +  +  +554x +  +  +  +  +6x +  +  +  +  +  +  +  +39x +12x +  +27x +27x +27x +  +  +  +  +451x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +473x +  +  +  +  +  +  +  +  +30x +  +  +  +30x +  +  +  +221x +221x +  +  +  +221x +  +221x +221x +421x +1x +1x +  +  +421x +219x +  +  +221x +219x +192x +192x +  +  +219x +10x +10x +  +  +219x +  +  +221x +  +  +  +97x +97x +97x +3x +  +94x +94x +171x +94x +94x +  +  +  +94x +73x +73x +  +  +94x +4x +4x +  +  +94x +  +  +  +  +6x +6x +  +  +  +21x +  +  +  +19x +  +  +  +354x +  +  +  +364x +364x +  +  +  +4x +4x +  +  +  +  +354x +354x +354x +12x +342x +342x +2x +340x +318x +22x +16x +11x +9x +  +2x +  +5x +  +6x +  +  +  +  +  +528x +1x +  +527x +  +  +  +314x +  +  +19x +  +  +21x +  +  +  +173x +  +  +  +  +  +21x +21x +1x +20x +20x +  +  +  +  +  +  +59x +  +  +  +200x +200x +9x +191x +191x +17x +2x +15x +2x +  +13x +13x +6x +3x +2x +  +3x +  +7x +12x +  +1x +  +  +  +174x +  +  +  +  +93x +  +93x +6x +6x +  +  +  +  +93x +93x +  +1x +  +  +92x +86x +86x +  +1x +  +  +  +92x +86x +86x +58x +  +85x +12x +  +82x +  +4x +  +  +  +  +  +  +76x +76x +76x +1x +75x +56x +56x +  +  +75x +4x +4x +  +  +75x +  +  +  +276x +276x +  +  +  +  +  +  +  +  +  +  +  +  +4x +  +  +  +  +19x +19x +17x +  +2x +  +  +  +  +3x +3x + 
    'use strict'
    + 
    +const assert = require('assert')
    +const EE = require('events').EventEmitter
    +const Parser = require('./parse.js')
    +const fs = require('fs')
    +const fsm = require('fs-minipass')
    +const path = require('path')
    +const mkdir = require('./mkdir.js')
    +const mkdirSync = mkdir.sync
    +const wc = require('./winchars.js')
    + 
    +const ONENTRY = Symbol('onEntry')
    +const CHECKFS = Symbol('checkFs')
    +const MAKEFS = Symbol('makeFs')
    +const FILE = Symbol('file')
    +const DIRECTORY = Symbol('directory')
    +const LINK = Symbol('link')
    +const SYMLINK = Symbol('symlink')
    +const HARDLINK = Symbol('hardlink')
    +const UNSUPPORTED = Symbol('unsupported')
    +const UNKNOWN = Symbol('unknown')
    +const CHECKPATH = Symbol('checkPath')
    +const MKDIR = Symbol('mkdir')
    +const ONERROR = Symbol('onError')
    +const PENDING = Symbol('pending')
    +const PEND = Symbol('pend')
    +const UNPEND = Symbol('unpend')
    +const ENDED = Symbol('ended')
    +const MAYBECLOSE = Symbol('maybeClose')
    +const SKIP = Symbol('skip')
    +const DOCHOWN = Symbol('doChown')
    +const UID = Symbol('uid')
    +const GID = Symbol('gid')
    + 
    +// this.gid, entry.gid, this.processUid
    +const uint32 = (a, b, c) =>
    +  a === a >>> 0 ? a
    +  : b === b >>> 0 ? b
    +  : c
    + 
    +class Unpack extends Parser {
    +  constructor (opt) {
    +    if (!opt)
    +      opt = {}
    + 
    +    opt.ondone = _ => {
    +      this[ENDED] = true
    +      this[MAYBECLOSE]()
    +    }
    + 
    +    super(opt)
    + 
    +    this.writable = true
    +    this.readable = false
    + 
    +    this[PENDING] = 0
    +    this[ENDED] = false
    + 
    +    this.dirCache = opt.dirCache || new Map()
    + 
    +    if (typeof opt.uid === 'number' || typeof opt.gid === 'number') {
    +      // need both or neither
    +      if (typeof opt.uid !== 'number' || typeof opt.gid !== 'number')
    +        throw new TypeError('cannot set owner without number uid and gid')
    +      if (opt.preserveOwner)
    +        throw new TypeError(
    +          'cannot preserve owner in archive and also set owner explicitly')
    +      this.uid = opt.uid
    +      this.gid = opt.gid
    +      this.setOwner = true
    +    } else {
    +      this.uid = null
    +      this.gid = null
    +      this.setOwner = false
    +    }
    + 
    +    // default true for root
    +    if (opt.preserveOwner === undefined && typeof opt.uid !== 'number')
    +      this.preserveOwner = process.getuid && process.getuid() === 0
    +    else
    +      this.preserveOwner = !!opt.preserveOwner
    + 
    +    this.processUid = (this.preserveOwner || this.setOwner) && process.getuid ?
    +      process.getuid() : null
    +    this.processGid = (this.preserveOwner || this.setOwner) && process.getgid ?
    +      process.getgid() : null
    + 
    +    // turn ><?| in filenames into 0xf000-higher encoded forms
    +    this.win32 = !!opt.win32 || process.platform === 'win32'
    + 
    +    // do not unpack over files that are newer than what's in the archive
    +    this.newer = !!opt.newer
    + 
    +    // do not unpack over ANY files
    +    this.keep = !!opt.keep
    + 
    +    // do not set mtime/atime of extracted entries
    +    this.noMtime = !!opt.noMtime
    + 
    +    // allow .., absolute path entries, and unpacking through symlinks
    +    // without this, warn and skip .., relativize absolutes, and error
    +    // on symlinks in extraction path
    +    this.preservePaths = !!opt.preservePaths
    + 
    +    // unlink files and links before writing. This breaks existing hard
    +    // links, and removes symlink directories rather than erroring
    +    this.unlink = !!opt.unlink
    + 
    +    this.cwd = path.resolve(opt.cwd || process.cwd())
    +    this.strip = +opt.strip || 0
    +    this.processUmask = process.umask()
    +    this.umask = typeof opt.umask === 'number' ? opt.umask : this.processUmask
    +    // default mode for dirs created as parents
    +    this.dmode = opt.dmode || (0o0777 & (~this.umask))
    +    this.fmode = opt.fmode || (0o0666 & (~this.umask))
    +    this.on('entry', entry => this[ONENTRY](entry))
    +  }
    + 
    +  [MAYBECLOSE] () {
    +    if (this[ENDED] && this[PENDING] === 0) {
    +      this.emit('prefinish')
    +      this.emit('finish')
    +      this.emit('end')
    +      this.emit('close')
    +    }
    +  }
    + 
    +  [CHECKPATH] (entry) {
    +    if (this.strip) {
    +      const parts = entry.path.split(/\/|\\/)
    +      if (parts.length < this.strip)
    +        return false
    +      entry.path = parts.slice(this.strip).join('/')
    +    }
    + 
    +    if (!this.preservePaths) {
    +      const p = entry.path
    +      if (p.match(/(^|\/|\\)\.\.(\\|\/|$)/)) {
    +        this.warn('path contains \'..\'', p)
    +        return false
    +      }
    + 
    +      // absolutes on posix are also absolutes on win32
    +      // so we only need to test this one to get both
    +      if (path.win32.isAbsolute(p)) {
    +        const parsed = path.win32.parse(p)
    +        this.warn('stripping ' + parsed.root + ' from absolute path', p)
    +        entry.path = p.substr(parsed.root.length)
    +      }
    +    }
    + 
    +    // only encode : chars that aren't drive letter indicators
    +    if (this.win32) {
    +      const parsed = path.win32.parse(entry.path)
    +      entry.path = parsed.root === '' ? wc.encode(entry.path)
    +        : parsed.root + wc.encode(entry.path.substr(parsed.root.length))
    +    }
    + 
    +    if (path.isAbsolute(entry.path))
    +      entry.absolute = entry.path
    +    else
    +      entry.absolute = path.resolve(this.cwd, entry.path)
    + 
    +    return true
    +  }
    + 
    +  [ONENTRY] (entry) {
    +    if (!this[CHECKPATH](entry))
    +      return entry.resume()
    + 
    +    assert.equal(typeof entry.absolute, 'string')
    + 
    +    switch (entry.type) {
    +      case 'Directory':
    +      case 'GNUDumpDir':
    +        if (entry.mode)
    +          entry.mode = entry.mode | 0o700
    + 
    +      case 'File':
    +      case 'OldFile':
    +      case 'ContiguousFile':
    +      case 'Link':
    +      case 'SymbolicLink':
    +        return this[CHECKFS](entry)
    + 
    +      case 'CharacterDevice':
    +      case 'BlockDevice':
    +      case 'FIFO':
    +        return this[UNSUPPORTED](entry)
    +    }
    +  }
    + 
    +  [ONERROR] (er, entry) {
    +    // Cwd has to exist, or else nothing works. That's serious.
    +    // Other errors are warnings, which raise the error in strict
    +    // mode, but otherwise continue on.
    +    if (er.name === 'CwdError')
    +      this.emit('error', er)
    +    else {
    +      this.warn(er.message, er)
    +      this[UNPEND]()
    +      entry.resume()
    +    }
    +  }
    + 
    +  [MKDIR] (dir, mode, cb) {
    +    mkdir(dir, {
    +      uid: this.uid,
    +      gid: this.gid,
    +      processUid: this.processUid,
    +      processGid: this.processGid,
    +      umask: this.processUmask,
    +      preserve: this.preservePaths,
    +      unlink: this.unlink,
    +      cache: this.dirCache,
    +      cwd: this.cwd,
    +      mode: mode
    +    }, cb)
    +  }
    + 
    +  [DOCHOWN] (entry) {
    +    // in preserve owner mode, chown if the entry doesn't match process
    +    // in set owner mode, chown if setting doesn't match process
    +    return this.preserveOwner &&
    +      ( typeof entry.uid === 'number' && entry.uid !== this.processUid ||
    +        typeof entry.gid === 'number' && entry.gid !== this.processGid )
    +      ||
    +      ( typeof this.uid === 'number' && this.uid !== this.processUid ||
    +        typeof this.gid === 'number' && this.gid !== this.processGid )
    +  }
    + 
    +  [UID] (entry) {
    +    return uint32(this.uid, entry.uid, this.processUid)
    +  }
    + 
    +  [GID] (entry) {
    +    return uint32(this.gid, entry.gid, this.processGid)
    +  }
    + 
    +  [FILE] (entry) {
    +    const mode = entry.mode & 0o7777 || this.fmode
    +    const stream = new fsm.WriteStream(entry.absolute, {
    +      mode: mode,
    +      autoClose: false
    +    })
    +    stream.on('error', er => this[ONERROR](er, entry))
    + 
    +    let actions = 1
    +    const done = er => {
    +      if (er) {
    +        this[ONERROR](er, entry)
    +        actions = 1
    +      }
    + 
    +      if (--actions === 0)
    +        fs.close(stream.fd, _ => this[UNPEND]())
    +    }
    + 
    +    stream.on('finish', _ => {
    +      if (entry.mtime && !this.noMtime) {
    +        actions++
    +        fs.futimes(stream.fd, entry.atime || new Date(), entry.mtime, done)
    +      }
    + 
    +      if (this[DOCHOWN](entry)) {
    +        actions++
    +        fs.fchown(stream.fd, this[UID](entry), this[GID](entry), done)
    +      }
    + 
    +      done()
    +    })
    + 
    +    entry.pipe(stream)
    +  }
    + 
    +  [DIRECTORY] (entry) {
    +    const mode = entry.mode & 0o7777 || this.dmode
    +    this[MKDIR](entry.absolute, mode, er => {
    +      if (er)
    +        return this[ONERROR](er, entry)
    + 
    +      let actions = 1
    +      const done = _ => {
    +        if (--actions === 0) {
    +          this[UNPEND]()
    +          entry.resume()
    +        }
    +      }
    + 
    +      if (entry.mtime && !this.noMtime) {
    +        actions++
    +        fs.utimes(entry.absolute, entry.atime || new Date(), entry.mtime, done)
    +      }
    + 
    +      if (this[DOCHOWN](entry)) {
    +        actions++
    +        fs.chown(entry.absolute, this[UID](entry), this[GID](entry), done)
    +      }
    + 
    +      done()
    +    })
    +  }
    + 
    +  [UNSUPPORTED] (entry) {
    +    this.warn('unsupported entry type: ' + entry.type, entry)
    +    entry.resume()
    +  }
    + 
    +  [SYMLINK] (entry) {
    +    this[LINK](entry, entry.linkpath, 'symlink')
    +  }
    + 
    +  [HARDLINK] (entry) {
    +    this[LINK](entry, path.resolve(this.cwd, entry.linkpath), 'link')
    +  }
    + 
    +  [PEND] () {
    +    this[PENDING]++
    +  }
    + 
    +  [UNPEND] () {
    +    this[PENDING]--
    +    this[MAYBECLOSE]()
    +  }
    + 
    +  [SKIP] (entry) {
    +    this[UNPEND]()
    +    entry.resume()
    +  }
    + 
    +  // check if a thing is there, and if so, try to clobber it
    +  [CHECKFS] (entry) {
    +    this[PEND]()
    +    this[MKDIR](path.dirname(entry.absolute), this.dmode, er => {
    +      if (er)
    +        return this[ONERROR](er, entry)
    +      fs.lstat(entry.absolute, (er, st) => {
    +        if (st && (this.keep || this.newer && st.mtime > entry.mtime))
    +          this[SKIP](entry)
    +        else if (er || (entry.type === 'File' && !this.unlink && st.isFile()))
    +          this[MAKEFS](null, entry)
    +        else if (st.isDirectory()) {
    +          if (entry.type === 'Directory') {
    +            if (!entry.mode || (st.mode & 0o7777) === entry.mode)
    +              this[MAKEFS](null, entry)
    +            else
    +              fs.chmod(entry.absolute, entry.mode, er => this[MAKEFS](er, entry))
    +          } else
    +            fs.rmdir(entry.absolute, er => this[MAKEFS](er, entry))
    +        } else
    +          fs.unlink(entry.absolute, er => this[MAKEFS](er, entry))
    +      })
    +    })
    +  }
    + 
    +  [MAKEFS] (er, entry) {
    +    if (er)
    +      return this[ONERROR](er, entry)
    + 
    +    switch (entry.type) {
    +      case 'File':
    +      case 'OldFile':
    +      case 'ContiguousFile':
    +        return this[FILE](entry)
    + 
    +      case 'Link':
    +        return this[HARDLINK](entry)
    + 
    +      case 'SymbolicLink':
    +        return this[SYMLINK](entry)
    + 
    +      case 'Directory':
    +      case 'GNUDumpDir':
    +        return this[DIRECTORY](entry)
    +    }
    +  }
    + 
    +  [LINK] (entry, linkpath, link) {
    +    // XXX: get the type ('file' or 'dir') for windows
    +    fs[link](linkpath, entry.absolute, er => {
    +      if (er)
    +        return this[ONERROR](er, entry)
    +      this[UNPEND]()
    +      entry.resume()
    +    })
    +  }
    +}
    + 
    +class UnpackSync extends Unpack {
    +  constructor (opt) {
    +    super(opt)
    +  }
    + 
    +  [CHECKFS] (entry) {
    +    const er = this[MKDIR](path.dirname(entry.absolute), this.dmode)
    +    if (er)
    +      return this[ONERROR](er, entry)
    +    try {
    +      const st = fs.lstatSync(entry.absolute)
    +      if (this.keep || this.newer && st.mtime > entry.mtime)
    +        return this[SKIP](entry)
    +      else if (entry.type === 'File' && !this.unlink && st.isFile())
    +        return this[MAKEFS](null, entry)
    +      else {
    +        try {
    +          if (st.isDirectory()) {
    +            if (entry.type === 'Directory') {
    +              if (entry.mode && (st.mode & 0o7777) !== entry.mode)
    +                fs.chmodSync(entry.absolute, entry.mode)
    +            } else
    +              fs.rmdirSync(entry.absolute)
    +          } else
    +            fs.unlinkSync(entry.absolute)
    +          return this[MAKEFS](null, entry)
    +        } catch (er) {
    +          return this[ONERROR](er, entry)
    +        }
    +      }
    +    } catch (er) {
    +      return this[MAKEFS](null, entry)
    +    }
    +  }
    + 
    +  [FILE] (entry) {
    +    const mode = entry.mode & 0o7777 || this.fmode
    + 
    +    const oner = er => {
    +      try { fs.closeSync(fd) } catch (_) {}
    +      this[ONERROR](er, entry)
    +    }
    + 
    +    let stream
    +    let fd
    +    try {
    +      fd = fs.openSync(entry.absolute, 'w', mode)
    +    } catch (er) {
    +      return oner(er)
    +    }
    + 
    +    entry.on('data', chunk => {
    +      try {
    +        fs.writeSync(fd, chunk, 0, chunk.length)
    +      } catch (er) {
    +        oner(er)
    +      }
    +    })
    + 
    +    entry.on('end', _ => {
    +      try {
    +        if (entry.mtime && !this.noMtime)
    +          fs.futimesSync(fd, entry.atime || new Date(), entry.mtime)
    + 
    +        if (this[DOCHOWN](entry))
    +          fs.fchownSync(fd, this[UID](entry), this[GID](entry))
    + 
    +        fs.closeSync(fd)
    +      } catch (er) {
    +        return oner(er)
    +      }
    +    })
    + 
    +  }
    + 
    +  [DIRECTORY] (entry) {
    +    const mode = entry.mode & 0o7777 || this.dmode
    +    const er = this[MKDIR](entry.absolute, mode)
    +    if (er)
    +      return this[ONERROR](er, entry)
    +    if (entry.mtime && !this.noMtime) {
    +      try {
    +        fs.utimesSync(entry.absolute, entry.atime || new Date(), entry.mtime)
    +      } catch (er) {}
    +    }
    +    if (this[DOCHOWN](entry)) {
    +      try {
    +        fs.chownSync(entry.absolute, this[UID](entry), this[GID](entry))
    +      } catch (er) {}
    +    }
    +    entry.resume()
    +  }
    + 
    +  [MKDIR] (dir, mode) {
    +    try {
    +      return mkdir.sync(dir, {
    +        uid: this.uid,
    +        gid: this.gid,
    +        processUid: this.processUid,
    +        processGid: this.processGid,
    +        umask: this.processUmask,
    +        preserve: this.preservePaths,
    +        unlink: this.unlink,
    +        cache: this.dirCache,
    +        cwd: this.cwd,
    +        mode: mode
    +      })
    +    } catch (er) {
    +      return er
    +    }
    +  }
    + 
    +  [LINK] (entry, linkpath, link) {
    +    try {
    +      fs[link + 'Sync'](linkpath, entry.absolute)
    +      entry.resume()
    +    } catch (er) {
    +      return this[ONERROR](er, entry)
    +    }
    +  }
    +}
    + 
    +Unpack.Sync = UnpackSync
    +module.exports = Unpack
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/update.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/update.js.html new file mode 100644 index 0000000000000..531cddef483e9 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/update.js.html @@ -0,0 +1,173 @@ + + + + Code coverage report for tar/lib/update.js + + + + + + + +
    +
    +

    + All files / tar/lib update.js +

    +
    +
    + 100% + Statements + 20/20 +
    +
    + 100% + Branches + 15/15 +
    +
    + 100% + Functions + 4/4 +
    +
    + 100% + Lines + 20/20 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37  +  +  +  +2x +2x +  +  +2x +36x +  +36x +1x +  +35x +1x +  +34x +1x +  +33x +  +33x +33x +  +  +2x +33x +  +33x +32x +  +33x +2x +24x +  + 
    'use strict'
    + 
    +// tar -u
    + 
    +const hlo = require('./high-level-opt.js')
    +const r = require('./replace.js')
    +// just call tar.r with the filter and mtimeCache
    + 
    +const u = module.exports = (opt_, files, cb) => {
    +  const opt = hlo(opt_)
    + 
    +  if (!opt.file)
    +    throw new TypeError('file is required')
    + 
    +  if (opt.gzip)
    +    throw new TypeError('cannot append to compressed archives')
    + 
    +  if (!files || !Array.isArray(files) || !files.length)
    +    throw new TypeError('no files or directories specified')
    + 
    +  files = Array.from(files)
    + 
    +  mtimeFilter(opt)
    +  return r(opt, files, cb)
    +}
    + 
    +const mtimeFilter = opt => {
    +  const filter = opt.filter
    + 
    +  if (!opt.mtimeCache)
    +    opt.mtimeCache = new Map()
    + 
    +  opt.filter = filter ? (path, stat) =>
    +    filter(path, stat) && !(opt.mtimeCache.get(path) > stat.mtime)
    +    : (path, stat) => !(opt.mtimeCache.get(path) > stat.mtime)
    +}
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/warn-mixin.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/warn-mixin.js.html new file mode 100644 index 0000000000000..99aa9f3498cc8 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/warn-mixin.js.html @@ -0,0 +1,107 @@ + + + + Code coverage report for tar/lib/warn-mixin.js + + + + + + + +
    +
    +

    + All files / tar/lib warn-mixin.js +

    +
    +
    + 100% + Statements + 9/9 +
    +
    + 100% + Branches + 4/4 +
    +
    + 100% + Functions + 2/2 +
    +
    + 100% + Lines + 8/8 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15  +27x +  +333x +184x +149x +2x +  +147x +147x +147x +  +  +  + 
    'use strict'
    +module.exports = Base => class extends Base {
    +  warn (msg, data) {
    +    if (!this.strict)
    +      this.emit('warn', msg, data)
    +    else if (data instanceof Error)
    +      this.emit('error', data)
    +    else {
    +      const er = new Error(msg)
    +      er.data = data
    +      this.emit('error', er)
    +    }
    +  }
    +}
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/winchars.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/winchars.js.html new file mode 100644 index 0000000000000..8e9fb65904602 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/winchars.js.html @@ -0,0 +1,134 @@ + + + + Code coverage report for tar/lib/winchars.js + + + + + + + +
    +
    +

    + All files / tar/lib winchars.js +

    +
    +
    + 100% + Statements + 12/12 +
    +
    + 100% + Branches + 0/0 +
    +
    + 100% + Functions + 7/7 +
    +
    + 100% + Lines + 8/8 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24  +  +  +  +  +9x +  +  +  +  +  +  +  +9x +45x +  +45x +45x +  +9x +30x +20x +  + 
    'use strict'
    + 
    +// When writing files on Windows, translate the characters to their
    +// 0xf000 higher-encoded versions.
    + 
    +const raw = [
    +  '|',
    +  '<',
    +  '>',
    +  '?',
    +  ':'
    +]
    + 
    +const win = raw.map(char =>
    +  String.fromCharCode(0xf000 + char.charCodeAt(0)))
    + 
    +const toWin = new Map(raw.map((char, i) => [char, win[i]]))
    +const toRaw = new Map(win.map((char, i) => [char, raw[i]]))
    + 
    +module.exports = {
    +  encode: s => raw.reduce((s, c) => s.split(c).join(toWin.get(c)), s),
    +  decode: s => win.reduce((s, c) => s.split(c).join(toRaw.get(c)), s)
    +}
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/write-entry.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/write-entry.js.html new file mode 100644 index 0000000000000..ba22b99475455 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/write-entry.js.html @@ -0,0 +1,1268 @@ + + + + Code coverage report for tar/lib/write-entry.js + + + + + + + +
    +
    +

    + All files / tar/lib write-entry.js +

    +
    +
    + 99.53% + Statements + 213/214 +
    +
    + 97.87% + Branches + 184/188 +
    +
    + 100% + Functions + 31/31 +
    +
    + 99.53% + Lines + 210/211 +
    +
    +
    +
    +
    
    +
    +
    1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +11 +12 +13 +14 +15 +16 +17 +18 +19 +20 +21 +22 +23 +24 +25 +26 +27 +28 +29 +30 +31 +32 +33 +34 +35 +36 +37 +38 +39 +40 +41 +42 +43 +44 +45 +46 +47 +48 +49 +50 +51 +52 +53 +54 +55 +56 +57 +58 +59 +60 +61 +62 +63 +64 +65 +66 +67 +68 +69 +70 +71 +72 +73 +74 +75 +76 +77 +78 +79 +80 +81 +82 +83 +84 +85 +86 +87 +88 +89 +90 +91 +92 +93 +94 +95 +96 +97 +98 +99 +100 +101 +102 +103 +104 +105 +106 +107 +108 +109 +110 +111 +112 +113 +114 +115 +116 +117 +118 +119 +120 +121 +122 +123 +124 +125 +126 +127 +128 +129 +130 +131 +132 +133 +134 +135 +136 +137 +138 +139 +140 +141 +142 +143 +144 +145 +146 +147 +148 +149 +150 +151 +152 +153 +154 +155 +156 +157 +158 +159 +160 +161 +162 +163 +164 +165 +166 +167 +168 +169 +170 +171 +172 +173 +174 +175 +176 +177 +178 +179 +180 +181 +182 +183 +184 +185 +186 +187 +188 +189 +190 +191 +192 +193 +194 +195 +196 +197 +198 +199 +200 +201 +202 +203 +204 +205 +206 +207 +208 +209 +210 +211 +212 +213 +214 +215 +216 +217 +218 +219 +220 +221 +222 +223 +224 +225 +226 +227 +228 +229 +230 +231 +232 +233 +234 +235 +236 +237 +238 +239 +240 +241 +242 +243 +244 +245 +246 +247 +248 +249 +250 +251 +252 +253 +254 +255 +256 +257 +258 +259 +260 +261 +262 +263 +264 +265 +266 +267 +268 +269 +270 +271 +272 +273 +274 +275 +276 +277 +278 +279 +280 +281 +282 +283 +284 +285 +286 +287 +288 +289 +290 +291 +292 +293 +294 +295 +296 +297 +298 +299 +300 +301 +302 +303 +304 +305 +306 +307 +308 +309 +310 +311 +312 +313 +314 +315 +316 +317 +318 +319 +320 +321 +322 +323 +324 +325 +326 +327 +328 +329 +330 +331 +332 +333 +334 +335 +336 +337 +338 +339 +340 +341 +342 +343 +344 +345 +346 +347 +348 +349 +350 +351 +352 +353 +354 +355 +356 +357 +358 +359 +360 +361 +362 +363 +364 +365 +366 +367 +368 +369 +370 +371 +372 +373 +374 +375 +376 +377 +378 +379 +380 +381 +382 +383 +384 +385 +386 +387 +388 +389 +390 +391 +392 +393 +394 +395 +396 +397 +398 +399 +400 +401 +402  +6x +6x +6x +6x +6x +6x +  +6x +6x +6x +6x +6x +6x +6x +6x +6x +6x +6x +6x +6x +6x +6x +6x +6x +6x +  +6x +  +6570x +6570x +6570x +1x +6569x +  +6569x +  +6569x +6569x +6569x +6569x +6569x +6569x +6569x +6569x +6569x +6569x +  +6569x +6515x +  +6569x +  +  +4x +4x +2x +  +  +6567x +6567x +2x +2x +  +  +6567x +  +6567x +1x +  +6567x +6513x +  +54x +  +  +  +34x +34x +1x +33x +  +  +  +  +6566x +6566x +6566x +902x +6566x +6566x +6566x +  +  +  +6566x +5664x +867x +34x +  +1x +  +  +  +  +6563x +4x +  +6563x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +6563x +17x +  +  +  +  +  +  +  +  +  +  +  +  +  +6563x +  +  +  +867x +859x +867x +867x +867x +  +  +  +32x +32x +1x +31x +  +  +  +  +32x +32x +32x +  +  +  +1x +1x +1x +1x +1x +  +  +  +5664x +7x +7x +2x +2x +1x +  +6x +  +  +5663x +5663x +42x +  +5621x +  +  +  +5568x +5568x +2x +5566x +  +  +  +  +5617x +5617x +5617x +5617x +  +  +  +7336x +7336x +1x +7335x +  +  +  +  +5566x +  +  +  +7393x +2x +2x +2x +2x +2x +  +  +  +7392x +5614x +1700449x +1700449x +1700449x +  +  +  +7392x +  +7392x +7392x +7392x +7392x +  +7392x +  +7392x +5614x +2x +5614x +5614x +5614x +  +  +1778x +1754x +1754x +  +1778x +1778x +  +  +  +  +  +99x +  +  +  +20x +  +  +  +2x +  +  +  +53x +  +  +  +59x +59x +59x +58x +57x +  +59x +2x +  +  +  +  +51x +  +  +  +6x +  +33x +33x +33x +33x +33x +33x +33x +  +33x +33x +33x +  +  +33x +33x +33x +26x +33x +33x +33x +33x +33x +33x +33x +33x +33x +  +33x +27x +  +33x +2x +2x +  +  +  +1x +  +  +32x +32x +  +32x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +  +32x +14x +  +  +  +  +  +  +  +  +  +  +  +  +  +  +32x +32x +  +  +  +52x +52x +1x +51x +51x +  +  +  +29x +22x +29x +  +  +  +6x +6x +  +6x +6566x +  +  +  +  +6x + 
    'use strict'
    +const MiniPass = require('minipass')
    +const Pax = require('./pax.js')
    +const Header = require('./header.js')
    +const ReadEntry = require('./read-entry.js')
    +const fs = require('fs')
    +const path = require('path')
    + 
    +const types = require('./types.js')
    +const maxReadSize = 16 * 1024 * 1024
    +const PROCESS = Symbol('process')
    +const FILE = Symbol('file')
    +const DIRECTORY = Symbol('directory')
    +const SYMLINK = Symbol('symlink')
    +const HARDLINK = Symbol('hardlink')
    +const HEADER = Symbol('header')
    +const READ = Symbol('read')
    +const LSTAT = Symbol('lstat')
    +const ONLSTAT = Symbol('onlstat')
    +const ONREAD = Symbol('onread')
    +const ONREADLINK = Symbol('onreadlink')
    +const OPENFILE = Symbol('openfile')
    +const ONOPENFILE = Symbol('onopenfile')
    +const CLOSE = Symbol('close')
    +const warner = require('./warn-mixin.js')
    +const winchars = require('./winchars.js')
    + 
    +const WriteEntry = warner(class WriteEntry extends MiniPass {
    +  constructor (p, opt) {
    +    opt = opt || {}
    +    super(opt)
    +    if (typeof p !== 'string')
    +      throw new TypeError('path is required')
    +    this.path = p
    +    // suppress atime, ctime, uid, gid, uname, gname
    +    this.portable = !!opt.portable
    +    // until node has builtin pwnam functions, this'll have to do
    +    this.myuid = process.getuid && process.getuid()
    +    this.myuser = process.env.USER || ''
    +    this.maxReadSize = opt.maxReadSize || maxReadSize
    +    this.linkCache = opt.linkCache || new Map()
    +    this.statCache = opt.statCache || new Map()
    +    this.preservePaths = !!opt.preservePaths
    +    this.cwd = opt.cwd || process.cwd()
    +    this.strict = !!opt.strict
    +    this.noPax = !!opt.noPax
    +    this.noMtime = !!opt.noMtime
    + 
    +    if (typeof opt.onwarn === 'function')
    +      this.on('warn', opt.onwarn)
    + 
    +    if (!this.preservePaths && path.win32.isAbsolute(p)) {
    +      // absolutes on posix are also absolutes on win32
    +      // so we only need to test this one to get both
    +      const parsed = path.win32.parse(p)
    +      this.warn('stripping ' + parsed.root + ' from absolute path', p)
    +      this.path = p.substr(parsed.root.length)
    +    }
    + 
    +    this.win32 = !!opt.win32 || process.platform === 'win32'
    +    if (this.win32) {
    +      this.path = winchars.decode(this.path.replace(/\\/g, '/'))
    +      p = p.replace(/\\/g, '/')
    +    }
    + 
    +    this.absolute = opt.absolute || path.resolve(this.cwd, p)
    + 
    +    if (this.path === '')
    +      this.path = './'
    + 
    +    if (this.statCache.has(this.absolute))
    +      this[ONLSTAT](this.statCache.get(this.absolute))
    +    else
    +      this[LSTAT]()
    +  }
    + 
    +  [LSTAT] () {
    +    fs.lstat(this.absolute, (er, stat) => {
    +      if (er)
    +        return this.emit('error', er)
    +      this[ONLSTAT](stat)
    +    })
    +  }
    + 
    +  [ONLSTAT] (stat) {
    +    this.statCache.set(this.absolute, stat)
    +    this.stat = stat
    +    if (!stat.isFile())
    +      stat.size = 0
    +    this.type = getType(stat)
    +    this.emit('stat', stat)
    +    this[PROCESS]()
    +  }
    + 
    +  [PROCESS] () {
    +    switch (this.type) {
    +      case 'File': return this[FILE]()
    +      case 'Directory': return this[DIRECTORY]()
    +      case 'SymbolicLink': return this[SYMLINK]()
    +      // unsupported types are ignored.
    +      default: return this.end()
    +    }
    +  }
    + 
    +  [HEADER] () {
    +    if (this.type === 'Directory' && this.portable)
    +      this.noMtime = true
    + 
    +    this.header = new Header({
    +      path: this.path,
    +      linkpath: this.linkpath,
    +      // only the permissions and setuid/setgid/sticky bitflags
    +      // not the higher-order bits that specify file type
    +      mode: this.stat.mode & 0o7777,
    +      uid: this.portable ? null : this.stat.uid,
    +      gid: this.portable ? null : this.stat.gid,
    +      size: this.stat.size,
    +      mtime: this.noMtime ? null : this.stat.mtime,
    +      type: this.type,
    +      uname: this.portable ? null :
    +        this.stat.uid === this.myuid ? this.myuser : '',
    +      atime: this.portable ? null : this.stat.atime,
    +      ctime: this.portable ? null : this.stat.ctime
    +    })
    + 
    +    if (this.header.encode() && !this.noPax)
    +      this.write(new Pax({
    +        atime: this.portable ? null : this.header.atime,
    +        ctime: this.portable ? null : this.header.ctime,
    +        gid: this.portable ? null : this.header.gid,
    +        mtime: this.noMtime ? null : this.header.mtime,
    +        path: this.path,
    +        linkpath: this.linkpath,
    +        size: this.header.size,
    +        uid: this.portable ? null : this.header.uid,
    +        uname: this.portable ? null : this.header.uname,
    +        dev: this.portable ? null : this.stat.dev,
    +        ino: this.portable ? null : this.stat.ino,
    +        nlink: this.portable ? null : this.stat.nlink
    +      }).encode())
    +    this.write(this.header.block)
    +  }
    + 
    +  [DIRECTORY] () {
    +    if (this.path.substr(-1) !== '/')
    +      this.path += '/'
    +    this.stat.size = 0
    +    this[HEADER]()
    +    this.end()
    +  }
    + 
    +  [SYMLINK] () {
    +    fs.readlink(this.absolute, (er, linkpath) => {
    +      if (er)
    +        return this.emit('error', er)
    +      this[ONREADLINK](linkpath)
    +    })
    +  }
    + 
    +  [ONREADLINK] (linkpath) {
    +    this.linkpath = linkpath
    +    this[HEADER]()
    +    this.end()
    +  }
    + 
    +  [HARDLINK] (linkpath) {
    +    this.type = 'Link'
    +    this.linkpath = path.relative(this.cwd, linkpath)
    +    this.stat.size = 0
    +    this[HEADER]()
    +    this.end()
    +  }
    + 
    +  [FILE] () {
    +    if (this.stat.nlink > 1) {
    +      const linkKey = this.stat.dev + ':' + this.stat.ino
    +      if (this.linkCache.has(linkKey)) {
    +        const linkpath = this.linkCache.get(linkKey)
    +        if (linkpath.indexOf(this.cwd) === 0)
    +          return this[HARDLINK](linkpath)
    +      }
    +      this.linkCache.set(linkKey, this.absolute)
    +    }
    + 
    +    this[HEADER]()
    +    if (this.stat.size === 0)
    +      return this.end()
    + 
    +    this[OPENFILE]()
    +  }
    + 
    +  [OPENFILE] () {
    +    fs.open(this.absolute, 'r', (er, fd) => {
    +      if (er)
    +        return this.emit('error', er)
    +      this[ONOPENFILE](fd)
    +    })
    +  }
    + 
    +  [ONOPENFILE] (fd) {
    +    const blockLen = 512 * Math.ceil(this.stat.size / 512)
    +    const bufLen = Math.min(blockLen, this.maxReadSize)
    +    const buf = Buffer.allocUnsafe(bufLen)
    +    this[READ](fd, buf, 0, buf.length, 0, this.stat.size, blockLen)
    +  }
    + 
    +  [READ] (fd, buf, offset, length, pos, remain, blockRemain) {
    +    fs.read(fd, buf, offset, length, pos, (er, bytesRead) => {
    +      if (er)
    +        return this[CLOSE](fd, _ => this.emit('error', er))
    +      this[ONREAD](fd, buf, offset, length, pos, remain, blockRemain, bytesRead)
    +    })
    +  }
    + 
    +  [CLOSE] (fd, cb) {
    +    fs.close(fd, cb)
    +  }
    + 
    +  [ONREAD] (fd, buf, offset, length, pos, remain, blockRemain, bytesRead) {
    +    if (bytesRead <= 0 && remain > 0) {
    +      const er = new Error('unexpected EOF')
    +      er.path = this.absolute
    +      er.syscall = 'read'
    +      er.code = 'EOF'
    +      this.emit('error', er)
    +    }
    + 
    +    // null out the rest of the buffer, if we could fit the block padding
    +    if (bytesRead === remain) {
    +      for (let i = bytesRead; i < length && bytesRead < blockRemain; i++) {
    +        buf[i + offset] = 0
    +        bytesRead ++
    +        remain ++
    +      }
    +    }
    + 
    +    const writeBuf = offset === 0 && bytesRead === buf.length ?
    +      buf : buf.slice(offset, offset + bytesRead)
    +    remain -= bytesRead
    +    blockRemain -= bytesRead
    +    pos += bytesRead
    +    offset += bytesRead
    + 
    +    this.write(writeBuf)
    + 
    +    if (!remain) {
    +      if (blockRemain)
    +        this.write(Buffer.alloc(blockRemain))
    +      this.end()
    +      this[CLOSE](fd, _ => _)
    +      return
    +    }
    + 
    +    if (offset >= length) {
    +      buf = Buffer.allocUnsafe(length)
    +      offset = 0
    +    }
    +    length = buf.length - offset
    +    this[READ](fd, buf, offset, length, pos, remain, blockRemain)
    +  }
    +})
    + 
    +class WriteEntrySync extends WriteEntry {
    +  constructor (path, opt) {
    +    super(path, opt)
    +  }
    + 
    +  [LSTAT] () {
    +    this[ONLSTAT](fs.lstatSync(this.absolute))
    +  }
    + 
    +  [SYMLINK] () {
    +    this[ONREADLINK](fs.readlinkSync(this.absolute))
    +  }
    + 
    +  [OPENFILE] () {
    +    this[ONOPENFILE](fs.openSync(this.absolute, 'r'))
    +  }
    + 
    +  [READ] (fd, buf, offset, length, pos, remain, blockRemain) {
    +    let threw = true
    +    try {
    +      const bytesRead = fs.readSync(fd, buf, offset, length, pos)
    +      this[ONREAD](fd, buf, offset, length, pos, remain, blockRemain, bytesRead)
    +      threw = false
    +    } finally {
    +      if (threw)
    +        try { this[CLOSE](fd) } catch (er) {}
    +    }
    +  }
    + 
    +  [CLOSE] (fd) {
    +    fs.closeSync(fd)
    +  }
    +}
    + 
    +const WriteEntryTar = warner(class WriteEntryTar extends MiniPass {
    +  constructor (readEntry, opt) {
    +    opt = opt || {}
    +    super(opt)
    +    this.preservePaths = !!opt.preservePaths
    +    this.portable = !!opt.portable
    +    this.strict = !!opt.strict
    +    this.noPax = !!opt.noPax
    +    this.noMtime = !!opt.noMtime
    + 
    +    this.readEntry = readEntry
    +    this.type = readEntry.type
    +    Iif (this.type === 'Directory' && this.portable)
    +      this.noMtime = true
    + 
    +    this.path = readEntry.path
    +    this.mode = readEntry.mode
    +    if (this.mode)
    +      this.mode = this.mode & 0o7777
    +    this.uid = this.portable ? null : readEntry.uid
    +    this.gid = this.portable ? null : readEntry.gid
    +    this.uname = this.portable ? null : readEntry.uname
    +    this.gname = this.portable ? null : readEntry.gname
    +    this.size = readEntry.size
    +    this.mtime = this.noMtime ? null : readEntry.mtime
    +    this.atime = this.portable ? null : readEntry.atime
    +    this.ctime = this.portable ? null : readEntry.ctime
    +    this.linkpath = readEntry.linkpath
    + 
    +    if (typeof opt.onwarn === 'function')
    +      this.on('warn', opt.onwarn)
    + 
    +    if (path.isAbsolute(this.path) && !this.preservePaths) {
    +      const parsed = path.parse(this.path)
    +      this.warn(
    +        'stripping ' + parsed.root + ' from absolute path',
    +        this.path
    +      )
    +      this.path = this.path.substr(parsed.root.length)
    +    }
    + 
    +    this.remain = readEntry.size
    +    this.blockRemain = readEntry.startBlockSize
    + 
    +    this.header = new Header({
    +      path: this.path,
    +      linkpath: this.linkpath,
    +      // only the permissions and setuid/setgid/sticky bitflags
    +      // not the higher-order bits that specify file type
    +      mode: this.mode,
    +      uid: this.portable ? null : this.uid,
    +      gid: this.portable ? null : this.gid,
    +      size: this.size,
    +      mtime: this.noMtime ? null : this.mtime,
    +      type: this.type,
    +      uname: this.portable ? null : this.uname,
    +      atime: this.portable ? null : this.atime,
    +      ctime: this.portable ? null : this.ctime
    +    })
    + 
    +    if (this.header.encode() && !this.noPax)
    +      super.write(new Pax({
    +        atime: this.portable ? null : this.atime,
    +        ctime: this.portable ? null : this.ctime,
    +        gid: this.portable ? null : this.gid,
    +        mtime: this.noMtime ? null : this.mtime,
    +        path: this.path,
    +        linkpath: this.linkpath,
    +        size: this.size,
    +        uid: this.portable ? null : this.uid,
    +        uname: this.portable ? null : this.uname,
    +        dev: this.portable ? null : this.readEntry.dev,
    +        ino: this.portable ? null : this.readEntry.ino,
    +        nlink: this.portable ? null : this.readEntry.nlink
    +      }).encode())
    + 
    +    super.write(this.header.block)
    +    readEntry.pipe(this)
    +  }
    + 
    +  write (data) {
    +    const writeLen = data.length
    +    if (writeLen > this.blockRemain)
    +      throw new Error('writing more to entry than is appropriate')
    +    this.blockRemain -= writeLen
    +    return super.write(data)
    +  }
    + 
    +  end () {
    +    if (this.blockRemain)
    +      this.write(Buffer.alloc(this.blockRemain))
    +    return super.end()
    +  }
    +})
    + 
    +WriteEntry.Sync = WriteEntrySync
    +WriteEntry.Tar = WriteEntryTar
    + 
    +const getType = stat =>
    +  stat.isFile() ? 'File'
    +  : stat.isDirectory() ? 'Directory'
    +  : stat.isSymbolicLink() ? 'SymbolicLink'
    +  : 'Unsupported'
    + 
    +module.exports = WriteEntry
    + 
    +
    +
    + + + + + + + diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov.info b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov.info new file mode 100644 index 0000000000000..19aa7c2206221 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov.info @@ -0,0 +1,3690 @@ +TN: +SF:/Users/isaacs/dev/js/tar/index.js +FNF:0 +FNH:0 +DA:4,1 +DA:5,1 +DA:6,1 +DA:7,1 +DA:8,1 +DA:11,1 +DA:12,1 +DA:13,1 +DA:14,1 +DA:15,1 +DA:16,1 +DA:17,1 +DA:18,1 +LF:13 +LH:13 +BRF:0 +BRH:0 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/create.js +FN:12,(anonymous_0) +FN:38,(anonymous_1) +FN:47,(anonymous_2) +FN:54,(anonymous_3) +FN:65,(anonymous_4) +FN:66,(anonymous_5) +FN:72,(anonymous_6) +FN:80,(anonymous_7) +FN:87,(anonymous_8) +FN:88,(anonymous_9) +FN:95,(anonymous_10) +FN:101,(anonymous_11) +FNF:12 +FNH:12 +FNDA:15,(anonymous_0) +FNDA:4,(anonymous_1) +FNDA:4,(anonymous_2) +FNDA:4,(anonymous_3) +FNDA:5,(anonymous_4) +FNDA:7,(anonymous_5) +FNDA:7,(anonymous_6) +FNDA:9,(anonymous_7) +FNDA:7,(anonymous_8) +FNDA:3,(anonymous_9) +FNDA:1,(anonymous_10) +FNDA:2,(anonymous_11) +DA:4,2 +DA:6,2 +DA:7,2 +DA:8,2 +DA:9,2 +DA:10,2 +DA:12,2 +DA:13,15 +DA:14,1 +DA:16,15 +DA:17,1 +DA:19,15 +DA:20,2 +DA:22,13 +DA:24,13 +DA:26,13 +DA:27,1 +DA:29,12 +DA:30,1 +DA:32,11 +DA:38,2 +DA:39,4 +DA:40,4 +DA:43,4 +DA:44,4 +DA:47,2 +DA:48,4 +DA:49,4 +DA:52,4 +DA:54,4 +DA:55,4 +DA:56,4 +DA:57,4 +DA:60,4 +DA:62,4 +DA:65,2 +DA:66,5 +DA:67,7 +DA:68,3 +DA:72,7 +DA:75,4 +DA:77,4 +DA:80,2 +DA:81,9 +DA:82,8 +DA:83,8 +DA:84,3 +DA:87,7 +DA:88,3 +DA:90,5 +DA:92,6 +DA:95,2 +DA:96,1 +DA:97,1 +DA:98,1 +DA:101,2 +DA:102,2 +DA:103,2 +DA:104,2 +LF:59 +LH:59 +BRDA:13,0,0,1 +BRDA:13,0,1,14 +BRDA:16,1,0,1 +BRDA:16,1,1,14 +BRDA:19,2,0,2 +BRDA:19,2,1,13 +BRDA:19,3,0,15 +BRDA:19,3,1,14 +BRDA:19,3,2,13 +BRDA:26,4,0,1 +BRDA:26,4,1,12 +BRDA:26,5,0,13 +BRDA:26,5,1,6 +BRDA:29,6,0,1 +BRDA:29,6,1,11 +BRDA:29,7,0,12 +BRDA:29,7,1,4 +BRDA:32,8,0,4 +BRDA:32,8,1,7 +BRDA:32,9,0,11 +BRDA:32,9,1,8 +BRDA:33,10,0,4 +BRDA:33,10,1,3 +BRDA:34,11,0,1 +BRDA:34,11,1,2 +BRDA:41,12,0,4 +BRDA:41,12,1,3 +BRDA:50,13,0,4 +BRDA:50,13,1,3 +BRDA:62,14,0,3 +BRDA:62,14,1,1 +BRDA:67,15,0,3 +BRDA:67,15,1,4 +BRDA:83,16,0,3 +BRDA:83,16,1,5 +BRF:35 +BRH:35 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/extract.js +FN:10,(anonymous_0) +FN:43,(anonymous_1) +FN:44,(anonymous_2) +FN:47,(anonymous_3) +FN:58,(anonymous_4) +FN:59,(anonymous_5) +FN:62,(anonymous_6) +FN:79,(anonymous_7) +FN:84,(anonymous_8) +FN:90,(anonymous_9) +FN:106,(anonymous_10) +FN:110,(anonymous_11) +FNF:12 +FNH:12 +FNDA:21,(anonymous_0) +FNDA:7,(anonymous_1) +FNDA:13,(anonymous_2) +FNDA:87,(anonymous_3) +FNDA:9,(anonymous_4) +FNDA:9,(anonymous_5) +FNDA:6,(anonymous_6) +FNDA:9,(anonymous_7) +FNDA:9,(anonymous_8) +FNDA:9,(anonymous_9) +FNDA:1,(anonymous_10) +FNDA:2,(anonymous_11) +DA:4,2 +DA:5,2 +DA:6,2 +DA:7,2 +DA:8,2 +DA:10,2 +DA:11,21 +DA:12,1 +DA:13,20 +DA:14,1 +DA:16,21 +DA:17,3 +DA:19,21 +DA:20,13 +DA:22,8 +DA:24,21 +DA:26,21 +DA:27,2 +DA:29,19 +DA:30,1 +DA:32,18 +DA:33,7 +DA:35,18 +DA:43,2 +DA:44,13 +DA:45,7 +DA:47,7 +DA:48,87 +DA:49,87 +DA:53,87 +DA:54,87 +DA:57,7 +DA:58,9 +DA:59,9 +DA:62,2 +DA:63,6 +DA:65,6 +DA:66,6 +DA:68,6 +DA:71,5 +DA:72,5 +DA:76,4 +DA:79,2 +DA:80,9 +DA:81,9 +DA:83,9 +DA:84,9 +DA:85,9 +DA:86,9 +DA:90,9 +DA:91,9 +DA:92,1 +DA:94,8 +DA:98,8 +DA:99,8 +DA:103,9 +DA:106,2 +DA:107,1 +DA:110,2 +DA:111,2 +LF:60 +LH:60 +BRDA:11,0,0,1 +BRDA:11,0,1,20 +BRDA:13,1,0,1 +BRDA:13,1,1,19 +BRDA:16,2,0,3 +BRDA:16,2,1,18 +BRDA:19,3,0,13 +BRDA:19,3,1,8 +BRDA:26,4,0,2 +BRDA:26,4,1,19 +BRDA:26,5,0,21 +BRDA:26,5,1,9 +BRDA:29,6,0,1 +BRDA:29,6,1,18 +BRDA:29,7,0,19 +BRDA:29,7,1,4 +BRDA:32,8,0,7 +BRDA:32,8,1,11 +BRDA:35,9,0,6 +BRDA:35,9,1,12 +BRDA:35,10,0,18 +BRDA:35,10,1,15 +BRDA:36,11,0,9 +BRDA:36,11,1,3 +BRDA:37,12,0,1 +BRDA:37,12,1,2 +BRDA:48,13,0,87 +BRDA:48,13,1,12 +BRDA:48,13,2,12 +BRDA:49,14,0,3 +BRDA:49,14,1,84 +BRDA:50,15,0,9 +BRDA:50,15,1,75 +BRDA:57,16,0,3 +BRDA:57,16,1,4 +BRDA:58,17,0,9 +BRDA:58,17,1,3 +BRDA:71,18,0,5 +BRDA:71,18,1,3 +BRDA:81,19,0,9 +BRDA:81,19,1,7 +BRDA:91,20,0,1 +BRDA:91,20,1,8 +BRDA:103,21,0,4 +BRDA:103,21,1,5 +BRF:45 +BRH:45 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/header.js +FN:14,(anonymous_0) +FN:42,(anonymous_1) +FN:103,(anonymous_2) +FN:157,(anonymous_3) +FN:164,(anonymous_4) +FN:168,(anonymous_5) +FN:172,(anonymous_6) +FN:180,(anonymous_7) +FN:219,(anonymous_8) +FN:222,(anonymous_9) +FN:225,(anonymous_10) +FN:227,(anonymous_11) +FN:231,(anonymous_12) +FN:233,(anonymous_13) +FN:244,(anonymous_14) +FN:250,(anonymous_15) +FN:253,(anonymous_16) +FN:256,(anonymous_17) +FN:260,(anonymous_18) +FN:267,(anonymous_19) +FNF:20 +FNH:20 +FNDA:13121,(anonymous_0) +FNDA:6393,(anonymous_1) +FNDA:6719,(anonymous_2) +FNDA:6728,(anonymous_3) +FNDA:8178,(anonymous_4) +FNDA:4,(anonymous_5) +FNDA:6723,(anonymous_6) +FNDA:6718,(anonymous_7) +FNDA:32001,(anonymous_8) +FNDA:14938,(anonymous_9) +FNDA:14938,(anonymous_10) +FNDA:55448,(anonymous_11) +FNDA:55411,(anonymous_12) +FNDA:55411,(anonymous_13) +FNDA:66910,(anonymous_14) +FNDA:66615,(anonymous_15) +FNDA:66615,(anonymous_16) +FNDA:66615,(anonymous_17) +FNDA:20150,(anonymous_18) +FNDA:40308,(anonymous_19) +DA:7,13 +DA:8,13 +DA:9,13 +DA:11,13 +DA:15,13121 +DA:16,13121 +DA:17,13121 +DA:19,13121 +DA:20,13121 +DA:21,13121 +DA:22,13121 +DA:23,13121 +DA:24,13121 +DA:25,13121 +DA:26,13121 +DA:27,13121 +DA:28,13121 +DA:29,13121 +DA:30,13121 +DA:31,13121 +DA:32,13121 +DA:33,13121 +DA:34,13121 +DA:36,13121 +DA:37,6393 +DA:38,6728 +DA:39,6726 +DA:43,6393 +DA:44,2795 +DA:46,6393 +DA:47,1 +DA:49,6392 +DA:50,6392 +DA:51,6392 +DA:52,6392 +DA:53,6392 +DA:54,6392 +DA:55,6392 +DA:58,6392 +DA:59,6392 +DA:60,1990 +DA:61,6392 +DA:62,2 +DA:69,6392 +DA:70,1594 +DA:72,6392 +DA:73,6392 +DA:74,4275 +DA:75,4275 +DA:76,4275 +DA:77,4275 +DA:78,4275 +DA:80,2 +DA:81,2 +DA:83,4273 +DA:84,4273 +DA:85,295 +DA:86,4273 +DA:87,4273 +DA:91,6392 +DA:92,6392 +DA:93,946016 +DA:95,6392 +DA:96,2275552 +DA:98,6392 +DA:99,6392 +DA:100,1860 +DA:104,6719 +DA:105,6600 +DA:106,6600 +DA:109,6719 +DA:110,6717 +DA:112,6719 +DA:113,1 +DA:115,6718 +DA:116,6718 +DA:117,6718 +DA:118,6718 +DA:119,6718 +DA:121,6718 +DA:122,6718 +DA:123,6718 +DA:124,6718 +DA:125,6718 +DA:126,6718 +DA:127,6718 +DA:128,6718 +DA:129,6718 +DA:130,6718 +DA:131,6718 +DA:132,6718 +DA:133,6718 +DA:134,6718 +DA:135,6718 +DA:136,2 +DA:138,6716 +DA:139,6716 +DA:140,6716 +DA:143,6718 +DA:144,6718 +DA:145,994264 +DA:147,6718 +DA:148,2391608 +DA:150,6718 +DA:151,6718 +DA:152,6718 +DA:154,6718 +DA:158,6728 +DA:159,73451 +DA:160,66740 +DA:165,8178 +DA:169,4 +DA:173,6723 +DA:174,6719 +DA:176,4 +DA:180,13 +DA:181,6718 +DA:182,6718 +DA:183,6718 +DA:185,6718 +DA:187,6718 +DA:188,6683 +DA:191,35 +DA:192,35 +DA:194,35 +DA:196,49 +DA:198,21 +DA:201,28 +DA:203,13 +DA:207,15 +DA:208,15 +DA:213,35 +DA:214,1 +DA:216,6718 +DA:219,13 +DA:220,32001 +DA:222,13 +DA:223,14938 +DA:225,14938 +DA:227,13 +DA:228,55448 +DA:231,55411 +DA:233,13 +DA:234,55411 +DA:239,13 +DA:244,13 +DA:245,66910 +DA:250,13 +DA:251,66615 +DA:253,13 +DA:254,66615 +DA:256,13 +DA:257,66615 +DA:260,13 +DA:261,20150 +DA:265,13 +DA:267,13 +DA:268,40308 +DA:272,13 +LF:159 +LH:159 +BRDA:36,0,0,6393 +BRDA:36,0,1,6728 +BRDA:37,1,0,6393 +BRDA:37,1,1,2795 +BRDA:38,2,0,6726 +BRDA:38,2,1,2 +BRDA:43,3,0,2795 +BRDA:43,3,1,3598 +BRDA:46,4,0,1 +BRDA:46,4,1,6392 +BRDA:46,5,0,6393 +BRDA:46,5,1,6393 +BRDA:59,6,0,1990 +BRDA:59,6,1,4402 +BRDA:61,7,0,2 +BRDA:61,7,1,6390 +BRDA:61,8,0,6392 +BRDA:61,8,1,3769 +BRDA:69,9,0,1594 +BRDA:69,9,1,4798 +BRDA:73,10,0,4275 +BRDA:73,10,1,2117 +BRDA:78,11,0,2 +BRDA:78,11,1,4273 +BRDA:84,12,0,295 +BRDA:84,12,1,3978 +BRDA:99,13,0,1860 +BRDA:99,13,1,4532 +BRDA:99,14,0,6392 +BRDA:99,14,1,1994 +BRDA:104,15,0,6600 +BRDA:104,15,1,119 +BRDA:109,16,0,6717 +BRDA:109,16,1,2 +BRDA:112,17,0,1 +BRDA:112,17,1,6718 +BRDA:115,18,0,6623 +BRDA:115,18,1,95 +BRDA:115,19,0,6718 +BRDA:115,19,1,95 +BRDA:116,20,0,6718 +BRDA:116,20,1,1 +BRDA:121,21,0,6718 +BRDA:121,21,1,6678 +BRDA:122,22,0,6718 +BRDA:122,22,1,6718 +BRDA:123,23,0,6718 +BRDA:123,23,1,6715 +BRDA:124,24,0,6718 +BRDA:124,24,1,6715 +BRDA:125,25,0,6718 +BRDA:125,25,1,6717 +BRDA:126,26,0,6718 +BRDA:126,26,1,6718 +BRDA:128,27,0,6718 +BRDA:128,27,1,6718 +BRDA:130,28,0,6718 +BRDA:130,28,1,6718 +BRDA:131,29,0,6718 +BRDA:131,29,1,6718 +BRDA:132,30,0,6718 +BRDA:132,30,1,6718 +BRDA:133,31,0,6718 +BRDA:133,31,1,6718 +BRDA:134,32,0,6718 +BRDA:134,32,1,6718 +BRDA:135,33,0,2 +BRDA:135,33,1,6716 +BRDA:136,34,0,2 +BRDA:136,34,1,2 +BRDA:138,35,0,6716 +BRDA:138,35,1,6716 +BRDA:139,36,0,6716 +BRDA:139,36,1,6716 +BRDA:140,37,0,6716 +BRDA:140,37,1,6716 +BRDA:159,38,0,66740 +BRDA:159,38,1,6711 +BRDA:159,39,0,73451 +BRDA:159,39,1,73273 +BRDA:165,40,0,8178 +BRDA:165,40,1,6 +BRDA:173,41,0,6719 +BRDA:173,41,1,4 +BRDA:185,42,0,6718 +BRDA:185,42,1,6712 +BRDA:187,43,0,6683 +BRDA:187,43,1,35 +BRDA:210,44,0,49 +BRDA:210,44,1,34 +BRDA:196,45,0,21 +BRDA:196,45,1,28 +BRDA:196,46,0,49 +BRDA:196,46,1,35 +BRDA:201,47,0,13 +BRDA:201,47,1,15 +BRDA:201,48,0,28 +BRDA:201,48,1,14 +BRDA:213,49,0,1 +BRDA:213,49,1,34 +BRDA:225,50,0,10449 +BRDA:225,50,1,4489 +BRDA:228,51,0,37 +BRDA:228,51,1,55411 +BRDA:231,52,0,21489 +BRDA:231,52,1,33922 +BRDA:245,53,0,288 +BRDA:245,53,1,66622 +BRDA:246,54,0,7 +BRDA:246,54,1,66615 +BRDA:246,55,0,66622 +BRDA:246,55,1,66615 +BRDA:257,56,0,19852 +BRDA:257,56,1,46763 +BRDA:261,57,0,266 +BRDA:261,57,1,19884 +BRDA:268,58,0,13394 +BRDA:268,58,1,26914 +BRDA:270,59,0,26914 +BRDA:270,59,1,26874 +BRF:120 +BRH:120 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/high-level-opt.js +FN:27,(anonymous_0) +FN:27,(anonymous_1) +FN:29,(anonymous_2) +FNF:3 +FNH:3 +FNDA:177,(anonymous_0) +FNDA:469,(anonymous_1) +FNDA:469,(anonymous_2) +DA:5,7 +DA:27,469 +DA:29,469 +LF:3 +LH:3 +BRDA:27,0,0,174 +BRDA:27,0,1,3 +BRDA:28,1,0,26 +BRDA:28,1,1,443 +BRF:4 +BRH:4 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/large-numbers.js +FN:7,(anonymous_0) +FN:16,(anonymous_1) +FN:28,(anonymous_2) +FN:51,(anonymous_3) +FN:58,(anonymous_4) +FN:79,(anonymous_5) +FN:90,(anonymous_6) +FN:92,(anonymous_7) +FNF:8 +FNH:8 +FNDA:17,(anonymous_0) +FNDA:11,(anonymous_1) +FNDA:6,(anonymous_2) +FNDA:47,(anonymous_3) +FNDA:6,(anonymous_4) +FNDA:41,(anonymous_5) +FNDA:96,(anonymous_6) +FNDA:12,(anonymous_7) +DA:7,14 +DA:8,17 +DA:9,17 +DA:10,6 +DA:12,11 +DA:13,17 +DA:16,14 +DA:17,11 +DA:18,11 +DA:19,86 +DA:20,31 +DA:22,55 +DA:23,55 +DA:28,14 +DA:29,6 +DA:30,6 +DA:31,6 +DA:32,6 +DA:34,60 +DA:35,42 +DA:37,18 +DA:38,18 +DA:40,60 +DA:41,48 +DA:42,12 +DA:43,6 +DA:45,6 +DA:46,6 +DA:51,14 +DA:52,47 +DA:53,47 +DA:54,47 +DA:58,14 +DA:59,6 +DA:60,6 +DA:61,6 +DA:62,6 +DA:63,60 +DA:65,60 +DA:66,48 +DA:67,12 +DA:68,6 +DA:70,6 +DA:71,6 +DA:73,60 +DA:74,12 +DA:76,6 +DA:79,14 +DA:80,41 +DA:81,41 +DA:82,41 +DA:83,266 +DA:84,266 +DA:85,161 +DA:87,41 +DA:90,96 +DA:92,14 +LF:57 +LH:57 +BRDA:9,0,0,6 +BRDA:9,0,1,11 +BRDA:19,1,0,31 +BRDA:19,1,1,55 +BRDA:34,2,0,42 +BRDA:34,2,1,18 +BRDA:40,3,0,48 +BRDA:40,3,1,12 +BRDA:42,4,0,6 +BRDA:42,4,1,6 +BRDA:54,5,0,41 +BRDA:54,5,1,6 +BRDA:65,6,0,48 +BRDA:65,6,1,12 +BRDA:67,7,0,6 +BRDA:67,7,1,6 +BRDA:73,8,0,12 +BRDA:73,8,1,48 +BRDA:84,9,0,161 +BRDA:84,9,1,105 +BRF:20 +BRH:20 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/list.js +FN:13,(anonymous_0) +FN:46,(anonymous_1) +FN:48,(anonymous_2) +FN:51,(anonymous_3) +FN:56,(anonymous_4) +FN:57,(anonymous_5) +FN:60,(anonymous_6) +FN:71,(anonymous_7) +FN:72,(anonymous_8) +FN:75,(anonymous_9) +FN:103,(anonymous_10) +FN:108,(anonymous_11) +FN:112,(anonymous_12) +FN:128,(anonymous_13) +FNF:14 +FNH:14 +FNDA:34,(anonymous_0) +FNDA:22,(anonymous_1) +FNDA:255,(anonymous_2) +FNDA:72,(anonymous_3) +FNDA:3,(anonymous_4) +FNDA:6,(anonymous_5) +FNDA:125,(anonymous_6) +FNDA:32,(anonymous_7) +FNDA:64,(anonymous_8) +FNDA:13,(anonymous_9) +FNDA:16,(anonymous_10) +FNDA:16,(anonymous_11) +FNDA:16,(anonymous_12) +FNDA:16,(anonymous_13) +DA:7,5 +DA:8,5 +DA:9,5 +DA:10,5 +DA:11,5 +DA:13,5 +DA:14,34 +DA:15,1 +DA:16,33 +DA:17,1 +DA:19,34 +DA:20,5 +DA:22,34 +DA:23,31 +DA:25,3 +DA:27,34 +DA:29,34 +DA:30,1 +DA:32,33 +DA:33,1 +DA:35,32 +DA:36,3 +DA:38,32 +DA:39,22 +DA:41,32 +DA:46,5 +DA:47,22 +DA:48,22 +DA:49,255 +DA:50,255 +DA:51,72 +DA:56,5 +DA:57,6 +DA:58,3 +DA:60,3 +DA:61,125 +DA:62,125 +DA:66,125 +DA:67,125 +DA:70,3 +DA:71,32 +DA:72,64 +DA:75,5 +DA:76,13 +DA:77,13 +DA:78,13 +DA:80,13 +DA:81,13 +DA:82,12 +DA:83,12 +DA:84,10 +DA:86,2 +DA:87,2 +DA:88,2 +DA:89,2 +DA:90,28 +DA:91,27 +DA:92,27 +DA:94,1 +DA:96,11 +DA:98,13 +DA:99,1 +DA:103,5 +DA:104,16 +DA:105,16 +DA:107,16 +DA:108,16 +DA:109,16 +DA:110,16 +DA:112,16 +DA:113,16 +DA:114,2 +DA:116,14 +DA:120,14 +DA:121,14 +DA:125,16 +DA:128,16 +LF:77 +LH:77 +BRDA:14,0,0,1 +BRDA:14,0,1,33 +BRDA:16,1,0,1 +BRDA:16,1,1,32 +BRDA:19,2,0,5 +BRDA:19,2,1,29 +BRDA:22,3,0,31 +BRDA:22,3,1,3 +BRDA:29,4,0,1 +BRDA:29,4,1,33 +BRDA:29,5,0,34 +BRDA:29,5,1,15 +BRDA:32,6,0,1 +BRDA:32,6,1,32 +BRDA:32,7,0,33 +BRDA:32,7,1,4 +BRDA:35,8,0,3 +BRDA:35,8,1,29 +BRDA:38,9,0,22 +BRDA:38,9,1,10 +BRDA:41,10,0,13 +BRDA:41,10,1,19 +BRDA:41,11,0,32 +BRDA:41,11,1,29 +BRDA:42,12,0,16 +BRDA:42,12,1,3 +BRDA:48,13,0,13 +BRDA:48,13,1,9 +BRDA:61,14,0,125 +BRDA:61,14,1,65 +BRDA:61,14,2,65 +BRDA:62,15,0,6 +BRDA:62,15,1,119 +BRDA:63,16,0,59 +BRDA:63,16,1,60 +BRDA:70,17,0,1 +BRDA:70,17,1,2 +BRDA:71,18,0,32 +BRDA:71,18,1,1 +BRDA:82,19,0,12 +BRDA:82,19,1,10 +BRDA:83,20,0,10 +BRDA:83,20,1,2 +BRDA:98,21,0,1 +BRDA:98,21,1,12 +BRDA:98,22,0,13 +BRDA:98,22,1,2 +BRDA:105,23,0,16 +BRDA:105,23,1,14 +BRDA:113,24,0,2 +BRDA:113,24,1,14 +BRDA:125,25,0,4 +BRDA:125,25,1,12 +BRF:53 +BRH:53 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/mkdir.js +FN:13,(anonymous_0) +FN:19,(anonymous_1) +FN:25,(anonymous_2) +FN:31,(anonymous_3) +FN:36,(anonymous_4) +FN:54,(anonymous_5) +FN:60,(anonymous_6) +FN:72,(anonymous_7) +FN:86,(anonymous_8) +FN:96,(anonymous_9) +FN:96,(anonymous_10) +FN:102,(anonymous_11) +FN:108,(anonymous_12) +FN:124,(anonymous_13) +FN:142,(anonymous_14) +FNF:15 +FNH:15 +FNDA:4,(anonymous_0) +FNDA:8,(anonymous_1) +FNDA:12,(anonymous_2) +FNDA:36,(anonymous_3) +FNDA:451,(anonymous_4) +FNDA:457,(anonymous_5) +FNDA:6,(anonymous_6) +FNDA:40,(anonymous_7) +FNDA:1062,(anonymous_8) +FNDA:222,(anonymous_9) +FNDA:222,(anonymous_10) +FNDA:32,(anonymous_11) +FNDA:3,(anonymous_12) +FNDA:276,(anonymous_13) +FNDA:266,(anonymous_14) +DA:7,3 +DA:8,3 +DA:9,3 +DA:10,3 +DA:14,4 +DA:15,4 +DA:16,4 +DA:20,8 +DA:26,12 +DA:27,12 +DA:28,12 +DA:32,36 +DA:36,3 +DA:39,451 +DA:40,451 +DA:41,451 +DA:43,451 +DA:44,451 +DA:45,451 +DA:49,451 +DA:50,451 +DA:51,451 +DA:52,451 +DA:54,451 +DA:55,457 +DA:56,15 +DA:58,442 +DA:59,442 +DA:60,6 +DA:61,436 +DA:62,1 +DA:64,435 +DA:68,451 +DA:69,272 +DA:71,179 +DA:72,40 +DA:73,40 +DA:74,2 +DA:75,40 +DA:78,139 +DA:79,8 +DA:81,131 +DA:82,131 +DA:83,131 +DA:86,3 +DA:87,1062 +DA:88,119 +DA:89,943 +DA:90,943 +DA:91,943 +DA:92,723 +DA:93,220 +DA:96,222 +DA:97,222 +DA:98,36 +DA:100,4 +DA:102,32 +DA:103,32 +DA:104,4 +DA:105,28 +DA:106,22 +DA:107,6 +DA:108,3 +DA:109,3 +DA:110,1 +DA:111,2 +DA:113,3 +DA:114,2 +DA:116,1 +DA:119,186 +DA:120,186 +DA:124,3 +DA:127,276 +DA:128,276 +DA:129,276 +DA:131,276 +DA:132,276 +DA:133,276 +DA:137,276 +DA:138,276 +DA:139,276 +DA:140,276 +DA:142,276 +DA:143,266 +DA:144,266 +DA:145,6 +DA:146,266 +DA:147,1 +DA:148,266 +DA:151,276 +DA:152,128 +DA:154,148 +DA:155,34 +DA:156,34 +DA:157,34 +DA:158,34 +DA:160,1 +DA:162,34 +DA:163,2 +DA:165,32 +DA:166,32 +DA:169,114 +DA:170,7 +DA:172,107 +DA:173,107 +DA:174,107 +DA:175,107 +DA:179,792 +DA:180,608 +DA:182,184 +DA:183,184 +DA:184,169 +DA:185,169 +DA:187,15 +DA:189,4 +DA:191,11 +DA:192,9 +DA:193,4 +DA:194,4 +DA:195,5 +DA:196,2 +DA:197,2 +DA:198,2 +DA:199,2 +DA:200,2 +DA:201,3 +DA:202,2 +DA:206,99 +LF:128 +LH:128 +BRDA:45,0,0,451 +BRDA:45,0,1,6 +BRDA:45,0,2,6 +BRDA:45,0,3,2 +BRDA:55,1,0,15 +BRDA:55,1,1,442 +BRDA:59,2,0,6 +BRDA:59,2,1,436 +BRDA:59,3,0,442 +BRDA:59,3,1,114 +BRDA:61,4,0,1 +BRDA:61,4,1,435 +BRDA:68,5,0,272 +BRDA:68,5,1,179 +BRDA:68,6,0,451 +BRDA:68,6,1,451 +BRDA:71,7,0,40 +BRDA:71,7,1,139 +BRDA:73,8,0,2 +BRDA:73,8,1,38 +BRDA:73,9,0,40 +BRDA:73,9,1,39 +BRDA:74,10,0,2 +BRDA:74,10,1,1 +BRDA:74,10,2,1 +BRDA:78,11,0,8 +BRDA:78,11,1,131 +BRDA:87,12,0,119 +BRDA:87,12,1,943 +BRDA:91,13,0,723 +BRDA:91,13,1,220 +BRDA:97,14,0,36 +BRDA:97,14,1,186 +BRDA:98,15,0,4 +BRDA:98,15,1,32 +BRDA:98,16,0,36 +BRDA:98,16,1,35 +BRDA:98,16,2,16 +BRDA:98,16,3,14 +BRDA:103,17,0,4 +BRDA:103,17,1,28 +BRDA:105,18,0,22 +BRDA:105,18,1,6 +BRDA:107,19,0,3 +BRDA:107,19,1,3 +BRDA:109,20,0,1 +BRDA:109,20,1,2 +BRDA:113,21,0,2 +BRDA:113,21,1,1 +BRDA:119,22,0,186 +BRDA:119,22,1,108 +BRDA:133,23,0,276 +BRDA:133,23,1,6 +BRDA:133,23,2,6 +BRDA:133,23,3,2 +BRDA:144,24,0,6 +BRDA:144,24,1,260 +BRDA:144,25,0,266 +BRDA:144,25,1,101 +BRDA:146,26,0,1 +BRDA:146,26,1,265 +BRDA:151,27,0,128 +BRDA:151,27,1,148 +BRDA:151,28,0,276 +BRDA:151,28,1,276 +BRDA:154,29,0,34 +BRDA:154,29,1,114 +BRDA:162,30,0,2 +BRDA:162,30,1,32 +BRDA:169,31,0,7 +BRDA:169,31,1,107 +BRDA:176,32,0,891 +BRDA:176,32,1,792 +BRDA:179,33,0,608 +BRDA:179,33,1,184 +BRDA:184,34,0,169 +BRDA:184,34,1,93 +BRDA:187,35,0,4 +BRDA:187,35,1,11 +BRDA:187,36,0,15 +BRDA:187,36,1,14 +BRDA:187,36,2,5 +BRDA:187,36,3,3 +BRDA:192,37,0,4 +BRDA:192,37,1,5 +BRDA:195,38,0,2 +BRDA:195,38,1,3 +BRDA:198,39,0,2 +BRDA:198,39,1,2 +BRDA:201,40,0,2 +BRDA:201,40,1,1 +BRF:91 +BRH:91 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/pack.js +FN:13,(anonymous_0) +FN:59,(anonymous_1) +FN:81,(anonymous_2) +FN:82,(anonymous_3) +FN:83,(anonymous_4) +FN:84,(anonymous_5) +FN:94,(anonymous_6) +FN:103,(anonymous_7) +FN:107,(anonymous_8) +FN:112,(anonymous_9) +FN:120,(anonymous_10) +FN:131,(anonymous_11) +FN:142,(anonymous_12) +FN:150,(anonymous_13) +FN:159,(anonymous_14) +FN:163,(anonymous_15) +FN:173,(anonymous_16) +FN:184,(anonymous_17) +FN:187,(anonymous_18) +FN:196,(anonymous_19) +FN:202,(anonymous_20) +FN:230,(anonymous_21) +FN:234,(anonymous_22) +FN:240,(anonymous_23) +FN:283,(anonymous_24) +FN:285,(anonymous_25) +FN:301,(anonymous_26) +FN:305,(anonymous_27) +FN:306,(anonymous_28) +FN:312,(anonymous_29) +FN:318,(anonymous_30) +FN:322,(anonymous_31) +FN:335,(anonymous_32) +FN:340,(anonymous_33) +FN:346,(anonymous_34) +FN:354,(anonymous_35) +FN:360,(anonymous_36) +FN:361,(anonymous_37) +FN:363,(anonymous_38) +FN:368,(anonymous_39) +FN:373,(anonymous_40) +FN:378,(anonymous_41) +FN:389,(anonymous_42) +FN:393,(anonymous_43) +FNF:44 +FNH:44 +FNDA:6566,(anonymous_0) +FNDA:122,(anonymous_1) +FNDA:503,(anonymous_2) +FNDA:4,(anonymous_3) +FNDA:146,(anonymous_4) +FNDA:219,(anonymous_5) +FNDA:6507,(anonymous_6) +FNDA:106,(anonymous_7) +FNDA:107,(anonymous_8) +FNDA:100,(anonymous_9) +FNDA:128,(anonymous_10) +FNDA:27,(anonymous_11) +FNDA:25,(anonymous_12) +FNDA:6541,(anonymous_13) +FNDA:6453,(anonymous_14) +FNDA:6453,(anonymous_15) +FNDA:6538,(anonymous_16) +FNDA:821,(anonymous_17) +FNDA:821,(anonymous_18) +FNDA:858,(anonymous_19) +FNDA:20596,(anonymous_20) +FNDA:25863,(anonymous_21) +FNDA:6533,(anonymous_22) +FNDA:38739,(anonymous_23) +FNDA:6537,(anonymous_24) +FNDA:1,(anonymous_25) +FNDA:6512,(anonymous_26) +FNDA:6508,(anonymous_27) +FNDA:1,(anonymous_28) +FNDA:248,(anonymous_29) +FNDA:6448,(anonymous_30) +FNDA:6393,(anonymous_31) +FNDA:11830,(anonymous_32) +FNDA:199,(anonymous_33) +FNDA:265,(anonymous_34) +FNDA:47,(anonymous_35) +FNDA:1,(anonymous_36) +FNDA:1,(anonymous_37) +FNDA:84,(anonymous_38) +FNDA:37,(anonymous_39) +FNDA:87,(anonymous_40) +FNDA:48,(anonymous_41) +FNDA:39,(anonymous_42) +FNDA:106,(anonymous_43) +DA:14,6566 +DA:15,6566 +DA:16,6566 +DA:17,6566 +DA:18,6566 +DA:19,6566 +DA:20,6566 +DA:21,6566 +DA:25,5 +DA:26,5 +DA:27,5 +DA:28,5 +DA:29,5 +DA:30,5 +DA:31,5 +DA:32,5 +DA:33,5 +DA:34,5 +DA:35,5 +DA:36,5 +DA:37,5 +DA:38,5 +DA:39,5 +DA:40,5 +DA:41,5 +DA:42,5 +DA:43,5 +DA:44,5 +DA:45,5 +DA:46,5 +DA:47,5 +DA:48,5 +DA:49,5 +DA:50,5 +DA:51,5 +DA:52,5 +DA:54,5 +DA:55,5 +DA:56,5 +DA:58,5 +DA:60,122 +DA:61,122 +DA:62,122 +DA:63,122 +DA:64,122 +DA:65,122 +DA:66,122 +DA:67,122 +DA:68,122 +DA:69,122 +DA:70,122 +DA:71,122 +DA:72,122 +DA:73,122 +DA:74,3 +DA:76,122 +DA:77,122 +DA:78,5 +DA:79,4 +DA:80,5 +DA:81,503 +DA:82,5 +DA:83,146 +DA:84,219 +DA:86,117 +DA:88,122 +DA:89,122 +DA:90,122 +DA:91,122 +DA:94,6507 +DA:96,122 +DA:97,122 +DA:98,122 +DA:99,122 +DA:100,122 +DA:104,106 +DA:108,107 +DA:109,103 +DA:113,100 +DA:114,21 +DA:115,99 +DA:116,99 +DA:117,99 +DA:121,128 +DA:122,1 +DA:124,127 +DA:125,27 +DA:127,100 +DA:128,123 +DA:132,27 +DA:133,27 +DA:134,1 +DA:137,27 +DA:138,2 +DA:140,25 +DA:141,25 +DA:142,25 +DA:143,25 +DA:144,25 +DA:147,27 +DA:151,6541 +DA:152,6541 +DA:153,34 +DA:155,6541 +DA:156,6541 +DA:160,6453 +DA:161,6453 +DA:162,6453 +DA:163,6453 +DA:164,6453 +DA:165,6453 +DA:166,6453 +DA:167,1 +DA:169,6452 +DA:174,6538 +DA:175,6538 +DA:178,6538 +DA:179,24 +DA:181,6538 +DA:185,821 +DA:186,821 +DA:187,821 +DA:188,821 +DA:189,821 +DA:190,821 +DA:191,1 +DA:192,820 +DA:197,858 +DA:198,858 +DA:199,858 +DA:203,20596 +DA:204,9093 +DA:206,11503 +DA:207,11503 +DA:210,38739 +DA:211,38735 +DA:212,25 +DA:213,25 +DA:214,25 +DA:218,11499 +DA:220,11499 +DA:221,96 +DA:222,4 +DA:224,92 +DA:225,92 +DA:231,25863 +DA:235,6533 +DA:236,6533 +DA:237,6533 +DA:241,38739 +DA:242,6156 +DA:244,32583 +DA:245,18770 +DA:246,4954 +DA:247,18770 +DA:250,13813 +DA:251,6541 +DA:252,4 +DA:254,6537 +DA:256,13811 +DA:257,6453 +DA:260,7358 +DA:261,24 +DA:263,7334 +DA:264,860 +DA:265,2 +DA:267,858 +DA:268,859 +DA:269,821 +DA:273,6512 +DA:274,6511 +DA:275,1 +DA:276,1 +DA:279,6510 +DA:280,1581 +DA:284,6537 +DA:286,1 +DA:302,6512 +DA:303,6512 +DA:304,6512 +DA:305,6508 +DA:306,1 +DA:308,2 +DA:313,248 +DA:314,158 +DA:319,6448 +DA:321,6448 +DA:322,820 +DA:323,6393 +DA:327,6393 +DA:328,6393 +DA:331,6448 +DA:332,6448 +DA:334,6448 +DA:335,6336 +DA:336,11830 +DA:337,156 +DA:340,112 +DA:341,199 +DA:342,53 +DA:347,265 +DA:348,214 +DA:349,265 +DA:355,47 +DA:356,47 +DA:364,84 +DA:365,84 +DA:369,37 +DA:374,87 +DA:375,87 +DA:377,87 +DA:378,38 +DA:379,48 +DA:384,48 +DA:385,48 +DA:388,87 +DA:389,31 +DA:390,39 +DA:393,56 +DA:394,106 +DA:399,5 +DA:401,5 +LF:222 +LH:222 +BRDA:14,0,0,6566 +BRDA:14,0,1,1 +BRDA:61,1,0,122 +BRDA:61,1,1,5 +BRDA:63,2,0,122 +BRDA:63,2,1,22 +BRDA:68,3,0,122 +BRDA:68,3,1,115 +BRDA:69,4,0,122 +BRDA:69,4,1,121 +BRDA:70,5,0,122 +BRDA:70,5,1,121 +BRDA:71,6,0,122 +BRDA:71,6,1,121 +BRDA:73,7,0,3 +BRDA:73,7,1,119 +BRDA:77,8,0,5 +BRDA:77,8,1,117 +BRDA:78,9,0,4 +BRDA:78,9,1,1 +BRDA:94,10,0,41 +BRDA:94,10,1,81 +BRDA:98,11,0,122 +BRDA:98,11,1,122 +BRDA:113,12,0,21 +BRDA:113,12,1,79 +BRDA:121,13,0,1 +BRDA:121,13,1,127 +BRDA:124,14,0,27 +BRDA:124,14,1,100 +BRDA:133,15,0,1 +BRDA:133,15,1,26 +BRDA:137,16,0,2 +BRDA:137,16,1,25 +BRDA:152,17,0,34 +BRDA:152,17,1,6507 +BRDA:162,18,0,1 +BRDA:162,18,1,6452 +BRDA:166,19,0,1 +BRDA:166,19,1,6452 +BRDA:178,20,0,24 +BRDA:178,20,1,6514 +BRDA:190,21,0,1 +BRDA:190,21,1,820 +BRDA:203,22,0,9093 +BRDA:203,22,1,11503 +BRDA:208,23,0,50238 +BRDA:208,23,1,49694 +BRDA:211,24,0,25 +BRDA:211,24,1,38710 +BRDA:220,25,0,96 +BRDA:220,25,1,11403 +BRDA:220,26,0,11499 +BRDA:220,26,1,11363 +BRDA:220,26,2,97 +BRDA:221,27,0,4 +BRDA:221,27,1,92 +BRDA:231,28,0,25863 +BRDA:231,28,1,25863 +BRDA:231,28,2,25792 +BRDA:241,29,0,6156 +BRDA:241,29,1,32583 +BRDA:244,30,0,18770 +BRDA:244,30,1,13813 +BRDA:245,31,0,4954 +BRDA:245,31,1,13816 +BRDA:245,32,0,18770 +BRDA:245,32,1,9951 +BRDA:250,33,0,6541 +BRDA:250,33,1,7272 +BRDA:251,34,0,4 +BRDA:251,34,1,6537 +BRDA:256,35,0,6453 +BRDA:256,35,1,7358 +BRDA:260,36,0,24 +BRDA:260,36,1,7334 +BRDA:263,37,0,860 +BRDA:263,37,1,6474 +BRDA:263,38,0,7334 +BRDA:263,38,1,7332 +BRDA:263,38,2,1680 +BRDA:264,39,0,2 +BRDA:264,39,1,858 +BRDA:268,40,0,821 +BRDA:268,40,1,38 +BRDA:274,41,0,1 +BRDA:274,41,1,6510 +BRDA:279,42,0,1581 +BRDA:279,42,1,4929 +BRDA:279,43,0,6510 +BRDA:279,43,1,1581 +BRDA:313,44,0,158 +BRDA:313,44,1,90 +BRDA:313,45,0,248 +BRDA:313,45,1,177 +BRDA:321,46,0,820 +BRDA:321,46,1,5628 +BRDA:323,47,0,14 +BRDA:323,47,1,6379 +BRDA:324,48,0,14 +BRDA:324,48,1,4 +BRDA:327,49,0,18 +BRDA:327,49,1,6375 +BRDA:334,50,0,6336 +BRDA:334,50,1,112 +BRDA:336,51,0,156 +BRDA:336,51,1,11674 +BRDA:341,52,0,53 +BRDA:341,52,1,146 +BRDA:347,53,0,214 +BRDA:347,53,1,51 +BRDA:364,54,0,1 +BRDA:364,54,1,83 +BRDA:377,55,0,38 +BRDA:377,55,1,49 +BRDA:379,56,0,14 +BRDA:379,56,1,34 +BRDA:380,57,0,14 +BRDA:380,57,1,4 +BRDA:384,58,0,4 +BRDA:384,58,1,44 +BRDA:388,59,0,31 +BRDA:388,59,1,56 +BRF:123 +BRH:123 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/parse.js +FN:61,(anonymous_0) +FN:64,(anonymous_1) +FN:71,(anonymous_2) +FN:103,(anonymous_3) +FN:128,(anonymous_4) +FN:157,(anonymous_5) +FN:169,(anonymous_6) +FN:177,(anonymous_7) +FN:194,(anonymous_8) +FN:198,(anonymous_9) +FN:216,(anonymous_10) +FN:227,(anonymous_11) +FN:234,(anonymous_12) +FN:262,(anonymous_13) +FN:268,(anonymous_14) +FN:290,(anonymous_15) +FN:291,(anonymous_16) +FN:293,(anonymous_17) +FN:316,(anonymous_18) +FN:321,(anonymous_19) +FN:326,(anonymous_20) +FN:342,(anonymous_21) +FN:370,(anonymous_22) +FN:405,(anonymous_23) +FNF:24 +FNH:24 +FNDA:2032,(anonymous_0) +FNDA:742,(anonymous_1) +FNDA:589,(anonymous_2) +FNDA:6101,(anonymous_3) +FNDA:475,(anonymous_4) +FNDA:4299,(anonymous_5) +FNDA:1272,(anonymous_6) +FNDA:2947,(anonymous_7) +FNDA:9,(anonymous_8) +FNDA:2194,(anonymous_9) +FNDA:475,(anonymous_10) +FNDA:4328,(anonymous_11) +FNDA:455,(anonymous_12) +FNDA:2,(anonymous_13) +FNDA:669590,(anonymous_14) +FNDA:20164,(anonymous_15) +FNDA:2,(anonymous_16) +FNDA:226,(anonymous_17) +FNDA:6,(anonymous_18) +FNDA:652869,(anonymous_19) +FNDA:3449,(anonymous_20) +FNDA:655942,(anonymous_21) +FNDA:655553,(anonymous_22) +FNDA:718,(anonymous_23) +DA:23,9 +DA:24,9 +DA:25,9 +DA:26,9 +DA:27,9 +DA:28,9 +DA:29,9 +DA:30,9 +DA:31,9 +DA:33,9 +DA:34,9 +DA:35,9 +DA:36,9 +DA:37,9 +DA:38,9 +DA:39,9 +DA:40,9 +DA:41,9 +DA:42,9 +DA:43,9 +DA:44,9 +DA:45,9 +DA:46,9 +DA:47,9 +DA:48,9 +DA:49,9 +DA:50,9 +DA:51,9 +DA:52,9 +DA:53,9 +DA:54,9 +DA:55,9 +DA:56,9 +DA:57,9 +DA:58,9 +DA:59,9 +DA:61,2032 +DA:63,9 +DA:65,742 +DA:66,742 +DA:68,742 +DA:69,134 +DA:71,608 +DA:72,589 +DA:73,589 +DA:74,589 +DA:75,589 +DA:78,742 +DA:79,742 +DA:80,742 +DA:83,742 +DA:84,742 +DA:86,742 +DA:87,742 +DA:88,742 +DA:89,742 +DA:90,742 +DA:91,742 +DA:92,742 +DA:93,742 +DA:94,742 +DA:95,742 +DA:96,742 +DA:97,742 +DA:98,36 +DA:99,742 +DA:100,34 +DA:104,6101 +DA:106,6101 +DA:107,1834 +DA:108,4267 +DA:109,160 +DA:110,4107 +DA:111,40 +DA:113,4067 +DA:114,4067 +DA:115,40 +DA:116,4027 +DA:117,40 +DA:119,3987 +DA:121,3987 +DA:122,759 +DA:123,260 +DA:124,260 +DA:125,260 +DA:126,499 +DA:127,455 +DA:128,475 +DA:129,455 +DA:133,3228 +DA:134,3228 +DA:135,3228 +DA:136,1070 +DA:137,1070 +DA:139,2158 +DA:140,1028 +DA:142,1130 +DA:143,1130 +DA:146,2158 +DA:147,1675 +DA:148,1675 +DA:150,483 +DA:158,4299 +DA:160,4299 +DA:161,1653 +DA:162,1653 +DA:163,2646 +DA:164,490 +DA:166,2156 +DA:167,2156 +DA:168,2150 +DA:169,1288 +DA:170,1288 +DA:174,4293 +DA:178,2947 +DA:180,2941 +DA:188,2478 +DA:189,2478 +DA:190,2478 +DA:191,2468 +DA:192,516 +DA:194,10 +DA:200,2194 +DA:201,2194 +DA:202,2194 +DA:205,2194 +DA:207,2194 +DA:208,2121 +DA:209,2121 +DA:210,2121 +DA:213,2194 +DA:217,475 +DA:218,475 +DA:221,475 +DA:222,455 +DA:224,475 +DA:228,4328 +DA:229,3815 +DA:231,513 +DA:235,455 +DA:236,455 +DA:239,351 +DA:240,351 +DA:243,44 +DA:244,44 +DA:248,40 +DA:249,40 +DA:250,40 +DA:253,20 +DA:254,20 +DA:255,20 +DA:263,2 +DA:264,2 +DA:265,2 +DA:269,669590 +DA:270,1 +DA:273,669589 +DA:274,944 +DA:275,224 +DA:276,224 +DA:278,944 +DA:279,224 +DA:280,224 +DA:282,720 +DA:283,947 +DA:284,493 +DA:286,720 +DA:287,227 +DA:288,227 +DA:289,227 +DA:290,20164 +DA:291,227 +DA:292,2 +DA:293,227 +DA:294,226 +DA:295,226 +DA:297,227 +DA:301,669138 +DA:302,669138 +DA:303,33586 +DA:305,635552 +DA:306,669132 +DA:310,669132 +DA:315,669132 +DA:316,63 +DA:318,669132 +DA:322,652869 +DA:323,652866 +DA:327,3449 +DA:328,709 +DA:329,709 +DA:330,709 +DA:331,2 +DA:332,2 +DA:334,2 +DA:335,1 +DA:336,2 +DA:338,709 +DA:343,655942 +DA:344,10 +DA:345,655932 +DA:346,381 +DA:348,655551 +DA:349,655551 +DA:350,652859 +DA:351,652859 +DA:352,652859 +DA:353,652859 +DA:355,2692 +DA:358,655545 +DA:359,2 +DA:360,2 +DA:361,2 +DA:363,655545 +DA:366,655936 +DA:367,3068 +DA:373,655553 +DA:374,655553 +DA:375,655553 +DA:376,8295 +DA:378,6101 +DA:379,6095 +DA:380,6095 +DA:384,1719 +DA:385,1719 +DA:388,475 +DA:389,475 +DA:397,655547 +DA:398,652863 +DA:399,1 +DA:401,652862 +DA:406,718 +DA:407,717 +DA:408,113 +DA:410,604 +DA:411,604 +LF:236 +LH:236 +BRDA:65,0,0,742 +BRDA:65,0,1,22 +BRDA:68,1,0,134 +BRDA:68,1,1,608 +BRDA:79,2,0,742 +BRDA:79,2,1,462 +BRDA:80,3,0,290 +BRDA:80,3,1,452 +BRDA:97,4,0,36 +BRDA:97,4,1,706 +BRDA:99,5,0,34 +BRDA:99,5,1,708 +BRDA:106,6,0,1834 +BRDA:106,6,1,4267 +BRDA:108,7,0,160 +BRDA:108,7,1,4107 +BRDA:110,8,0,40 +BRDA:110,8,1,4067 +BRDA:114,9,0,40 +BRDA:114,9,1,4027 +BRDA:114,10,0,4067 +BRDA:114,10,1,248 +BRDA:116,11,0,40 +BRDA:116,11,1,3987 +BRDA:116,12,0,4027 +BRDA:116,12,1,3819 +BRDA:121,13,0,759 +BRDA:121,13,1,3228 +BRDA:122,14,0,260 +BRDA:122,14,1,499 +BRDA:126,15,0,455 +BRDA:126,15,1,44 +BRDA:134,16,0,3228 +BRDA:134,16,1,3226 +BRDA:135,17,0,1070 +BRDA:135,17,1,2158 +BRDA:137,18,0,382 +BRDA:137,18,1,688 +BRDA:139,19,0,1028 +BRDA:139,19,1,1130 +BRDA:146,20,0,1675 +BRDA:146,20,1,483 +BRDA:160,21,0,1653 +BRDA:160,21,1,2646 +BRDA:163,22,0,490 +BRDA:163,22,1,2156 +BRDA:168,23,0,1288 +BRDA:168,23,1,862 +BRDA:180,24,0,2478 +BRDA:180,24,1,463 +BRDA:189,25,0,2478 +BRDA:189,25,1,825 +BRDA:189,25,2,167 +BRDA:190,26,0,2468 +BRDA:190,26,1,10 +BRDA:191,27,0,516 +BRDA:191,27,1,1952 +BRDA:202,28,0,583 +BRDA:202,28,1,1611 +BRDA:202,29,0,2194 +BRDA:202,29,1,593 +BRDA:207,30,0,2121 +BRDA:207,30,1,73 +BRDA:221,31,0,455 +BRDA:221,31,1,20 +BRDA:228,32,0,3815 +BRDA:228,32,1,513 +BRDA:228,33,0,4328 +BRDA:228,33,1,3916 +BRDA:236,34,0,351 +BRDA:236,34,1,351 +BRDA:236,34,2,44 +BRDA:236,34,3,40 +BRDA:236,34,4,40 +BRDA:236,34,5,20 +BRDA:248,35,0,40 +BRDA:248,35,1,40 +BRDA:253,36,0,20 +BRDA:253,36,1,20 +BRDA:269,37,0,1 +BRDA:269,37,1,669589 +BRDA:273,38,0,944 +BRDA:273,38,1,668645 +BRDA:273,39,0,669589 +BRDA:273,39,1,944 +BRDA:274,40,0,224 +BRDA:274,40,1,720 +BRDA:278,41,0,224 +BRDA:278,41,1,720 +BRDA:282,42,0,1667 +BRDA:282,42,1,1174 +BRDA:283,43,0,493 +BRDA:283,43,1,454 +BRDA:286,44,0,227 +BRDA:286,44,1,493 +BRDA:297,45,0,113 +BRDA:297,45,1,114 +BRDA:302,46,0,33586 +BRDA:302,46,1,635552 +BRDA:310,47,0,190 +BRDA:310,47,1,668942 +BRDA:311,48,0,61606 +BRDA:311,48,1,607336 +BRDA:315,49,0,63 +BRDA:315,49,1,669069 +BRDA:315,50,0,669132 +BRDA:315,50,1,253 +BRDA:322,51,0,652866 +BRDA:322,51,1,3 +BRDA:322,52,0,652869 +BRDA:322,52,1,652866 +BRDA:323,53,0,652864 +BRDA:323,53,1,2 +BRDA:327,54,0,709 +BRDA:327,54,1,2740 +BRDA:327,55,0,3449 +BRDA:327,55,1,1094 +BRDA:327,55,2,710 +BRDA:330,56,0,2 +BRDA:330,56,1,707 +BRDA:330,57,0,709 +BRDA:330,57,1,255 +BRDA:331,58,0,1 +BRDA:331,58,1,1 +BRDA:334,59,0,1 +BRDA:334,59,1,1 +BRDA:343,60,0,10 +BRDA:343,60,1,655932 +BRDA:345,61,0,381 +BRDA:345,61,1,655551 +BRDA:345,62,0,655932 +BRDA:345,62,1,382 +BRDA:349,63,0,652859 +BRDA:349,63,1,2692 +BRDA:358,64,0,655547 +BRDA:358,64,1,652864 +BRDA:358,64,2,2 +BRDA:366,65,0,3068 +BRDA:366,65,1,652868 +BRDA:366,66,0,655936 +BRDA:366,66,1,652872 +BRDA:375,67,0,663842 +BRDA:375,67,1,8295 +BRDA:376,68,0,6101 +BRDA:376,68,1,670 +BRDA:376,68,2,1719 +BRDA:376,68,3,475 +BRDA:397,69,0,652863 +BRDA:397,69,1,2684 +BRDA:398,70,0,1 +BRDA:398,70,1,652862 +BRDA:406,71,0,717 +BRDA:406,71,1,1 +BRDA:407,72,0,113 +BRDA:407,72,1,604 +BRF:155 +BRH:155 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/pax.js +FN:6,(anonymous_0) +FN:25,(anonymous_1) +FN:71,(anonymous_2) +FN:91,(anonymous_3) +FN:112,(anonymous_4) +FN:114,(anonymous_5) +FN:115,(anonymous_6) +FN:117,(anonymous_7) +FN:123,(anonymous_8) +FNF:9 +FNH:9 +FNDA:435,(anonymous_0) +FNDA:34,(anonymous_1) +FNDA:34,(anonymous_2) +FNDA:510,(anonymous_3) +FNDA:401,(anonymous_4) +FNDA:401,(anonymous_5) +FNDA:1,(anonymous_6) +FNDA:401,(anonymous_7) +FNDA:2259,(anonymous_8) +DA:2,11 +DA:3,11 +DA:7,435 +DA:8,435 +DA:9,435 +DA:10,435 +DA:11,435 +DA:12,435 +DA:13,435 +DA:14,435 +DA:15,435 +DA:16,435 +DA:17,435 +DA:18,435 +DA:19,435 +DA:20,435 +DA:21,435 +DA:22,435 +DA:26,34 +DA:27,34 +DA:28,1 +DA:30,33 +DA:33,33 +DA:34,33 +DA:37,33 +DA:38,16896 +DA:41,33 +DA:61,33 +DA:64,33 +DA:65,8949 +DA:68,33 +DA:72,34 +DA:92,510 +DA:93,204 +DA:94,306 +DA:96,306 +DA:100,306 +DA:104,306 +DA:105,306 +DA:106,30 +DA:107,306 +DA:108,306 +DA:112,401 +DA:114,11 +DA:115,401 +DA:117,11 +DA:118,401 +DA:123,11 +DA:124,2259 +DA:128,2259 +DA:129,5 +DA:131,2254 +DA:132,2254 +DA:133,2254 +DA:134,2254 +DA:135,1 +DA:137,2253 +DA:138,2253 +DA:142,2253 +DA:145,11 +LF:60 +LH:60 +BRDA:7,0,0,435 +BRDA:7,0,1,85 +BRDA:8,1,0,435 +BRDA:8,1,1,435 +BRDA:9,2,0,435 +BRDA:9,2,1,411 +BRDA:10,3,0,435 +BRDA:10,3,1,85 +BRDA:11,4,0,435 +BRDA:11,4,1,369 +BRDA:12,5,0,435 +BRDA:12,5,1,410 +BRDA:13,6,0,435 +BRDA:13,6,1,435 +BRDA:14,7,0,435 +BRDA:14,7,1,368 +BRDA:15,8,0,435 +BRDA:15,8,1,2 +BRDA:16,9,0,435 +BRDA:16,9,1,363 +BRDA:17,10,0,435 +BRDA:17,10,1,371 +BRDA:18,11,0,435 +BRDA:18,11,1,373 +BRDA:19,12,0,435 +BRDA:19,12,1,86 +BRDA:20,13,0,435 +BRDA:20,13,1,86 +BRDA:21,14,0,435 +BRDA:21,14,1,86 +BRDA:22,15,0,435 +BRDA:22,15,1,389 +BRDA:27,16,0,1 +BRDA:27,16,1,33 +BRDA:46,17,0,33 +BRDA:46,17,1,33 +BRDA:47,18,0,33 +BRDA:47,18,1,6 +BRDA:48,19,0,33 +BRDA:48,19,1,6 +BRDA:50,20,0,33 +BRDA:50,20,1,5 +BRDA:51,21,0,1 +BRDA:51,21,1,32 +BRDA:53,22,0,33 +BRDA:53,22,1,7 +BRDA:54,23,0,33 +BRDA:54,23,1,32 +BRDA:57,24,0,33 +BRDA:57,24,1,6 +BRDA:58,25,0,33 +BRDA:58,25,1,6 +BRDA:92,26,0,204 +BRDA:92,26,1,306 +BRDA:92,27,0,510 +BRDA:92,27,1,306 +BRDA:94,28,0,82 +BRDA:94,28,1,224 +BRDA:97,29,0,78 +BRDA:97,29,1,228 +BRDA:97,30,0,306 +BRDA:97,30,1,280 +BRDA:97,30,2,254 +BRDA:105,31,0,30 +BRDA:105,31,1,276 +BRDA:115,32,0,1 +BRDA:115,32,1,400 +BRDA:128,33,0,5 +BRDA:128,33,1,2254 +BRDA:134,34,0,1 +BRDA:134,34,1,2253 +BRDA:138,35,0,685 +BRDA:138,35,1,1568 +BRDA:140,36,0,1084 +BRDA:140,36,1,484 +BRF:75 +BRH:75 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/read-entry.js +FN:7,(anonymous_0) +FN:66,(anonymous_1) +FN:85,(anonymous_2) +FNF:3 +FNH:3 +FNDA:4004,(anonymous_0) +FNDA:2222,(anonymous_1) +FNDA:457,(anonymous_2) +DA:2,11 +DA:3,11 +DA:5,11 +DA:6,11 +DA:8,4004 +DA:9,4004 +DA:10,4004 +DA:11,4004 +DA:12,4004 +DA:13,4004 +DA:14,4004 +DA:15,4004 +DA:16,4004 +DA:17,4004 +DA:18,4004 +DA:29,3241 +DA:37,760 +DA:38,760 +DA:43,3 +DA:46,4004 +DA:47,4004 +DA:48,4004 +DA:49,3720 +DA:50,4004 +DA:51,4004 +DA:52,4004 +DA:53,4004 +DA:54,4004 +DA:55,4004 +DA:56,4004 +DA:57,4004 +DA:58,4004 +DA:59,4004 +DA:60,4004 +DA:62,4004 +DA:63,4004 +DA:67,2222 +DA:68,2222 +DA:69,2 +DA:71,2220 +DA:72,2220 +DA:73,2220 +DA:74,2220 +DA:75,2220 +DA:76,673 +DA:78,1547 +DA:79,132 +DA:82,1415 +DA:86,457 +DA:89,6384 +DA:91,2657 +LF:51 +LH:51 +BRDA:18,0,0,1502 +BRDA:18,0,1,1502 +BRDA:18,0,2,1565 +BRDA:18,0,3,1710 +BRDA:18,0,4,1712 +BRDA:18,0,5,1714 +BRDA:18,0,6,3239 +BRDA:18,0,7,3241 +BRDA:18,0,8,3241 +BRDA:18,0,9,3241 +BRDA:18,0,10,41 +BRDA:18,0,11,121 +BRDA:18,0,12,121 +BRDA:18,0,13,165 +BRDA:18,0,14,760 +BRDA:18,0,15,760 +BRDA:18,0,16,3 +BRDA:48,1,0,3720 +BRDA:48,1,1,284 +BRDA:62,2,0,412 +BRDA:62,2,1,3592 +BRDA:63,3,0,45 +BRDA:63,3,1,3959 +BRDA:68,4,0,2 +BRDA:68,4,1,2220 +BRDA:75,5,0,673 +BRDA:75,5,1,1547 +BRDA:78,6,0,132 +BRDA:78,6,1,1415 +BRDA:89,7,0,2657 +BRDA:89,7,1,3727 +BRDA:89,8,0,6384 +BRDA:89,8,1,2702 +BRDA:89,8,2,2701 +BRDA:90,9,0,2701 +BRDA:90,9,1,89 +BRF:36 +BRH:36 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/replace.js +FN:20,(anonymous_0) +FN:38,(anonymous_1) +FN:92,(anonymous_2) +FN:101,(anonymous_3) +FN:105,(anonymous_4) +FN:106,(anonymous_5) +FN:108,(anonymous_6) +FN:119,(anonymous_7) +FN:156,(anonymous_8) +FN:159,(anonymous_9) +FN:168,(anonymous_10) +FN:171,(anonymous_11) +FN:191,(anonymous_12) +FN:192,(anonymous_13) +FN:198,(anonymous_14) +FN:206,(anonymous_15) +FN:213,(anonymous_16) +FN:214,(anonymous_17) +FNF:18 +FNH:18 +FNDA:70,(anonymous_0) +FNDA:26,(anonymous_1) +FNDA:18,(anonymous_2) +FNDA:41,(anonymous_3) +FNDA:37,(anonymous_4) +FNDA:37,(anonymous_5) +FNDA:4,(anonymous_6) +FNDA:112,(anonymous_7) +FNDA:41,(anonymous_8) +FNDA:45,(anonymous_9) +FNDA:39,(anonymous_10) +FNDA:37,(anonymous_11) +FNDA:18,(anonymous_12) +FNDA:19,(anonymous_13) +FNDA:3,(anonymous_14) +FNDA:34,(anonymous_15) +FNDA:3,(anonymous_16) +FNDA:1,(anonymous_17) +DA:4,3 +DA:5,3 +DA:6,3 +DA:7,3 +DA:8,3 +DA:9,3 +DA:10,3 +DA:18,3 +DA:20,3 +DA:21,70 +DA:23,70 +DA:24,1 +DA:26,69 +DA:27,1 +DA:29,68 +DA:30,1 +DA:32,67 +DA:34,67 +DA:38,3 +DA:39,26 +DA:41,26 +DA:45,26 +DA:46,26 +DA:47,26 +DA:49,4 +DA:50,2 +DA:52,2 +DA:55,24 +DA:56,22 +DA:58,22 +DA:59,61 +DA:60,63 +DA:64,61 +DA:65,2 +DA:67,59 +DA:68,2 +DA:71,55 +DA:72,55 +DA:73,8 +DA:74,47 +DA:75,47 +DA:76,2 +DA:79,45 +DA:80,45 +DA:81,28 +DA:83,18 +DA:85,18 +DA:87,26 +DA:88,8 +DA:92,3 +DA:93,18 +DA:97,18 +DA:98,18 +DA:101,3 +DA:102,41 +DA:103,41 +DA:105,41 +DA:106,37 +DA:107,37 +DA:108,4 +DA:110,33 +DA:113,37 +DA:114,37 +DA:115,8 +DA:117,29 +DA:118,29 +DA:119,29 +DA:120,112 +DA:121,2 +DA:122,110 +DA:123,110 +DA:124,6 +DA:129,104 +DA:130,2 +DA:133,102 +DA:134,4 +DA:136,98 +DA:137,98 +DA:138,13 +DA:140,85 +DA:141,85 +DA:142,4 +DA:144,81 +DA:145,81 +DA:146,4 +DA:148,77 +DA:149,46 +DA:150,77 +DA:151,77 +DA:153,29 +DA:156,41 +DA:157,41 +DA:158,41 +DA:159,41 +DA:160,45 +DA:161,4 +DA:162,4 +DA:165,41 +DA:166,2 +DA:168,39 +DA:169,39 +DA:170,2 +DA:171,37 +DA:172,37 +DA:173,4 +DA:174,33 +DA:178,33 +DA:179,33 +DA:180,33 +DA:181,33 +DA:185,41 +DA:188,41 +DA:191,3 +DA:192,18 +DA:193,19 +DA:194,1 +DA:198,3 +DA:201,18 +DA:203,18 +DA:206,3 +DA:207,34 +DA:208,33 +DA:209,33 +DA:210,1 +DA:213,3 +DA:214,1 +DA:216,32 +DA:218,33 +LF:128 +LH:128 +BRDA:23,0,0,1 +BRDA:23,0,1,69 +BRDA:26,1,0,1 +BRDA:26,1,1,68 +BRDA:29,2,0,1 +BRDA:29,2,1,67 +BRDA:29,3,0,68 +BRDA:29,3,1,68 +BRDA:29,3,2,68 +BRDA:34,4,0,26 +BRDA:34,4,1,41 +BRDA:49,5,0,2 +BRDA:49,5,1,2 +BRDA:64,6,0,2 +BRDA:64,6,1,59 +BRDA:64,7,0,61 +BRDA:64,7,1,16 +BRDA:64,7,2,2 +BRDA:67,8,0,2 +BRDA:67,8,1,57 +BRDA:72,9,0,8 +BRDA:72,9,1,47 +BRDA:75,10,0,2 +BRDA:75,10,1,45 +BRDA:80,11,0,28 +BRDA:80,11,1,17 +BRDA:87,12,0,8 +BRDA:87,12,1,18 +BRDA:107,13,0,4 +BRDA:107,13,1,33 +BRDA:114,14,0,8 +BRDA:114,14,1,29 +BRDA:120,15,0,2 +BRDA:120,15,1,110 +BRDA:123,16,0,6 +BRDA:123,16,1,104 +BRDA:123,17,0,110 +BRDA:123,17,1,12 +BRDA:129,18,0,2 +BRDA:129,18,1,102 +BRDA:129,19,0,104 +BRDA:129,19,1,27 +BRDA:129,19,2,2 +BRDA:133,20,0,4 +BRDA:133,20,1,98 +BRDA:137,21,0,13 +BRDA:137,21,1,85 +BRDA:141,22,0,4 +BRDA:141,22,1,81 +BRDA:145,23,0,4 +BRDA:145,23,1,77 +BRDA:148,24,0,46 +BRDA:148,24,1,31 +BRDA:160,25,0,4 +BRDA:160,25,1,41 +BRDA:160,26,0,45 +BRDA:160,26,1,6 +BRDA:160,26,2,4 +BRDA:165,27,0,2 +BRDA:165,27,1,39 +BRDA:169,28,0,2 +BRDA:169,28,1,37 +BRDA:172,29,0,4 +BRDA:172,29,1,33 +BRDA:188,30,0,24 +BRDA:188,30,1,17 +BRDA:193,31,0,1 +BRDA:193,31,1,18 +BRDA:209,32,0,1 +BRDA:209,32,1,32 +BRF:70 +BRH:70 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/types.js +FN:44,(anonymous_0) +FNF:1 +FNH:1 +FNDA:294,(anonymous_0) +DA:3,14 +DA:44,294 +LF:2 +LH:2 +BRF:0 +BRH:0 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/unpack.js +FN:37,(anonymous_0) +FN:43,(anonymous_1) +FN:47,(anonymous_2) +FN:117,(anonymous_3) +FN:120,(anonymous_4) +FN:129,(anonymous_5) +FN:168,(anonymous_6) +FN:194,(anonymous_7) +FN:207,(anonymous_8) +FN:222,(anonymous_9) +FN:233,(anonymous_10) +FN:237,(anonymous_11) +FN:241,(anonymous_12) +FN:247,(anonymous_13) +FN:250,(anonymous_14) +FN:257,(anonymous_15) +FN:260,(anonymous_16) +FN:277,(anonymous_17) +FN:279,(anonymous_18) +FN:284,(anonymous_19) +FN:305,(anonymous_20) +FN:310,(anonymous_21) +FN:314,(anonymous_22) +FN:318,(anonymous_23) +FN:322,(anonymous_24) +FN:327,(anonymous_25) +FN:333,(anonymous_26) +FN:335,(anonymous_27) +FN:338,(anonymous_28) +FN:348,(anonymous_29) +FN:350,(anonymous_30) +FN:352,(anonymous_31) +FN:357,(anonymous_32) +FN:379,(anonymous_33) +FN:381,(anonymous_34) +FN:391,(anonymous_35) +FN:395,(anonymous_36) +FN:425,(anonymous_37) +FN:428,(anonymous_38) +FN:441,(anonymous_39) +FN:449,(anonymous_40) +FN:465,(anonymous_41) +FN:483,(anonymous_42) +FN:502,(anonymous_43) +FNF:44 +FNH:44 +FNDA:60,(anonymous_0) +FNDA:134,(anonymous_1) +FNDA:109,(anonymous_2) +FNDA:571,(anonymous_3) +FNDA:473,(anonymous_4) +FNDA:571,(anonymous_5) +FNDA:571,(anonymous_6) +FNDA:39,(anonymous_7) +FNDA:451,(anonymous_8) +FNDA:473,(anonymous_9) +FNDA:30,(anonymous_10) +FNDA:30,(anonymous_11) +FNDA:221,(anonymous_12) +FNDA:2,(anonymous_13) +FNDA:421,(anonymous_14) +FNDA:219,(anonymous_15) +FNDA:219,(anonymous_16) +FNDA:97,(anonymous_17) +FNDA:97,(anonymous_18) +FNDA:171,(anonymous_19) +FNDA:6,(anonymous_20) +FNDA:21,(anonymous_21) +FNDA:19,(anonymous_22) +FNDA:354,(anonymous_23) +FNDA:364,(anonymous_24) +FNDA:4,(anonymous_25) +FNDA:354,(anonymous_26) +FNDA:354,(anonymous_27) +FNDA:342,(anonymous_28) +FNDA:2,(anonymous_29) +FNDA:5,(anonymous_30) +FNDA:6,(anonymous_31) +FNDA:528,(anonymous_32) +FNDA:21,(anonymous_33) +FNDA:21,(anonymous_34) +FNDA:59,(anonymous_35) +FNDA:200,(anonymous_36) +FNDA:93,(anonymous_37) +FNDA:6,(anonymous_38) +FNDA:86,(anonymous_39) +FNDA:86,(anonymous_40) +FNDA:76,(anonymous_41) +FNDA:276,(anonymous_42) +FNDA:19,(anonymous_43) +DA:3,3 +DA:4,3 +DA:5,3 +DA:6,3 +DA:7,3 +DA:8,3 +DA:9,3 +DA:10,3 +DA:11,3 +DA:13,3 +DA:14,3 +DA:15,3 +DA:16,3 +DA:17,3 +DA:18,3 +DA:19,3 +DA:20,3 +DA:21,3 +DA:22,3 +DA:23,3 +DA:24,3 +DA:25,3 +DA:26,3 +DA:27,3 +DA:28,3 +DA:29,3 +DA:30,3 +DA:31,3 +DA:32,3 +DA:33,3 +DA:34,3 +DA:37,3 +DA:38,60 +DA:44,134 +DA:45,4 +DA:47,134 +DA:48,109 +DA:49,109 +DA:52,134 +DA:54,134 +DA:55,134 +DA:57,134 +DA:58,134 +DA:60,134 +DA:62,134 +DA:64,9 +DA:65,2 +DA:66,7 +DA:67,1 +DA:69,6 +DA:70,6 +DA:71,6 +DA:73,125 +DA:74,125 +DA:75,125 +DA:79,131 +DA:80,119 +DA:82,12 +DA:84,131 +DA:86,131 +DA:90,131 +DA:93,131 +DA:96,131 +DA:99,131 +DA:104,131 +DA:108,131 +DA:110,131 +DA:111,131 +DA:112,131 +DA:113,131 +DA:115,131 +DA:116,131 +DA:117,571 +DA:121,473 +DA:122,98 +DA:123,98 +DA:124,98 +DA:125,98 +DA:130,571 +DA:131,144 +DA:132,144 +DA:133,9 +DA:134,135 +DA:137,562 +DA:138,545 +DA:139,545 +DA:140,2 +DA:141,2 +DA:146,543 +DA:147,2 +DA:148,2 +DA:149,2 +DA:154,560 +DA:155,3 +DA:156,3 +DA:160,560 +DA:161,2 +DA:163,558 +DA:165,560 +DA:169,571 +DA:170,11 +DA:172,560 +DA:174,560 +DA:177,179 +DA:178,140 +DA:185,554 +DA:190,6 +DA:198,39 +DA:199,12 +DA:201,27 +DA:202,27 +DA:203,27 +DA:208,451 +DA:225,473 +DA:234,30 +DA:238,30 +DA:242,221 +DA:243,221 +DA:247,221 +DA:249,221 +DA:250,221 +DA:251,421 +DA:252,1 +DA:253,1 +DA:256,421 +DA:257,219 +DA:260,221 +DA:261,219 +DA:262,192 +DA:263,192 +DA:266,219 +DA:267,10 +DA:268,10 +DA:271,219 +DA:274,221 +DA:278,97 +DA:279,97 +DA:280,97 +DA:281,3 +DA:283,94 +DA:284,94 +DA:285,171 +DA:286,94 +DA:287,94 +DA:291,94 +DA:292,73 +DA:293,73 +DA:296,94 +DA:297,4 +DA:298,4 +DA:301,94 +DA:306,6 +DA:307,6 +DA:311,21 +DA:315,19 +DA:319,354 +DA:323,364 +DA:324,364 +DA:328,4 +DA:329,4 +DA:334,354 +DA:335,354 +DA:336,354 +DA:337,12 +DA:338,342 +DA:339,342 +DA:340,2 +DA:341,340 +DA:342,318 +DA:343,22 +DA:344,16 +DA:345,11 +DA:346,9 +DA:348,2 +DA:350,5 +DA:352,6 +DA:358,528 +DA:359,1 +DA:361,527 +DA:365,314 +DA:368,19 +DA:371,21 +DA:375,173 +DA:381,21 +DA:382,21 +DA:383,1 +DA:384,20 +DA:385,20 +DA:392,59 +DA:396,200 +DA:397,200 +DA:398,9 +DA:399,191 +DA:400,191 +DA:401,17 +DA:402,2 +DA:403,15 +DA:404,2 +DA:406,13 +DA:407,13 +DA:408,6 +DA:409,3 +DA:410,2 +DA:412,3 +DA:414,7 +DA:415,12 +DA:417,1 +DA:421,174 +DA:426,93 +DA:428,93 +DA:429,6 +DA:430,6 +DA:435,93 +DA:436,93 +DA:438,1 +DA:441,92 +DA:442,86 +DA:443,86 +DA:445,1 +DA:449,92 +DA:450,86 +DA:451,86 +DA:452,58 +DA:454,85 +DA:455,12 +DA:457,82 +DA:459,4 +DA:466,76 +DA:467,76 +DA:468,76 +DA:469,1 +DA:470,75 +DA:471,56 +DA:472,56 +DA:475,75 +DA:476,4 +DA:477,4 +DA:480,75 +DA:484,276 +DA:485,276 +DA:498,4 +DA:503,19 +DA:504,19 +DA:505,17 +DA:507,2 +DA:512,3 +DA:513,3 +LF:247 +LH:247 +BRDA:38,0,0,24 +BRDA:38,0,1,36 +BRDA:39,1,0,26 +BRDA:39,1,1,10 +BRDA:44,2,0,4 +BRDA:44,2,1,130 +BRDA:60,3,0,134 +BRDA:60,3,1,134 +BRDA:62,4,0,9 +BRDA:62,4,1,125 +BRDA:62,5,0,134 +BRDA:62,5,1,126 +BRDA:64,6,0,2 +BRDA:64,6,1,7 +BRDA:64,7,0,9 +BRDA:64,7,1,8 +BRDA:66,8,0,1 +BRDA:66,8,1,6 +BRDA:79,9,0,119 +BRDA:79,9,1,12 +BRDA:79,10,0,131 +BRDA:79,10,1,125 +BRDA:80,11,0,119 +BRDA:80,11,1,119 +BRDA:84,12,0,11 +BRDA:84,12,1,120 +BRDA:84,13,0,131 +BRDA:84,13,1,126 +BRDA:84,13,2,11 +BRDA:86,14,0,11 +BRDA:86,14,1,120 +BRDA:86,15,0,131 +BRDA:86,15,1,126 +BRDA:86,15,2,11 +BRDA:90,16,0,131 +BRDA:90,16,1,128 +BRDA:110,17,0,131 +BRDA:110,17,1,11 +BRDA:111,18,0,131 +BRDA:111,18,1,129 +BRDA:113,19,0,1 +BRDA:113,19,1,130 +BRDA:115,20,0,131 +BRDA:115,20,1,131 +BRDA:116,21,0,131 +BRDA:116,21,1,127 +BRDA:121,22,0,98 +BRDA:121,22,1,375 +BRDA:121,23,0,473 +BRDA:121,23,1,178 +BRDA:130,24,0,144 +BRDA:130,24,1,427 +BRDA:132,25,0,9 +BRDA:132,25,1,135 +BRDA:137,26,0,545 +BRDA:137,26,1,17 +BRDA:139,27,0,2 +BRDA:139,27,1,543 +BRDA:146,28,0,2 +BRDA:146,28,1,541 +BRDA:154,29,0,3 +BRDA:154,29,1,557 +BRDA:156,30,0,2 +BRDA:156,30,1,1 +BRDA:160,31,0,2 +BRDA:160,31,1,558 +BRDA:169,32,0,11 +BRDA:169,32,1,560 +BRDA:174,33,0,179 +BRDA:174,33,1,179 +BRDA:174,33,2,514 +BRDA:174,33,3,514 +BRDA:174,33,4,514 +BRDA:174,33,5,533 +BRDA:174,33,6,554 +BRDA:174,33,7,2 +BRDA:174,33,8,4 +BRDA:174,33,9,6 +BRDA:177,34,0,140 +BRDA:177,34,1,39 +BRDA:198,35,0,12 +BRDA:198,35,1,27 +BRDA:225,36,0,473 +BRDA:225,36,1,34 +BRDA:225,36,2,31 +BRDA:225,36,3,23 +BRDA:225,36,4,15 +BRDA:225,36,5,455 +BRDA:225,36,6,12 +BRDA:225,36,7,447 +BRDA:225,36,8,4 +BRDA:242,37,0,221 +BRDA:242,37,1,30 +BRDA:251,38,0,1 +BRDA:251,38,1,420 +BRDA:256,39,0,219 +BRDA:256,39,1,202 +BRDA:261,40,0,192 +BRDA:261,40,1,27 +BRDA:261,41,0,219 +BRDA:261,41,1,193 +BRDA:263,42,0,192 +BRDA:263,42,1,156 +BRDA:266,43,0,10 +BRDA:266,43,1,209 +BRDA:278,44,0,97 +BRDA:278,44,1,20 +BRDA:280,45,0,3 +BRDA:280,45,1,94 +BRDA:285,46,0,94 +BRDA:285,46,1,77 +BRDA:291,47,0,73 +BRDA:291,47,1,21 +BRDA:291,48,0,94 +BRDA:291,48,1,74 +BRDA:293,49,0,73 +BRDA:293,49,1,71 +BRDA:296,50,0,4 +BRDA:296,50,1,90 +BRDA:336,51,0,12 +BRDA:336,51,1,342 +BRDA:339,52,0,2 +BRDA:339,52,1,340 +BRDA:339,53,0,342 +BRDA:339,53,1,27 +BRDA:339,53,2,26 +BRDA:339,53,3,1 +BRDA:341,54,0,318 +BRDA:341,54,1,22 +BRDA:341,55,0,340 +BRDA:341,55,1,25 +BRDA:341,55,2,6 +BRDA:341,55,3,5 +BRDA:343,56,0,16 +BRDA:343,56,1,6 +BRDA:344,57,0,11 +BRDA:344,57,1,5 +BRDA:345,58,0,9 +BRDA:345,58,1,2 +BRDA:345,59,0,11 +BRDA:345,59,1,8 +BRDA:358,60,0,1 +BRDA:358,60,1,527 +BRDA:361,61,0,314 +BRDA:361,61,1,314 +BRDA:361,61,2,314 +BRDA:361,61,3,19 +BRDA:361,61,4,21 +BRDA:361,61,5,173 +BRDA:361,61,6,173 +BRDA:382,62,0,1 +BRDA:382,62,1,20 +BRDA:397,63,0,9 +BRDA:397,63,1,191 +BRDA:401,64,0,2 +BRDA:401,64,1,15 +BRDA:401,65,0,17 +BRDA:401,65,1,16 +BRDA:401,65,2,1 +BRDA:403,66,0,2 +BRDA:403,66,1,13 +BRDA:403,67,0,15 +BRDA:403,67,1,4 +BRDA:403,67,2,3 +BRDA:407,68,0,6 +BRDA:407,68,1,7 +BRDA:408,69,0,3 +BRDA:408,69,1,3 +BRDA:409,70,0,2 +BRDA:409,70,1,1 +BRDA:409,71,0,3 +BRDA:409,71,1,2 +BRDA:426,72,0,93 +BRDA:426,72,1,30 +BRDA:451,73,0,58 +BRDA:451,73,1,28 +BRDA:451,74,0,86 +BRDA:451,74,1,59 +BRDA:452,75,0,58 +BRDA:452,75,1,31 +BRDA:454,76,0,12 +BRDA:454,76,1,73 +BRDA:466,77,0,76 +BRDA:466,77,1,19 +BRDA:468,78,0,1 +BRDA:468,78,1,75 +BRDA:470,79,0,56 +BRDA:470,79,1,19 +BRDA:470,80,0,75 +BRDA:470,80,1,57 +BRDA:472,81,0,56 +BRDA:472,81,1,52 +BRDA:475,82,0,4 +BRDA:475,82,1,71 +BRF:194 +BRH:194 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/update.js +FN:9,(anonymous_0) +FN:27,(anonymous_1) +FN:33,(anonymous_2) +FN:35,(anonymous_3) +FNF:4 +FNH:4 +FNDA:36,(anonymous_0) +FNDA:33,(anonymous_1) +FNDA:2,(anonymous_2) +FNDA:24,(anonymous_3) +DA:5,2 +DA:6,2 +DA:9,2 +DA:10,36 +DA:12,36 +DA:13,1 +DA:15,35 +DA:16,1 +DA:18,34 +DA:19,1 +DA:21,33 +DA:23,33 +DA:24,33 +DA:27,2 +DA:28,33 +DA:30,33 +DA:31,32 +DA:33,33 +DA:34,2 +DA:35,24 +LF:20 +LH:20 +BRDA:12,0,0,1 +BRDA:12,0,1,35 +BRDA:15,1,0,1 +BRDA:15,1,1,34 +BRDA:18,2,0,1 +BRDA:18,2,1,33 +BRDA:18,3,0,34 +BRDA:18,3,1,34 +BRDA:18,3,2,34 +BRDA:30,4,0,32 +BRDA:30,4,1,1 +BRDA:33,5,0,1 +BRDA:33,5,1,32 +BRDA:34,6,0,2 +BRDA:34,6,1,1 +BRF:15 +BRH:15 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/warn-mixin.js +FN:2,(anonymous_0) +FN:3,(anonymous_1) +FNF:2 +FNH:2 +FNDA:27,(anonymous_0) +FNDA:333,(anonymous_1) +DA:2,27 +DA:4,333 +DA:5,184 +DA:6,149 +DA:7,2 +DA:9,147 +DA:10,147 +DA:11,147 +LF:8 +LH:8 +BRDA:4,0,0,184 +BRDA:4,0,1,149 +BRDA:6,1,0,2 +BRDA:6,1,1,147 +BRF:4 +BRH:4 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/winchars.js +FN:14,(anonymous_0) +FN:17,(anonymous_1) +FN:18,(anonymous_2) +FN:21,(anonymous_3) +FN:21,(anonymous_4) +FN:22,(anonymous_5) +FN:22,(anonymous_6) +FNF:7 +FNH:7 +FNDA:45,(anonymous_0) +FNDA:45,(anonymous_1) +FNDA:45,(anonymous_2) +FNDA:6,(anonymous_3) +FNDA:30,(anonymous_4) +FNDA:4,(anonymous_5) +FNDA:20,(anonymous_6) +DA:6,9 +DA:14,9 +DA:15,45 +DA:17,45 +DA:18,45 +DA:20,9 +DA:21,30 +DA:22,20 +LF:8 +LH:8 +BRF:0 +BRH:0 +end_of_record +TN: +SF:/Users/isaacs/dev/js/tar/lib/write-entry.js +FN:29,(anonymous_0) +FN:77,(anonymous_1) +FN:78,(anonymous_2) +FN:85,(anonymous_3) +FN:95,(anonymous_4) +FN:105,(anonymous_5) +FN:144,(anonymous_6) +FN:152,(anonymous_7) +FN:153,(anonymous_8) +FN:160,(anonymous_9) +FN:166,(anonymous_10) +FN:174,(anonymous_11) +FN:192,(anonymous_12) +FN:193,(anonymous_13) +FN:200,(anonymous_14) +FN:207,(anonymous_15) +FN:208,(anonymous_16) +FN:210,(anonymous_17) +FN:215,(anonymous_18) +FN:219,(anonymous_19) +FN:250,(anonymous_20) +FN:264,(anonymous_21) +FN:268,(anonymous_22) +FN:272,(anonymous_23) +FN:276,(anonymous_24) +FN:280,(anonymous_25) +FN:292,(anonymous_26) +FN:298,(anonymous_27) +FN:377,(anonymous_28) +FN:385,(anonymous_29) +FN:395,(anonymous_30) +FNF:31 +FNH:31 +FNDA:6570,(anonymous_0) +FNDA:34,(anonymous_1) +FNDA:34,(anonymous_2) +FNDA:6566,(anonymous_3) +FNDA:6566,(anonymous_4) +FNDA:6563,(anonymous_5) +FNDA:867,(anonymous_6) +FNDA:32,(anonymous_7) +FNDA:32,(anonymous_8) +FNDA:32,(anonymous_9) +FNDA:1,(anonymous_10) +FNDA:5664,(anonymous_11) +FNDA:5568,(anonymous_12) +FNDA:5568,(anonymous_13) +FNDA:5617,(anonymous_14) +FNDA:7336,(anonymous_15) +FNDA:7336,(anonymous_16) +FNDA:1,(anonymous_17) +FNDA:5566,(anonymous_18) +FNDA:7393,(anonymous_19) +FNDA:5565,(anonymous_20) +FNDA:99,(anonymous_21) +FNDA:20,(anonymous_22) +FNDA:2,(anonymous_23) +FNDA:53,(anonymous_24) +FNDA:59,(anonymous_25) +FNDA:51,(anonymous_26) +FNDA:33,(anonymous_27) +FNDA:52,(anonymous_28) +FNDA:29,(anonymous_29) +FNDA:6566,(anonymous_30) +DA:2,6 +DA:3,6 +DA:4,6 +DA:5,6 +DA:6,6 +DA:7,6 +DA:9,6 +DA:10,6 +DA:11,6 +DA:12,6 +DA:13,6 +DA:14,6 +DA:15,6 +DA:16,6 +DA:17,6 +DA:18,6 +DA:19,6 +DA:20,6 +DA:21,6 +DA:22,6 +DA:23,6 +DA:24,6 +DA:25,6 +DA:26,6 +DA:28,6 +DA:30,6570 +DA:31,6570 +DA:32,6570 +DA:33,1 +DA:34,6569 +DA:36,6569 +DA:38,6569 +DA:39,6569 +DA:40,6569 +DA:41,6569 +DA:42,6569 +DA:43,6569 +DA:44,6569 +DA:45,6569 +DA:46,6569 +DA:47,6569 +DA:49,6569 +DA:50,6515 +DA:52,6569 +DA:55,4 +DA:56,4 +DA:57,2 +DA:60,6567 +DA:61,6567 +DA:62,2 +DA:63,2 +DA:66,6567 +DA:68,6567 +DA:69,1 +DA:71,6567 +DA:72,6513 +DA:74,54 +DA:78,34 +DA:79,34 +DA:80,1 +DA:81,33 +DA:86,6566 +DA:87,6566 +DA:88,6566 +DA:89,902 +DA:90,6566 +DA:91,6566 +DA:92,6566 +DA:96,6566 +DA:97,5664 +DA:98,867 +DA:99,34 +DA:101,1 +DA:106,6563 +DA:107,4 +DA:109,6563 +DA:126,6563 +DA:127,17 +DA:141,6563 +DA:145,867 +DA:146,859 +DA:147,867 +DA:148,867 +DA:149,867 +DA:153,32 +DA:154,32 +DA:155,1 +DA:156,31 +DA:161,32 +DA:162,32 +DA:163,32 +DA:167,1 +DA:168,1 +DA:169,1 +DA:170,1 +DA:171,1 +DA:175,5664 +DA:176,7 +DA:177,7 +DA:178,2 +DA:179,2 +DA:180,1 +DA:182,6 +DA:185,5663 +DA:186,5663 +DA:187,42 +DA:189,5621 +DA:193,5568 +DA:194,5568 +DA:195,2 +DA:196,5566 +DA:201,5617 +DA:202,5617 +DA:203,5617 +DA:204,5617 +DA:208,7336 +DA:209,7336 +DA:210,1 +DA:211,7335 +DA:216,5566 +DA:220,7393 +DA:221,2 +DA:222,2 +DA:223,2 +DA:224,2 +DA:225,2 +DA:229,7392 +DA:230,5614 +DA:231,1700449 +DA:232,1700449 +DA:233,1700449 +DA:237,7392 +DA:239,7392 +DA:240,7392 +DA:241,7392 +DA:242,7392 +DA:244,7392 +DA:246,7392 +DA:247,5614 +DA:248,2 +DA:249,5614 +DA:250,5614 +DA:251,5614 +DA:254,1778 +DA:255,1754 +DA:256,1754 +DA:258,1778 +DA:259,1778 +DA:265,99 +DA:269,20 +DA:273,2 +DA:277,53 +DA:281,59 +DA:282,59 +DA:283,59 +DA:284,58 +DA:285,57 +DA:287,59 +DA:288,2 +DA:293,51 +DA:297,6 +DA:299,33 +DA:300,33 +DA:301,33 +DA:302,33 +DA:303,33 +DA:304,33 +DA:305,33 +DA:307,33 +DA:308,33 +DA:309,33 +DA:310,0 +DA:312,33 +DA:313,33 +DA:314,33 +DA:315,26 +DA:316,33 +DA:317,33 +DA:318,33 +DA:319,33 +DA:320,33 +DA:321,33 +DA:322,33 +DA:323,33 +DA:324,33 +DA:326,33 +DA:327,27 +DA:329,33 +DA:330,2 +DA:331,2 +DA:335,1 +DA:338,32 +DA:339,32 +DA:341,32 +DA:357,32 +DA:358,14 +DA:373,32 +DA:374,32 +DA:378,52 +DA:379,52 +DA:380,1 +DA:381,51 +DA:382,51 +DA:386,29 +DA:387,22 +DA:388,29 +DA:392,6 +DA:393,6 +DA:395,6 +DA:396,6566 +DA:401,6 +LF:211 +LH:210 +BRDA:30,0,0,6570 +BRDA:30,0,1,2 +BRDA:32,1,0,1 +BRDA:32,1,1,6569 +BRDA:38,2,0,6569 +BRDA:38,2,1,6569 +BRDA:39,3,0,6569 +BRDA:39,3,1,37 +BRDA:40,4,0,6569 +BRDA:40,4,1,6563 +BRDA:41,5,0,6569 +BRDA:41,5,1,53 +BRDA:42,6,0,6569 +BRDA:42,6,1,55 +BRDA:44,7,0,6569 +BRDA:44,7,1,4 +BRDA:49,8,0,6515 +BRDA:49,8,1,54 +BRDA:52,9,0,4 +BRDA:52,9,1,6565 +BRDA:52,10,0,6569 +BRDA:52,10,1,6564 +BRDA:60,11,0,6567 +BRDA:60,11,1,6565 +BRDA:61,12,0,2 +BRDA:61,12,1,6565 +BRDA:66,13,0,6567 +BRDA:66,13,1,54 +BRDA:68,14,0,1 +BRDA:68,14,1,6566 +BRDA:71,15,0,6513 +BRDA:71,15,1,54 +BRDA:79,16,0,1 +BRDA:79,16,1,33 +BRDA:88,17,0,902 +BRDA:88,17,1,5664 +BRDA:96,18,0,5664 +BRDA:96,18,1,867 +BRDA:96,18,2,34 +BRDA:96,18,3,1 +BRDA:106,19,0,4 +BRDA:106,19,1,6559 +BRDA:106,20,0,6563 +BRDA:106,20,1,867 +BRDA:115,21,0,10 +BRDA:115,21,1,6553 +BRDA:116,22,0,10 +BRDA:116,22,1,6553 +BRDA:118,23,0,6 +BRDA:118,23,1,6557 +BRDA:120,24,0,10 +BRDA:120,24,1,6553 +BRDA:121,25,0,6552 +BRDA:121,25,1,1 +BRDA:122,26,0,10 +BRDA:122,26,1,6553 +BRDA:123,27,0,10 +BRDA:123,27,1,6553 +BRDA:126,28,0,17 +BRDA:126,28,1,6546 +BRDA:126,29,0,6563 +BRDA:126,29,1,18 +BRDA:128,30,0,4 +BRDA:128,30,1,13 +BRDA:129,31,0,4 +BRDA:129,31,1,13 +BRDA:130,32,0,4 +BRDA:130,32,1,13 +BRDA:131,33,0,2 +BRDA:131,33,1,15 +BRDA:135,34,0,4 +BRDA:135,34,1,13 +BRDA:136,35,0,4 +BRDA:136,35,1,13 +BRDA:137,36,0,4 +BRDA:137,36,1,13 +BRDA:138,37,0,4 +BRDA:138,37,1,13 +BRDA:139,38,0,4 +BRDA:139,38,1,13 +BRDA:145,39,0,859 +BRDA:145,39,1,8 +BRDA:154,40,0,1 +BRDA:154,40,1,31 +BRDA:175,41,0,7 +BRDA:175,41,1,5657 +BRDA:177,42,0,2 +BRDA:177,42,1,5 +BRDA:179,43,0,1 +BRDA:179,43,1,1 +BRDA:186,44,0,42 +BRDA:186,44,1,5621 +BRDA:194,45,0,2 +BRDA:194,45,1,5566 +BRDA:209,46,0,1 +BRDA:209,46,1,7335 +BRDA:220,47,0,2 +BRDA:220,47,1,7391 +BRDA:220,48,0,7393 +BRDA:220,48,1,2 +BRDA:229,49,0,5614 +BRDA:229,49,1,1778 +BRDA:230,50,0,1706063 +BRDA:230,50,1,1700456 +BRDA:237,51,0,7338 +BRDA:237,51,1,54 +BRDA:237,52,0,7392 +BRDA:237,52,1,7369 +BRDA:246,53,0,5614 +BRDA:246,53,1,1778 +BRDA:247,54,0,2 +BRDA:247,54,1,5612 +BRDA:254,55,0,1754 +BRDA:254,55,1,24 +BRDA:287,56,0,2 +BRDA:287,56,1,57 +BRDA:299,57,0,33 +BRDA:299,57,1,4 +BRDA:309,58,0,0 +BRDA:309,58,1,33 +BRDA:309,59,0,33 +BRDA:309,59,1,2 +BRDA:314,60,0,26 +BRDA:314,60,1,7 +BRDA:316,61,0,1 +BRDA:316,61,1,32 +BRDA:317,62,0,1 +BRDA:317,62,1,32 +BRDA:318,63,0,1 +BRDA:318,63,1,32 +BRDA:319,64,0,1 +BRDA:319,64,1,32 +BRDA:321,65,0,0 +BRDA:321,65,1,33 +BRDA:322,66,0,1 +BRDA:322,66,1,32 +BRDA:323,67,0,1 +BRDA:323,67,1,32 +BRDA:326,68,0,27 +BRDA:326,68,1,6 +BRDA:329,69,0,2 +BRDA:329,69,1,31 +BRDA:329,70,0,33 +BRDA:329,70,1,3 +BRDA:347,71,0,1 +BRDA:347,71,1,31 +BRDA:348,72,0,1 +BRDA:348,72,1,31 +BRDA:350,73,0,0 +BRDA:350,73,1,32 +BRDA:352,74,0,1 +BRDA:352,74,1,31 +BRDA:353,75,0,1 +BRDA:353,75,1,31 +BRDA:354,76,0,1 +BRDA:354,76,1,31 +BRDA:357,77,0,14 +BRDA:357,77,1,18 +BRDA:357,78,0,32 +BRDA:357,78,1,14 +BRDA:359,79,0,1 +BRDA:359,79,1,13 +BRDA:360,80,0,1 +BRDA:360,80,1,13 +BRDA:361,81,0,1 +BRDA:361,81,1,13 +BRDA:362,82,0,0 +BRDA:362,82,1,14 +BRDA:366,83,0,1 +BRDA:366,83,1,13 +BRDA:367,84,0,1 +BRDA:367,84,1,13 +BRDA:368,85,0,1 +BRDA:368,85,1,13 +BRDA:369,86,0,1 +BRDA:369,86,1,13 +BRDA:370,87,0,1 +BRDA:370,87,1,13 +BRDA:379,88,0,1 +BRDA:379,88,1,51 +BRDA:386,89,0,22 +BRDA:386,89,1,7 +BRDA:396,90,0,5664 +BRDA:396,90,1,902 +BRDA:397,91,0,867 +BRDA:397,91,1,35 +BRDA:398,92,0,34 +BRDA:398,92,1,1 +BRF:188 +BRH:184 +end_of_record diff --git a/node_modules/node-gyp/node_modules/tar/examples/extracter.js b/node_modules/npm-lifecycle/node_modules/tar/examples/extracter.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/examples/extracter.js rename to node_modules/npm-lifecycle/node_modules/tar/examples/extracter.js diff --git a/node_modules/node-gyp/node_modules/tar/examples/packer.js b/node_modules/npm-lifecycle/node_modules/tar/examples/packer.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/examples/packer.js rename to node_modules/npm-lifecycle/node_modules/tar/examples/packer.js diff --git a/node_modules/node-gyp/node_modules/tar/examples/reader.js b/node_modules/npm-lifecycle/node_modules/tar/examples/reader.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/examples/reader.js rename to node_modules/npm-lifecycle/node_modules/tar/examples/reader.js diff --git a/node_modules/node-gyp/node_modules/tar/lib/buffer-entry.js b/node_modules/npm-lifecycle/node_modules/tar/lib/buffer-entry.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/lib/buffer-entry.js rename to node_modules/npm-lifecycle/node_modules/tar/lib/buffer-entry.js diff --git a/node_modules/node-gyp/node_modules/tar/lib/entry-writer.js b/node_modules/npm-lifecycle/node_modules/tar/lib/entry-writer.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/lib/entry-writer.js rename to node_modules/npm-lifecycle/node_modules/tar/lib/entry-writer.js diff --git a/node_modules/node-gyp/node_modules/tar/lib/entry.js b/node_modules/npm-lifecycle/node_modules/tar/lib/entry.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/lib/entry.js rename to node_modules/npm-lifecycle/node_modules/tar/lib/entry.js diff --git a/node_modules/node-gyp/node_modules/tar/lib/extended-header-writer.js b/node_modules/npm-lifecycle/node_modules/tar/lib/extended-header-writer.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/lib/extended-header-writer.js rename to node_modules/npm-lifecycle/node_modules/tar/lib/extended-header-writer.js diff --git a/node_modules/node-gyp/node_modules/tar/lib/extended-header.js b/node_modules/npm-lifecycle/node_modules/tar/lib/extended-header.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/lib/extended-header.js rename to node_modules/npm-lifecycle/node_modules/tar/lib/extended-header.js diff --git a/node_modules/node-gyp/node_modules/tar/lib/extract.js b/node_modules/npm-lifecycle/node_modules/tar/lib/extract.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/lib/extract.js rename to node_modules/npm-lifecycle/node_modules/tar/lib/extract.js diff --git a/node_modules/node-gyp/node_modules/tar/lib/global-header-writer.js b/node_modules/npm-lifecycle/node_modules/tar/lib/global-header-writer.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/lib/global-header-writer.js rename to node_modules/npm-lifecycle/node_modules/tar/lib/global-header-writer.js diff --git a/node_modules/node-gyp/node_modules/tar/lib/header.js b/node_modules/npm-lifecycle/node_modules/tar/lib/header.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/lib/header.js rename to node_modules/npm-lifecycle/node_modules/tar/lib/header.js diff --git a/node_modules/node-gyp/node_modules/tar/lib/pack.js b/node_modules/npm-lifecycle/node_modules/tar/lib/pack.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/lib/pack.js rename to node_modules/npm-lifecycle/node_modules/tar/lib/pack.js diff --git a/node_modules/node-gyp/node_modules/tar/lib/parse.js b/node_modules/npm-lifecycle/node_modules/tar/lib/parse.js similarity index 98% rename from node_modules/node-gyp/node_modules/tar/lib/parse.js rename to node_modules/npm-lifecycle/node_modules/tar/lib/parse.js index 600ad782f0f61..1c66ebdaf0c15 100644 --- a/node_modules/node-gyp/node_modules/tar/lib/parse.js +++ b/node_modules/npm-lifecycle/node_modules/tar/lib/parse.js @@ -38,6 +38,7 @@ function Parse () { me._stream = new BlockStream(512) me.position = 0 me._ended = false + me._hardLinks = {} me._stream.on("error", function (e) { me.emit("error", e) @@ -251,6 +252,11 @@ Parse.prototype._startEntry = function (c) { if (onend) entry.on("end", onend) this._entry = entry + + if (entry.type === "Link") { + this._hardLinks[entry.path] = entry + } + var me = this entry.on("pause", function () { diff --git a/node_modules/node-gyp/node_modules/tar/package.json b/node_modules/npm-lifecycle/node_modules/tar/package.json similarity index 68% rename from node_modules/node-gyp/node_modules/tar/package.json rename to node_modules/npm-lifecycle/node_modules/tar/package.json index 2ab77e47f328d..4a4dacaba5a5d 100644 --- a/node_modules/node-gyp/node_modules/tar/package.json +++ b/node_modules/npm-lifecycle/node_modules/tar/package.json @@ -1,9 +1,9 @@ { "_from": "tar@^2.0.0", - "_id": "tar@2.2.1", + "_id": "tar@2.2.2", "_inBundle": false, - "_integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "_location": "/node-gyp/tar", + "_integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "_location": "/npm-lifecycle/tar", "_phantomChildren": {}, "_requested": { "type": "range", @@ -16,12 +16,12 @@ "fetchSpec": "^2.0.0" }, "_requiredBy": [ - "/node-gyp" + "/npm-lifecycle/node-gyp" ], - "_resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "_shasum": "8e4d2a256c0e2185c6b18ad694aec968b83cb1d1", + "_resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "_shasum": "0ca8848562c7299b8b446ff6a4d60cdbb23edc40", "_spec": "tar@^2.0.0", - "_where": "/Users/rebecca/code/npm/node_modules/node-gyp", + "_where": "/home/hugh/Development/github.com/npm/cli/node_modules/npm-lifecycle/node_modules/node-gyp", "author": { "name": "Isaac Z. Schlueter", "email": "i@izs.me", @@ -33,7 +33,7 @@ "bundleDependencies": false, "dependencies": { "block-stream": "*", - "fstream": "^1.0.2", + "fstream": "^1.0.12", "inherits": "2" }, "deprecated": false, @@ -55,5 +55,5 @@ "scripts": { "test": "tap test/*.js" }, - "version": "2.2.1" + "version": "2.2.2" } diff --git a/node_modules/node-gyp/node_modules/tar/tar.js b/node_modules/npm-lifecycle/node_modules/tar/tar.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/tar.js rename to node_modules/npm-lifecycle/node_modules/tar/tar.js diff --git a/node_modules/node-gyp/node_modules/tar/test/00-setup-fixtures.js b/node_modules/npm-lifecycle/node_modules/tar/test/00-setup-fixtures.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/00-setup-fixtures.js rename to node_modules/npm-lifecycle/node_modules/tar/test/00-setup-fixtures.js diff --git a/node_modules/node-gyp/node_modules/tar/test/cb-never-called-1.0.1.tgz b/node_modules/npm-lifecycle/node_modules/tar/test/cb-never-called-1.0.1.tgz similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/cb-never-called-1.0.1.tgz rename to node_modules/npm-lifecycle/node_modules/tar/test/cb-never-called-1.0.1.tgz diff --git a/node_modules/node-gyp/node_modules/tar/test/dir-normalization.js b/node_modules/npm-lifecycle/node_modules/tar/test/dir-normalization.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/dir-normalization.js rename to node_modules/npm-lifecycle/node_modules/tar/test/dir-normalization.js diff --git a/node_modules/node-gyp/node_modules/tar/test/dir-normalization.tar b/node_modules/npm-lifecycle/node_modules/tar/test/dir-normalization.tar similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/dir-normalization.tar rename to node_modules/npm-lifecycle/node_modules/tar/test/dir-normalization.tar diff --git a/node_modules/node-gyp/node_modules/tar/test/error-on-broken.js b/node_modules/npm-lifecycle/node_modules/tar/test/error-on-broken.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/error-on-broken.js rename to node_modules/npm-lifecycle/node_modules/tar/test/error-on-broken.js diff --git a/node_modules/node-gyp/node_modules/tar/test/extract-move.js b/node_modules/npm-lifecycle/node_modules/tar/test/extract-move.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/extract-move.js rename to node_modules/npm-lifecycle/node_modules/tar/test/extract-move.js diff --git a/node_modules/node-gyp/node_modules/tar/test/extract.js b/node_modules/npm-lifecycle/node_modules/tar/test/extract.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/extract.js rename to node_modules/npm-lifecycle/node_modules/tar/test/extract.js diff --git a/node_modules/node-gyp/node_modules/tar/test/fixtures.tgz b/node_modules/npm-lifecycle/node_modules/tar/test/fixtures.tgz similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/fixtures.tgz rename to node_modules/npm-lifecycle/node_modules/tar/test/fixtures.tgz diff --git a/node_modules/node-gyp/node_modules/tar/test/header.js b/node_modules/npm-lifecycle/node_modules/tar/test/header.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/header.js rename to node_modules/npm-lifecycle/node_modules/tar/test/header.js diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision.js b/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision.js new file mode 100644 index 0000000000000..cb3e2d5e4edf8 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision.js @@ -0,0 +1,39 @@ +// Set the umask, so that it works the same everywhere. +process.umask(parseInt('22', 8)) + +var tap = require("tap") + , tar = require("../tar.js") + , fs = require("fs") + , path = require("path") + , file = path.resolve(__dirname, "link-file-entry-collision/bad-link.tar") + , target = path.resolve(__dirname, "tmp/link-file-entry-collision") + , index = 0 + , fstream = require("fstream") + , mkdirp = require("mkdirp") + , rimraf = require("rimraf") + +tap.test("preclean", function (t) { + rimraf.sync(target) + t.pass("cleaned!") + t.end() +}) + +tap.test("extract test", function (t) { + var extract = tar.Extract(target) + var inp = fs.createReadStream(file) + inp.pipe(extract) + + extract.on("end", function () { + t.equal(fs.readFileSync(target + "/bad-link-target", "utf8"), + "this should remain the same\n") + t.equal(fs.readFileSync(target + "/a.txt", "utf8"), + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + t.end() + }) +}) + +tap.test("cleanup", function (t) { + rimraf.sync(target) + t.pass("cleaned!") + t.end() +}) diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.hex b/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.hex new file mode 100644 index 0000000000000..99f5db0db0248 --- /dev/null +++ b/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.hex @@ -0,0 +1,25 @@ +-- header for the link target -- +6261642d6c696e6b2d74617267657400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030303037363520003030303032342000303030303030303030333420313334363636353530353620303134333731002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # bad-link-target.....................................................................................000644..000765..000024..00000000034.13466655056.014371..0................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- link target file contents (should not be overwritten) -- +746869732073686f756c642072656d61696e207468652073616d650a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # this.should.remain.the.same..................................................................................................................................................................................................................................... +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # ................................................................................................................................................................................................................................................................ + +-- header for the link named a.txt -- +612e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003030303634342000303030373635200030303030323420003030303030303030303030203133343636363535303536203031353334320020316261642d6c696e6b2d746172676574000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # a.txt...............................................................................................000644..000765..000024..00000000000.13466655056.015342..1bad-link-target.................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- header for file entry which attempts to overwrite the link -- +612e7478740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030353737363120003030303032342000303030303030303034303120313136353133363033333320303132343531002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # a.txt...............................................................................................000644..057761..000024..00000000401.11651360333.012451..0................................................................................................... +00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... + +-- contents that threaten to overwrite the link target -- +61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +61000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # a............................................................................................................................................................................................................................................................... + +-- tar eof -- +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # ................................................................................................................................................................................................................................................................ +00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # ................................................................................................................................................................................................................................................................ diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.tar b/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.tar new file mode 100644 index 0000000000000000000000000000000000000000..be0b0d2f73a2cdca26771554090aca269bfcfc69 GIT binary patch literal 3584 zcmeHH+X{m)4E1?mksoj*wvFFYr%stVuod?C3-dvyu%}f7o0r^5I638{uw~k{!z1-} zyjMO6VTj0DLn1zB^YNI?xs=3|22z@tjX}eJq*YD{UmvH zFX<+lH<_11giZgT1>dv|T=Sf|62_{x?Et>1z}ddK929bd^+yKm)xW~1egP@c_^p4@ z%eVfG(pdsj>~Ne;uK!*C-{d*d_Wo-mAYwy`Q7I+&Khq}O|3yFnBYSoW$ZZ@Q8Hfx- I29C_Y8xFy>h5!Hn literal 0 HcmV?d00001 diff --git a/node_modules/node-gyp/node_modules/tar/test/pack-no-proprietary.js b/node_modules/npm-lifecycle/node_modules/tar/test/pack-no-proprietary.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/pack-no-proprietary.js rename to node_modules/npm-lifecycle/node_modules/tar/test/pack-no-proprietary.js diff --git a/node_modules/node-gyp/node_modules/tar/test/pack.js b/node_modules/npm-lifecycle/node_modules/tar/test/pack.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/pack.js rename to node_modules/npm-lifecycle/node_modules/tar/test/pack.js diff --git a/node_modules/node-gyp/node_modules/tar/test/parse-discard.js b/node_modules/npm-lifecycle/node_modules/tar/test/parse-discard.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/parse-discard.js rename to node_modules/npm-lifecycle/node_modules/tar/test/parse-discard.js diff --git a/node_modules/node-gyp/node_modules/tar/test/parse.js b/node_modules/npm-lifecycle/node_modules/tar/test/parse.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/parse.js rename to node_modules/npm-lifecycle/node_modules/tar/test/parse.js diff --git a/node_modules/node-gyp/node_modules/tar/test/zz-cleanup.js b/node_modules/npm-lifecycle/node_modules/tar/test/zz-cleanup.js similarity index 100% rename from node_modules/node-gyp/node_modules/tar/test/zz-cleanup.js rename to node_modules/npm-lifecycle/node_modules/tar/test/zz-cleanup.js diff --git a/package-lock.json b/package-lock.json index 56b143db5ae6e..b10cf726fe9b2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2007,9 +2007,9 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "fstream": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.11.tgz", - "integrity": "sha1-XB+x8RdHcRTwYyoOtLcbPLD9MXE=", + "version": "1.0.12", + "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", + "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", "requires": { "graceful-fs": "^4.1.2", "inherits": "~2.0.0", @@ -3343,11 +3343,10 @@ } }, "node-gyp": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-4.0.0.tgz", + "integrity": "sha512-2XiryJ8sICNo6ej8d0idXDEMKfVfFK7kekGCtJAuelGsYHQxhj13KTf95swTCN2dZ/4lTfZ84Fu31jqJEEgjWA==", "requires": { - "fstream": "^1.0.0", "glob": "^7.0.3", "graceful-fs": "^4.1.2", "mkdirp": "^0.5.0", @@ -3357,7 +3356,7 @@ "request": "^2.87.0", "rimraf": "2", "semver": "~5.3.0", - "tar": "^2.0.0", + "tar": "^4.4.8", "which": "1" }, "dependencies": { @@ -3373,16 +3372,6 @@ "version": "5.3.0", "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" - }, - "tar": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.1.tgz", - "integrity": "sha1-jk0qJWwOIYXGsYrWlK7JaLg8sdE=", - "requires": { - "block-stream": "*", - "fstream": "^1.0.2", - "inherits": "2" - } } } }, @@ -3462,6 +3451,50 @@ "uid-number": "0.0.6", "umask": "^1.1.0", "which": "^1.3.1" + }, + "dependencies": { + "node-gyp": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", + "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", + "requires": { + "fstream": "^1.0.0", + "glob": "^7.0.3", + "graceful-fs": "^4.1.2", + "mkdirp": "^0.5.0", + "nopt": "2 || 3", + "npmlog": "0 || 1 || 2 || 3 || 4", + "osenv": "0", + "request": "^2.87.0", + "rimraf": "2", + "semver": "~5.3.0", + "tar": "^2.0.0", + "which": "1" + } + }, + "nopt": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", + "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", + "requires": { + "abbrev": "1" + } + }, + "semver": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", + "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" + }, + "tar": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", + "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", + "requires": { + "block-stream": "*", + "fstream": "^1.0.12", + "inherits": "2" + } + } } }, "npm-logical-tree": { diff --git a/package.json b/package.json index 24827e59cfd9a..5a097a1dae6be 100644 --- a/package.json +++ b/package.json @@ -88,7 +88,7 @@ "mississippi": "^3.0.0", "mkdirp": "~0.5.1", "move-concurrently": "^1.0.1", - "node-gyp": "^3.8.0", + "node-gyp": "^4.0.0", "nopt": "~4.0.1", "normalize-package-data": "^2.5.0", "npm-audit-report": "^1.3.2", diff --git a/test/npm_cache/_cacache/content-v2/sha1/07/07/8db5f6377f6321fceaaedf497de124dc9465 b/test/npm_cache/_cacache/content-v2/sha1/07/07/8db5f6377f6321fceaaedf497de124dc9465 new file mode 100644 index 0000000000000000000000000000000000000000..cbd0cddbacf6bdd26e109da2e5fd46d87188a6a2 GIT binary patch literal 4025 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 VKeosA*dE*6?H{y%ESUft001#v16%+A literal 0 HcmV?d00001 diff --git a/test/npm_cache/_cacache/content-v2/sha1/ee/56/8a2b1efaeb95bec4d9e59e5301fc63339866 b/test/npm_cache/_cacache/content-v2/sha1/ee/56/8a2b1efaeb95bec4d9e59e5301fc63339866 new file mode 100644 index 0000000000000000000000000000000000000000..c4b25ccf69b8931e2fb8a3aa529b60ae153928ff GIT binary patch literal 4733 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 Lihv|$0C)fZqI5hc literal 0 HcmV?d00001 diff --git a/test/npm_cache/_cacache/content-v2/sha512/0b/61/241d7c17bcbb1baee7094d14b7c451efecc7ffcbd92598a0f13d313cc9ebc2a07e61f007baf58fbf94ff9a8695bdd5cae7ce03bbf1e94e93613a00f25f21 b/test/npm_cache/_cacache/content-v2/sha512/0b/61/241d7c17bcbb1baee7094d14b7c451efecc7ffcbd92598a0f13d313cc9ebc2a07e61f007baf58fbf94ff9a8695bdd5cae7ce03bbf1e94e93613a00f25f21 new file mode 100644 index 0000000000000..945c9b46d684f --- /dev/null +++ b/test/npm_cache/_cacache/content-v2/sha512/0b/61/241d7c17bcbb1baee7094d14b7c451efecc7ffcbd92598a0f13d313cc9ebc2a07e61f007baf58fbf94ff9a8695bdd5cae7ce03bbf1e94e93613a00f25f21 @@ -0,0 +1 @@ +. \ No newline at end of file diff --git a/test/npm_cache/_cacache/content-v2/sha512/21/82/eac4f83e50f3b6aa8bea561c5dfebdc1d66941e2da785af406e045de56a0fc422034ca7fa2ab5fa99022c6b860203eb4853ce85f15f26b96c84b8d9e7320 b/test/npm_cache/_cacache/content-v2/sha512/21/82/eac4f83e50f3b6aa8bea561c5dfebdc1d66941e2da785af406e045de56a0fc422034ca7fa2ab5fa99022c6b860203eb4853ce85f15f26b96c84b8d9e7320 new file mode 100644 index 0000000000000..a568011ff72d0 --- /dev/null +++ b/test/npm_cache/_cacache/content-v2/sha512/21/82/eac4f83e50f3b6aa8bea561c5dfebdc1d66941e2da785af406e045de56a0fc422034ca7fa2ab5fa99022c6b860203eb4853ce85f15f26b96c84b8d9e7320 @@ -0,0 +1 @@ +{"versions":{"1.0.0":{"name":"inherits","version":"1.0.0","dependencies":{},"devDependencies":{},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"38e1975285bf1f7ba9c84da102bb12771322ac48","tarball":"https://registry.npmjs.org/inherits/-/inherits-1.0.0.tgz"},"engines":{"node":"*"}},"2.0.0":{"name":"inherits","version":"2.0.0","_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"76c81b3b1c10ddee3a60bf2c247162bc369f8ba8","tarball":"https://registry.npmjs.org/inherits/-/inherits-2.0.0.tgz"}},"2.0.1":{"name":"inherits","version":"2.0.1","_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"b17d08d326b4423e568eff719f91b0b1cbdf69f1","tarball":"https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz"}},"1.0.1":{"name":"inherits","version":"1.0.1","_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"1bdf16c6ff8266cb858c6da2baf3637a99fb3d87","tarball":"https://registry.npmjs.org/inherits/-/inherits-1.0.1.tgz"}},"1.0.2":{"name":"inherits","version":"1.0.2","_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b","tarball":"https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz"}},"2.0.3":{"name":"inherits","version":"2.0.3","devDependencies":{"tap":"^7.1.0"},"_hasShrinkwrap":false,"directories":{},"dist":{"shasum":"633c2c83e3da42a502f52466022480f4208261de","tarball":"https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz"}}},"name":"inherits","dist-tags":{"latest":"2.0.3"},"modified":"2018-08-03T00:38:03.803Z"} \ No newline at end of file diff --git a/test/npm_cache/_cacache/content-v2/sha512/2e/36/48f976830aeaba0724b382a09a6a6736dfd4c755963a4f462f963f9ecb211c2258f00766dc3aa68664f66d3a01cb2789b2cf614aeb292dbeb4afe0b206cc b/test/npm_cache/_cacache/content-v2/sha512/2e/36/48f976830aeaba0724b382a09a6a6736dfd4c755963a4f462f963f9ecb211c2258f00766dc3aa68664f66d3a01cb2789b2cf614aeb292dbeb4afe0b206cc new file mode 100644 index 0000000000000000000000000000000000000000..c4b25ccf69b8931e2fb8a3aa529b60ae153928ff GIT binary patch literal 4733 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 Lihv|$0C)fZqI5hc literal 0 HcmV?d00001 diff --git a/test/npm_cache/_cacache/content-v2/sha512/55/a3/cb2911b2e84215a5d93c85438bac8f76cdf605a4ebb8bcc45a615a178ec498e4006d8b05e7569d3dc46deb04a85cc226987f32f6abcea8d4427c3aad50eb b/test/npm_cache/_cacache/content-v2/sha512/55/a3/cb2911b2e84215a5d93c85438bac8f76cdf605a4ebb8bcc45a615a178ec498e4006d8b05e7569d3dc46deb04a85cc226987f32f6abcea8d4427c3aad50eb new file mode 100644 index 0000000000000000000000000000000000000000..4f4263f79774153f61a339702603d151eb9f7853 GIT binary patch literal 5787 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.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.1.4":{"name":"graceful-fs","version":"1.1.4","dependencies":{"fast-list":"1"},"optionalDependencies":{},"devDependencies":{},"directories":{},"dist":{"shasum":"d53940783394758e59b24e10d355cbcf8c225103","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.4.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.1.5":{"name":"graceful-fs","version":"1.1.5","dependencies":{"fast-list":"1"},"optionalDependencies":{},"devDependencies":{},"directories":{},"dist":{"shasum":"0e4692e2240d3951c135587ff7dc8c557186d037","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.5.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.1.6":{"name":"graceful-fs","version":"1.1.6","dependencies":{},"optionalDependencies":{},"devDependencies":{},"directories":{},"dist":{"shasum":"cb87fa245e5669fb7b1da44ceef5920054052e24","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.6.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.1.7":{"name":"graceful-fs","version":"1.1.7","dependencies":{},"optionalDependencies":{},"devDependencies":{},"directories":{},"dist":{"shasum":"e5cfd7904de546273c1c461ddd053e44e84bc0d7","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.7.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.1.8":{"name":"graceful-fs","version":"1.1.8","dependencies":{},"optionalDependencies":{},"devDependencies":{},"directories":{},"dist":{"shasum":"7c9b7cd96f16b83230f61d522156306500914888","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.8.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.1.9":{"name":"graceful-fs","version":"1.1.9","devDependencies":{},"directories":{},"dist":{"shasum":"2d8916e828b906a921d7e7de8fc2ba148f03b18a","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.9.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.1.10":{"name":"graceful-fs","version":"1.1.10","dependencies":{},"devDependencies":{},"directories":{"test":"test"},"dist":{"shasum":"388a63917e823bc695afd57c76d7f3ee3db54ad3","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.10.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.1.11":{"name":"graceful-fs","version":"1.1.11","dependencies":{},"devDependencies":{},"directories":{"test":"test"},"dist":{"shasum":"3a3de260cc4cc80ae13debf31b71f73c2c5eb5e5","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.11.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.1.12":{"name":"graceful-fs","version":"1.1.12","dependencies":{"mkdirp":"~0.3.4"},"devDependencies":{},"directories":{"test":"test"},"dist":{"shasum":"baff9d5d87b722ecef6615ea301a5cb9e2860038","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.12.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.1.13":{"name":"graceful-fs","version":"1.1.13","directories":{"test":"test"},"dist":{"shasum":"a91e1d8231dc083bdaa227983fbdf5010944ca14","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.13.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.1.14":{"name":"graceful-fs","version":"1.1.14","directories":{"test":"test"},"dist":{"shasum":"07078db5f6377f6321fceaaedf497de124dc9465","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.14.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.2.0":{"name":"graceful-fs","version":"1.2.0","directories":{"test":"test"},"dist":{"shasum":"fe2d82a295e30de4e1d1c04ec159e10061140704","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.0.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.2.1":{"name":"graceful-fs","version":"1.2.1","directories":{"test":"test"},"dist":{"shasum":"b35cc6e623576fc2a278cba12c00dda6a1758d2d","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.1.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.2.2":{"name":"graceful-fs","version":"1.2.2","directories":{"test":"test"},"dist":{"shasum":"2643e33eaed1c7277decd37377ff9fb394689cf5","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.2.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"1.2.3":{"name":"graceful-fs","version":"1.2.3","directories":{"test":"test"},"dist":{"shasum":"15a4806a57547cb2d2dbf27f42e89a8c3451b364","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.2.3.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"2.0.0":{"name":"graceful-fs","version":"2.0.0","directories":{"test":"test"},"dist":{"shasum":"c9a206f6f5f4b94e1046dfaaccfe9e12d0ab8cef","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.0.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"2.0.1":{"name":"graceful-fs","version":"2.0.1","directories":{"test":"test"},"dist":{"shasum":"7fd6e0a4837c35d0cc15330294d9584a3898cf84","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.1.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"2.0.2":{"name":"graceful-fs","version":"2.0.2","directories":{"test":"test"},"dist":{"shasum":"26806eaca4bff8fc5dbc935e696135792175c46f","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.2.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"2.0.3":{"name":"graceful-fs","version":"2.0.3","directories":{"test":"test"},"dist":{"shasum":"7cd2cdb228a4a3f36e95efa6cc142de7d1a136d0","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-2.0.3.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"3.0.0":{"name":"graceful-fs","version":"3.0.0","directories":{"test":"test"},"dist":{"shasum":"5792ffae0ed7e318060ebf9f6e7a6e6cf5139327","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.0.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"3.0.1":{"name":"graceful-fs","version":"3.0.1","directories":{"test":"test"},"dist":{"shasum":"93352b5b951b009ef541271204122b612e46edaf","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.1.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"3.0.2":{"name":"graceful-fs","version":"3.0.2","directories":{"test":"test"},"dist":{"shasum":"2cb5bf7f742bea8ad47c754caeee032b7e71a577","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.2.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"3.0.3":{"name":"graceful-fs","version":"3.0.3","directories":{"test":"test"},"dist":{"shasum":"277141085e739ae7d54361119a62797b08a1d8c0","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.3.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"3.0.4":{"name":"graceful-fs","version":"3.0.4","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^0.4.13"},"directories":{"test":"test"},"dist":{"shasum":"a0306d9b0940e0fc512d33b5df1014e88e0637a3","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.4.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"3.0.5":{"name":"graceful-fs","version":"3.0.5","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^0.4.13"},"directories":{"test":"test"},"dist":{"shasum":"4a880474bdeb716fe3278cf29792dec38dfac418","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.5.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"3.0.6":{"name":"graceful-fs","version":"3.0.6","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^0.4.13"},"directories":{"test":"test"},"dist":{"shasum":"dce3a18351cb94cdc82e688b2e3dd2842d1b09bb","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.6.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"3.0.7":{"name":"graceful-fs","version":"3.0.7","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^0.4.13"},"directories":{"test":"test"},"dist":{"shasum":"e935be4b3e57892d289dc3bef7be8c02779d2b54","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.7.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"3.0.8":{"name":"graceful-fs","version":"3.0.8","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^1.2.0"},"directories":{"test":"test"},"dist":{"shasum":"ce813e725fa82f7e6147d51c9a5ca68270551c22","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.8.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"4.1.0":{"name":"graceful-fs","version":"4.1.0","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^1.2.0"},"directories":{"test":"test"},"dist":{"shasum":"6be6119244f64d6417fe303cc36ab497b5756cc1","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.0.tgz"},"engines":{"node":">=0.4.0"}},"4.1.1":{"name":"graceful-fs","version":"4.1.1","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^1.2.0"},"directories":{"test":"test"},"dist":{"shasum":"db940cb46e47bd719314a876bace802ea3e90d3c","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.1.tgz"},"engines":{"node":">=0.4.0"}},"4.1.2":{"name":"graceful-fs","version":"4.1.2","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^1.2.0"},"directories":{"test":"test"},"dist":{"shasum":"fe2239b7574972e67e41f808823f9bfa4a991e37","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.2.tgz"},"engines":{"node":">=0.4.0"}},"4.1.3":{"name":"graceful-fs","version":"4.1.3","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^5.4.2"},"directories":{"test":"test"},"dist":{"shasum":"92033ce11113c41e2628d61fdfa40bc10dc0155c","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.3.tgz"},"engines":{"node":">=0.4.0"}},"4.1.4":{"name":"graceful-fs","version":"4.1.4","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^5.4.2"},"directories":{"test":"test"},"dist":{"shasum":"ef089d2880f033b011823ce5c8fae798da775dbd","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.4.tgz"},"engines":{"node":">=0.4.0"}},"4.1.5":{"name":"graceful-fs","version":"4.1.5","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^5.4.2"},"directories":{"test":"test"},"dist":{"shasum":"f4745e8caed5e0dd2ef21bb5e2d229a32e8093c0","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.5.tgz"},"engines":{"node":">=0.4.0"}},"3.0.9":{"name":"graceful-fs","version":"3.0.9","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^1.2.0"},"directories":{"test":"test"},"dist":{"shasum":"44e10a870a068e892485bace909520905b08ba24","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.9.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"4.1.6":{"name":"graceful-fs","version":"4.1.6","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^5.4.2"},"directories":{"test":"test"},"dist":{"shasum":"514c38772b31bee2e08bedc21a0aeb3abf54c19e","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.6.tgz"},"engines":{"node":">=0.4.0"}},"3.0.10":{"name":"graceful-fs","version":"3.0.10","dependencies":{"natives":"^1.0.1"},"devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^1.2.0"},"directories":{"test":"test"},"dist":{"shasum":"5268b37746ff73a549708f3ce47fb54c84d5b0f0","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.10.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"3.0.11":{"name":"graceful-fs","version":"3.0.11","dependencies":{"natives":"^1.1.0"},"devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^1.2.0"},"directories":{"test":"test"},"dist":{"shasum":"7613c778a1afea62f25c630a086d7f3acbbdd818","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-3.0.11.tgz"},"engines":{"node":">=0.4.0"},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js"},"4.1.7":{"name":"graceful-fs","version":"4.1.7","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^5.4.2"},"directories":{"test":"test"},"dist":{"shasum":"f8b39fe797b022ae88024cff94a3613197141f32","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.7.tgz"},"engines":{"node":">=0.4.0"}},"4.1.8":{"name":"graceful-fs","version":"4.1.8","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^5.4.2"},"directories":{"test":"test"},"dist":{"shasum":"da3e11135eb2168bdd374532c4e2649751672890","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.8.tgz"},"engines":{"node":">=0.4.0"}},"4.1.9":{"name":"graceful-fs","version":"4.1.9","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^5.4.2"},"directories":{"test":"test"},"dist":{"shasum":"baacba37d19d11f9d146d3578bc99958c3787e29","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.9.tgz"},"engines":{"node":">=0.4.0"}},"4.1.10":{"name":"graceful-fs","version":"4.1.10","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^5.4.2"},"directories":{"test":"test"},"dist":{"shasum":"f2d720c22092f743228775c75e3612632501f131","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.10.tgz"},"engines":{"node":">=0.4.0"}},"4.1.11":{"name":"graceful-fs","version":"4.1.11","devDependencies":{"mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^5.4.2"},"directories":{"test":"test"},"dist":{"shasum":"0e8bdfe4d1ddb8854d64e04ea7c00e2a026e5658","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz"},"engines":{"node":">=0.4.0"}},"4.1.12":{"name":"graceful-fs","version":"4.1.12","devDependencies":{"import-fresh":"^2.0.0","mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^12.0.1"},"_hasShrinkwrap":false,"directories":{"test":"test"},"dist":{"integrity":"sha512-E1kqZR391RPU4xZ4uJSKm42R1ZsN8qcolVVlMKDZ1yGa0HVRcNwhjJ74VGDTriDcOHa/LNzFCDHAOx/jq4F63A==","shasum":"5f732cae9d5023c66371362e72685e9c6cd42326","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.12.tgz","fileCount":6,"unpackedSize":25559,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb3LkMCRA9TVsSAnZWagAAizkP/3ROSu1bgKvgHuJ3BP7Q\nFA6TmxzkoAH9K55guUge0xxR7SCZI5YxiwImggAmklVXopSQXLl/jo7EfOpR\nHqyiUwIVnDlBKn9AB7CWRgPkIZRH4rGuu0JMiRqCHXdXboDUKn4qONTfI6mj\nfcAoVpAXpwumAP7LJD2olEnHE1j2fUca8RIaJlAAqw8LSiZd5Hdn/+JpLlp2\nK/9kM54BpPL9xM+IfaM07O59+6/TaNL1OcUb06wa1Qj0MP9jMqQPjrOxSOmQ\noKvOu2Vg6jsRTUkaIMRgsWO9puzhz74LLHe+DzBKqa8wVX97EEDd4Pldxeyx\n8UUzmLqQlSmdiNCY6dkR1F7yOQnbWMT3FBp9+tqlW6/IAA1vLnIwbofj1jJX\nBY0F8wi632qdE2gNti8puFqu79JedDLa/FQKyWppJ1pcLSOCrZK7dd6mGipr\nSmsQZPTXFOJuX9BJxH4sFnps/5hU47dpcnVPcPnTQneifVG1FN7l0Wqd+kpj\nxxbnOAnIZ+0q4L/Ppat1ks7c9R2OrknZM7+Ye8wAMT6VCgUkfxOjFWS11wad\nZ3iAZc6o2WZ1N4FJCsWchMXhceeevDhBhgCuGoOedYFXNKcfa3jPeR7oWRTV\no2/A9bryp6dmYYw+rpKi60xhqV/9Islf0bSfR028kfRBuIpohIGNkxhQqQtT\nic6a\r\n=7wOy\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":">=6"}},"4.1.13":{"name":"graceful-fs","version":"4.1.13","devDependencies":{"import-fresh":"^2.0.0","mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^12.0.1"},"_hasShrinkwrap":false,"directories":{"test":"test"},"dist":{"integrity":"sha512-a3u3Sck0c7/X622CIqiU0q/eRmhEOssVa3jkrfRRxxHPzaW1EcZgsQt87zKipdteGmFEKGGBvIBPr13pCB2HYw==","shasum":"9291d55cf899209ec0c2c8445d0ff7f6cc0e2df1","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.13.tgz","fileCount":7,"unpackedSize":25976,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb3MFwCRA9TVsSAnZWagAAivkP/AlHtY1y8mmXNgKdLPov\n0ULfG8zMLkNfnKx437uFEHjcyjClOFrrV2nOuQnNBR/HYvWp6kSRoRJMX6eB\nzPhPN7bsR2SZGdIqOKwkoweDyFjrA/BPMaHLYPeoY+OkMZ8SdHcOQ4EelvWM\nmRtXMGjB+6W1KOsBjFxqvRKi7eMmkaJf6tyFRsEhju1RUGmhw1VY+F9fS67s\nbn/DCTujUAHxMhzvmcsBscoiI7WN6q/vP1W8cRHSKe+5INPwISp/M4bo+gU3\ng7XwafgK9bMHgSsC2a7sE0i6zPzlre55bEAvDemE7WsORGagrM2AHJw5Ow1n\nnGulaYd5rit5f2++DPGQ50FaGJtlEFqOqS+J1XldGB69KSvKIqjgyqmoG4VH\nBLv9DflSyO5kJJZggtXKMqqwf/GlXCRij4s5sZVyVqUQ8VK1N95MCF+IWm51\nvyVlyg+ZgnuT8LEiDyxDMx27KbwwxUcN3QPLXvp5zuvDsqlePVMg9AzmsF01\niB6tX/ZddeMF2yTbOV8FRZ7bD23jqbWfSapilKNZBgvLpi2ah3Li9suu1B8v\nz2t/oAU6aqC8PQ1D59Eq8t0eq4wYlKWpIHL24Z/Fj+LUdHw/GnpUy60Tu0GW\npwCoqmZVmP9K9THjahagpXKWxsYaewHr+MhBca+DJ9vjCHv40MrOmgauB7g6\nwCoN\r\n=t9Oq\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":">=6"}},"4.1.14":{"name":"graceful-fs","version":"4.1.14","devDependencies":{"import-fresh":"^2.0.0","mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^12.0.1"},"_hasShrinkwrap":false,"directories":{"test":"test"},"dist":{"integrity":"sha512-ns/IGcSmmGNPP085JCheg0Nombh1QPvSCnlx+2V+byQWRQEIL4ZB5jXJMNIHOFVS1roi85HIi5Ka0h43iWXfcQ==","shasum":"1b6e8362ef8c5ecb5da799901f39297e3054773a","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.14.tgz","fileCount":7,"unpackedSize":25976,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb3NtKCRA9TVsSAnZWagAAn50P/R41gvttUFl7OysdDnVH\nTUFoUzk5WrVSQMO76cf8gQZ46xC4du+1BQhDFJ3gYvpmv57+6MDsgh2IFfCl\ntm0KsuBFnP9C3z8I47YdIqlMoUG+paoIRPrk0YIlqZddnaaf/BRO/9yr1Hb/\nm0mA4puWt+ceJh+pdSu3UzPFNoSSXr/+ViuVQiDVcxFOHHrWCxyXBrRLFc+8\nVTAinVmUEGLi9CkjlwIz99QbjizBd7INzRGCvCFm17XQlRHeT7e3EtRO2ySM\nvOU7o0K02vrP1XWtW7rXvGDATVJnTACM1yPZIhIXdZVxgD5zAEsTjqvvOAYJ\nfY3vqkHE1uoDTbf3mdT24ZmmaMRrOcOwmUPTa5ZxnIqAwOInOeVSwLUMIN+z\nqK+A4nL98U5L568OxpHlbAtbAgIHCPYADg+fT+8Xj7mIGtx/HBN+75h1WHaq\naGVvkK2kclgXFKXzHzCKfDlHe268rvqoRy+6Q9a1d5Cth1aArO6kTNajc4AX\nfco+TDCEg/oMDgCikHI4qL6zXwQ6aQiJjeuHONprnyrwrRhS9iCFD1DSC37Q\nsglCxNioVpd7TlfDg0v3yDFr8gZqo7a2ELoRmog3rwzgGYZ/VA/FJO/ztfE4\nkPH4rW2tbDldWc8bZ3FkH2TFHgwEw2qTgziPSFwE+V7G0GaDrbFjHslABMaP\nvlOn\r\n=G/Sv\r\n-----END PGP SIGNATURE-----\r\n"},"engines":{"node":">=6"}},"4.1.15":{"name":"graceful-fs","version":"4.1.15","devDependencies":{"import-fresh":"^2.0.0","mkdirp":"^0.5.0","rimraf":"^2.2.8","tap":"^12.0.1"},"_hasShrinkwrap":false,"directories":{"test":"test"},"dist":{"integrity":"sha512-6uHUhOPEBgQ24HM+r6b/QwWfZq+yiFcipKFrOFiBEnWdy5sdzYoi+pJeQaPI5qOLRFqWmAXUPQNsielzdLoecA==","shasum":"ffb703e1066e8a0eeaa4c8b80ba9253eeefbfb00","tarball":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.15.tgz","fileCount":7,"unpackedSize":25938,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb31vrCRA9TVsSAnZWagAAjMYP/2AwGCPcxbX+2ZBkpyRq\nJ85zkTLDdO2AhSNpgApHrPFbvQ2MYSedMmA/tuNOILCd2zulEvadRZLSW5zI\nHUkRFdU20ByFJoLMvoGm8EY9gEnQ3lpIvh6lmgNSYhQhm5khE0XHQ4sAs9YW\nV61Qr4yqKvkxXrMpElTgzkCfEZ79pNzZ58lE0Qvqmcp3OTczsOimh+w5UIUu\nt/GMZpsmLC4VHTj+hSRqYsh8HJFt9Nl2ahXK08eGAroZMRgRY5hA/9aJ2bA7\nHpuyqMH2wjbaJRnT8ORLfgfJ9a8xO+VzIp0ueAWpAjAaCtbC2dKF3/YJ8Bn6\nZUaCWMM1PZG1BIM/4g/q++OV7o9NgJvqjvjMmVZKanzUMBwfD9ygwFcP8oNF\nlLSR4GU6itDJo2oqdtsrTsfDe35sNTl3kwyhMqZPWFlNJ5C02jmeH2qPtc9s\n69lGDH5JNBBKOmJXV9WKfN+mOSXniBnUsUVu0vAm/y9nY1GZQiAlI5MfIW+T\n1a+K2cGakv6c+b2bO6ExwnIjWPwEpKNlPYHdjLv01GoT9qZRh2guD5RBJqDj\nbNToHu3zR6po45ekShHykoFDz3F+mOKWKyfQ1F3Z+z+8udFk7xbO4vxRTC4M\nq1HSgomC6uFS+RRNVhmTS2L4S1izPDbozKOUU+rpk4hQMBhTLgf7nQ0Bates\nG+db\r\n=Fpd7\r\n-----END PGP SIGNATURE-----\r\n"}}},"name":"graceful-fs","dist-tags":{"latest":"4.1.15","old":"3.0.11"},"modified":"2019-01-04T00:30:40.023Z"} \ No newline at end of file diff --git a/test/npm_cache/_cacache/content-v2/sha512/d0/9a/edf7b49ad59ad630957608c01609c61ecc2eb3ce20ef7f9020ae8673aa278352399dbfdb23a742d07556e1333ed74cd0f33fd00f401aa912a07a2a138d41 b/test/npm_cache/_cacache/content-v2/sha512/d0/9a/edf7b49ad59ad630957608c01609c61ecc2eb3ce20ef7f9020ae8673aa278352399dbfdb23a742d07556e1333ed74cd0f33fd00f401aa912a07a2a138d41 new file mode 100644 index 0000000000000000000000000000000000000000..768c8e7f3eaf3acfacc55922d2accae7da0e9b4d GIT binary patch literal 15106 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 literal 0 HcmV?d00001 diff --git a/test/npm_cache/_cacache/index-v5/21/90/97d7c2a8081808dcd3d6fc97011bebe11fc8e308eaff2d4224c21477d1d5 b/test/npm_cache/_cacache/index-v5/21/90/97d7c2a8081808dcd3d6fc97011bebe11fc8e308eaff2d4224c21477d1d5 new file mode 100644 index 0000000000000..df676f6b2624b --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/21/90/97d7c2a8081808dcd3d6fc97011bebe11fc8e308eaff2d4224c21477d1d5 @@ -0,0 +1,2 @@ + +569a467363ea14fb1fd9b5424f767d9d07663d53 {"key":"pacote:remote-manifest:https://github.com/substack/jsonify/tarball/master:sha512-LjZI+XaDCuq6BySzgqCaamc239THVZY6T0Yvlj+eyyEcIljwB2bcOqaGZPZtOgHLJ4myz2FK6yktvrSv4LIGzA==","integrity":"sha512-C2EkHXwXvLsbrucJTRS3xFHv7Mf/y9klmKDxPTE8yevCoH5h8Ae69Y+/lP+ahpW91crnzgO78elOk2E6APJfIQ==","time":1558529593696,"size":1,"metadata":{"id":"jsonify@0.0.0","manifest":{"name":"jsonify","version":"0.0.0","dependencies":{},"optionalDependencies":{},"devDependencies":{"tap":"0.4.x","garbage":"0.0.x"},"bundleDependencies":false,"peerDependencies":{},"deprecated":false,"_resolved":"https://github.com/substack/jsonify/tarball/master","_integrity":"sha512-LjZI+XaDCuq6BySzgqCaamc239THVZY6T0Yvlj+eyyEcIljwB2bcOqaGZPZtOgHLJ4myz2FK6yktvrSv4LIGzA==","_shasum":"ee568a2b1efaeb95bec4d9e59e5301fc63339866","_shrinkwrap":null,"bin":null,"_id":"jsonify@0.0.0"},"type":"finalized-manifest"}} \ No newline at end of file diff --git a/test/npm_cache/_cacache/index-v5/2d/22/47328dfeb3a9f00c15c20ec3ebdaa0e12382c5c6badfa30fb7b376f6a580 b/test/npm_cache/_cacache/index-v5/2d/22/47328dfeb3a9f00c15c20ec3ebdaa0e12382c5c6badfa30fb7b376f6a580 new file mode 100644 index 0000000000000..4fae405743b36 --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/2d/22/47328dfeb3a9f00c15c20ec3ebdaa0e12382c5c6badfa30fb7b376f6a580 @@ -0,0 +1,2 @@ + +6663f8d0b13fd1a2e2a0e4f5e13f0fcd1e1f0461 {"key":"pacote:packed-dir:git://github.com/isaacs/node-glob.git#67bda227fd7a559cca5620307c7d30a6732a792f","integrity":"sha512-0ex7++A20onXBeFvfsBbgcCaQy5F4Xd3PwkY5az4/YigslWeNcGCnODLDBHuYx4VAX7sv2dAG0aCWdUveQ0SSQ==","time":1558529588624,"size":27637} \ No newline at end of file diff --git a/test/npm_cache/_cacache/index-v5/61/41/453946604fdfa210a19eb38d07610e8ad7007ffc3f0f3b25da20b9af281d b/test/npm_cache/_cacache/index-v5/61/41/453946604fdfa210a19eb38d07610e8ad7007ffc3f0f3b25da20b9af281d new file mode 100644 index 0000000000000..ff0918f962f91 --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/61/41/453946604fdfa210a19eb38d07610e8ad7007ffc3f0f3b25da20b9af281d @@ -0,0 +1,2 @@ + +d2218a1a24882f856cd6f4d0cd23c52f72843469 {"key":"pacote:git-manifest:git://github.com/isaacs/node-glob.git#67bda227fd7a559cca5620307c7d30a6732a792f","integrity":"sha512-C2EkHXwXvLsbrucJTRS3xFHv7Mf/y9klmKDxPTE8yevCoH5h8Ae69Y+/lP+ahpW91crnzgO78elOk2E6APJfIQ==","time":1558529588625,"size":1,"metadata":{"id":"glob@3.1.5","manifest":{"name":"glob","version":"3.1.5","engines":{"node":"*"},"dependencies":{"minimatch":"0.2","graceful-fs":"~1.1.2","inherits":"1"},"optionalDependencies":{},"devDependencies":{"tap":"~0.2.3","mkdirp":"0","rimraf":"1"},"bundleDependencies":["minimatch"],"peerDependencies":{},"deprecated":false,"_resolved":"git://github.com/isaacs/node-glob.git#67bda227fd7a559cca5620307c7d30a6732a792f","_integrity":null,"_shasum":null,"_shrinkwrap":null,"bin":null,"_id":"glob@3.1.5"},"type":"finalized-manifest"}} \ No newline at end of file diff --git a/test/npm_cache/_cacache/index-v5/89/eb/a7a81ab3eeec3076546f7e1fce3892c4e717a9379d4ad43a7111b5dc8cc2 b/test/npm_cache/_cacache/index-v5/89/eb/a7a81ab3eeec3076546f7e1fce3892c4e717a9379d4ad43a7111b5dc8cc2 new file mode 100644 index 0000000000000..0faef62b0394b --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/89/eb/a7a81ab3eeec3076546f7e1fce3892c4e717a9379d4ad43a7111b5dc8cc2 @@ -0,0 +1,3 @@ + +fc74cc9783de108ec5c5ca86fb213eee9839ecfe {"key":"pacote:packed-dir:git://github.com/isaacs/canonical-host.git#7d5ad6eda4ca2948f890b1d8169bc1029bf62364","integrity":"sha512-VaPLKRGy6EIVpdk8hUOLrI92zfYFpOu4vMRaYVoXjsSY5ABtiwXnVp09xG3rBKhcwiaYfzL2q86o1EJ8Oq1Q6w==","time":1558529601371,"size":5787} +eccf825fcc77ecdf849302306d405840f4f3ff56 {"key":"pacote:packed-dir:git://github.com/isaacs/canonical-host.git#7d5ad6eda4ca2948f890b1d8169bc1029bf62364","integrity":"sha512-VaPLKRGy6EIVpdk8hUOLrI92zfYFpOu4vMRaYVoXjsSY5ABtiwXnVp09xG3rBKhcwiaYfzL2q86o1EJ8Oq1Q6w==","time":1558529608331,"size":5787} \ No newline at end of file diff --git a/test/npm_cache/_cacache/index-v5/93/4e/425c049345ed549becd9e42f3ca7ad942331f73dd73c3e6f5549e910679b b/test/npm_cache/_cacache/index-v5/93/4e/425c049345ed549becd9e42f3ca7ad942331f73dd73c3e6f5549e910679b new file mode 100644 index 0000000000000..fa10329dcc330 --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/93/4e/425c049345ed549becd9e42f3ca7ad942331f73dd73c3e6f5549e910679b @@ -0,0 +1,3 @@ + +9f8f343084f44b0596c2aa860b25533c760e5163 {"key":"make-fetch-happen:request-cache:https://codeload.github.com/substack/jsonify/legacy.tar.gz/master","integrity":"sha1-7laKKx7665W+xNnlnlMB/GMzmGY=","time":1558529593688,"size":4733,"metadata":{"url":"https://codeload.github.com/substack/jsonify/legacy.tar.gz/master","reqHeaders":{"connection":["keep-alive"],"user-agent":["npm/6.9.0 node/v12.2.0 linux x64"],"npm-in-ci":["false"],"npm-scope":[""],"npm-session":["fb2662bf39cf2a91"],"pacote-pkg-id":["registry:undefined@https://github.com/substack/jsonify/tarball/master"],"pacote-req-type":["tarball"],"referer":["install [REDACTED]"]},"resHeaders":{"transfer-encoding":["chunked"],"access-control-allow-origin":["https://render.githubusercontent.com"],"content-security-policy":["default-src 'none'; style-src 'unsafe-inline'; sandbox"],"strict-transport-security":["max-age=31536000"],"vary":["Authorization,Accept-Encoding"],"x-content-type-options":["nosniff"],"x-frame-options":["deny"],"x-xss-protection":["1; mode=block"],"etag":["\"7064ab53e5f73fa31e2ce7aa47d210c539662f16\""],"content-type":["application/x-gzip"],"content-disposition":["attachment; filename=substack-jsonify-7064ab5.tar.gz"],"x-geo-block-list":[""],"date":["Wed, 22 May 2019 12:53:13 GMT"],"x-github-request-id":["A8EE:59B6:88D23:11445B:5CE54639"],"x-fetch-attempts":["1"]}}} +d7bd9b0771d618ad4327d5dd0db3944cb5454653 {"key":"make-fetch-happen:request-cache:https://codeload.github.com/substack/jsonify/legacy.tar.gz/master","integrity":"sha512-LjZI+XaDCuq6BySzgqCaamc239THVZY6T0Yvlj+eyyEcIljwB2bcOqaGZPZtOgHLJ4myz2FK6yktvrSv4LIGzA==","time":1558529611135,"size":4733,"metadata":{"url":"https://codeload.github.com/substack/jsonify/legacy.tar.gz/master","reqHeaders":{"connection":["keep-alive"],"user-agent":["npm/6.9.0 node/v12.2.0 linux x64"],"npm-in-ci":["false"],"npm-scope":[""],"npm-session":["fb2662bf39cf2a91"],"pacote-pkg-id":["registry:undefined@https://github.com/substack/jsonify/tarball/master"],"pacote-req-type":["tarball"],"referer":["install [REDACTED]"]},"resHeaders":{"transfer-encoding":["chunked"],"access-control-allow-origin":["https://render.githubusercontent.com"],"content-security-policy":["default-src 'none'; style-src 'unsafe-inline'; sandbox"],"strict-transport-security":["max-age=31536000"],"vary":["Authorization,Accept-Encoding"],"x-content-type-options":["nosniff"],"x-frame-options":["deny"],"x-xss-protection":["1; mode=block"],"etag":["\"7064ab53e5f73fa31e2ce7aa47d210c539662f16\""],"content-type":["application/x-gzip"],"content-disposition":["attachment; filename=substack-jsonify-7064ab5.tar.gz"],"x-geo-block-list":[""],"date":["Wed, 22 May 2019 12:53:31 GMT"],"x-github-request-id":["A8F6:5062:21CFCE:3FC7B9:5CE5464B"],"x-fetch-attempts":["1"]}}} \ No newline at end of file diff --git a/test/npm_cache/_cacache/index-v5/9b/03/54636aae9cb55a079d1cc7f9caf4f3e654df7abd1fc8279dde9f935c76aa b/test/npm_cache/_cacache/index-v5/9b/03/54636aae9cb55a079d1cc7f9caf4f3e654df7abd1fc8279dde9f935c76aa new file mode 100644 index 0000000000000..0b8aac624854f --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/9b/03/54636aae9cb55a079d1cc7f9caf4f3e654df7abd1fc8279dde9f935c76aa @@ -0,0 +1,2 @@ + +90e7fd72e02b0d88a201adf21dee3a1c11bb1e7e {"key":"make-fetch-happen:request-cache:http://localhost:1337/-/whoami","integrity":"sha512-ffpdvFaxF0A84UCiK1atrQsMrxXM3FJJvKA2Cr3C+rOBAJA6beVPP4WXdGEzcy1kWQZqRsXPfIO7Xu0IyAYZcw==","time":1558529624275,"size":21,"metadata":{"url":"http://localhost:1337/-/whoami","reqHeaders":{"connection":["keep-alive"],"user-agent":["npm/6.9.0 node/v12.2.0 linux x64"],"npm-in-ci":["false"],"npm-scope":[""],"npm-session":["7c3c1fd40ca86e8f"],"referer":["whoami"],"authorization":["Bearer wombat-developers-union"]},"resHeaders":{"content-type":["application/json"],"date":["Wed, 22 May 2019 12:53:44 GMT"],"connection":["keep-alive"],"transfer-encoding":["chunked"],"x-fetch-attempts":["1"]}}} \ No newline at end of file diff --git a/test/npm_cache/_cacache/index-v5/b7/1c/f06201305985169fc251111ddb9fa636ef144ff9fad15784c1e9620b0dac b/test/npm_cache/_cacache/index-v5/b7/1c/f06201305985169fc251111ddb9fa636ef144ff9fad15784c1e9620b0dac new file mode 100644 index 0000000000000..d12fafc8da182 --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/b7/1c/f06201305985169fc251111ddb9fa636ef144ff9fad15784c1e9620b0dac @@ -0,0 +1,2 @@ + +88e96e8746d41fe6775255d98c6834a09fcf2136 {"key":"pacote:range-manifest:https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz:sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=","integrity":"sha512-C2EkHXwXvLsbrucJTRS3xFHv7Mf/y9klmKDxPTE8yevCoH5h8Ae69Y+/lP+ahpW91crnzgO78elOk2E6APJfIQ==","time":1558529589471,"size":1,"metadata":{"id":"inherits@1.0.2","manifest":{"name":"inherits","version":"1.0.2","dependencies":{},"optionalDependencies":{},"devDependencies":{},"bundleDependencies":false,"peerDependencies":{},"deprecated":false,"_resolved":"https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz","_integrity":"sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=","_shasum":"ca4309dadee6b54cc0b8d247e8d7c7a0975bdc9b","_shrinkwrap":null,"bin":null,"_id":"inherits@1.0.2"},"type":"finalized-manifest"}} \ No newline at end of file diff --git a/test/npm_cache/_cacache/index-v5/b8/16/bf6e49afbd1323783f2f5a63b3d871adc66f517669450807aec3b62e71b2 b/test/npm_cache/_cacache/index-v5/b8/16/bf6e49afbd1323783f2f5a63b3d871adc66f517669450807aec3b62e71b2 new file mode 100644 index 0000000000000..94abfb38ce6fd --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/b8/16/bf6e49afbd1323783f2f5a63b3d871adc66f517669450807aec3b62e71b2 @@ -0,0 +1,2 @@ + +4d69bac991b667e1a5004e3626e1aa3b40390b0d {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz","integrity":"sha1-ykMJ2t7mtUzAuNJH6NfHoJdb3Js=","time":1558529589607,"size":1519,"metadata":{"url":"https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz","reqHeaders":{"connection":["keep-alive"],"user-agent":["npm/6.9.0 node/v12.2.0 linux x64"],"npm-in-ci":["false"],"npm-scope":[""],"npm-session":["cbe86d0bebd8e092"],"referer":["install [REDACTED]"],"pacote-req-type":["tarball"],"pacote-pkg-id":["registry:inherits@https://registry.npmjs.org/inherits/-/inherits-1.0.2.tgz"],"authorization":["Basic dXNlcm5hbWU6cGFzc3dvcmQ="]},"resHeaders":{"date":["Wed, 22 May 2019 12:53:09 GMT"],"content-type":["application/octet-stream"],"content-length":["1519"],"connection":["keep-alive"],"set-cookie":["__cfduid=dfa024e90eaf146937b638444b9c027ec1558529589; expires=Thu, 21-May-20 12:53:09 GMT; path=/; domain=.registry.npmjs.org; HttpOnly"],"cf-cache-status":["HIT"],"cache-control":["max-age=432000"],"cf-ray":["4daeee710d4d7604-ARN"],"accept-ranges":["bytes"],"etag":["\"54a4d8823795a0d30b28479c10e3d486\""],"expect-ct":["max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\""],"last-modified":["Sun, 27 May 2018 04:40:10 GMT"],"vary":["Accept-Encoding"],"server":["cloudflare"],"x-fetch-attempts":["1"]}}} \ No newline at end of file diff --git a/test/npm_cache/_cacache/index-v5/be/6a/458105f31e845d57376ed2b2019e46a63cff8cbb76981a37eac2100c8e55 b/test/npm_cache/_cacache/index-v5/be/6a/458105f31e845d57376ed2b2019e46a63cff8cbb76981a37eac2100c8e55 new file mode 100644 index 0000000000000..35f0e70f5948d --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/be/6a/458105f31e845d57376ed2b2019e46a63cff8cbb76981a37eac2100c8e55 @@ -0,0 +1,3 @@ + +d7c87936ca675486b86bc57df6f96c570d82d271 {"key":"pacote:packed-dir:github:isaacs/sax-js#5aee2163d55cff24b817bbf550bac44841f9df45","integrity":"sha512-0Jrt97Sa1ZrWMJV2CMAWCcYezC6zziDvf5AgroZzqieDUjmdv9sjp0LQdVbhMz7XTNDzP9APQBqpEqB6KhONQQ==","time":1558529607534,"size":15106} +d04d5852522f42319b25f53e2d680d09e1ea679d {"key":"pacote:packed-dir:github:isaacs/sax-js#5aee2163d55cff24b817bbf550bac44841f9df45","integrity":"sha512-0Jrt97Sa1ZrWMJV2CMAWCcYezC6zziDvf5AgroZzqieDUjmdv9sjp0LQdVbhMz7XTNDzP9APQBqpEqB6KhONQQ==","time":1558529619044,"size":15106} \ No newline at end of file diff --git a/test/npm_cache/_cacache/index-v5/cf/e4/3df81895eebe708ef970bd1392d702e19e29ee41c85a315fd7e717f8373c b/test/npm_cache/_cacache/index-v5/cf/e4/3df81895eebe708ef970bd1392d702e19e29ee41c85a315fd7e717f8373c new file mode 100644 index 0000000000000..222bf72f29f19 --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/cf/e4/3df81895eebe708ef970bd1392d702e19e29ee41c85a315fd7e717f8373c @@ -0,0 +1,2 @@ + +7f6a71a3dcdae2ff38192fa82d7fc3dc7256fc8a {"key":"pacote:range-manifest:https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.14.tgz:sha1-BweNtfY3f2Mh/Oqu30l94STclGU=","integrity":"sha512-C2EkHXwXvLsbrucJTRS3xFHv7Mf/y9klmKDxPTE8yevCoH5h8Ae69Y+/lP+ahpW91crnzgO78elOk2E6APJfIQ==","time":1558529589518,"size":1,"metadata":{"id":"graceful-fs@1.1.14","manifest":{"name":"graceful-fs","version":"1.1.14","engines":{"node":">=0.4.0"},"dependencies":{},"optionalDependencies":{},"devDependencies":{},"bundleDependencies":false,"peerDependencies":{},"deprecated":"please upgrade to graceful-fs 4 for compatibility with current and future versions of Node.js","_resolved":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.14.tgz","_integrity":"sha1-BweNtfY3f2Mh/Oqu30l94STclGU=","_shasum":"07078db5f6377f6321fceaaedf497de124dc9465","_shrinkwrap":null,"bin":null,"_id":"graceful-fs@1.1.14"},"type":"finalized-manifest"}} \ No newline at end of file diff --git a/test/npm_cache/_cacache/index-v5/d0/a2/9b5933a9df317b031c4407f0d9cae19a4d56f253f7746786597a52daa76d b/test/npm_cache/_cacache/index-v5/d0/a2/9b5933a9df317b031c4407f0d9cae19a4d56f253f7746786597a52daa76d new file mode 100644 index 0000000000000..85d4dbce95e78 --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/d0/a2/9b5933a9df317b031c4407f0d9cae19a4d56f253f7746786597a52daa76d @@ -0,0 +1,2 @@ + +f705ca7b007baa2dbdb2f30ee1bbbfc29bc40fa6 {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/graceful-fs","integrity":"sha512-rzKbSdpDOrE5owQ/IE19ebrdvglPa2HL09o3TdT7g4zRtwheVyN+H9AoRuCEMMkrjmBAIy7X51hySaV3chT85g==","time":1558529589472,"size":24382,"metadata":{"url":"https://registry.npmjs.org/graceful-fs","reqHeaders":{"connection":["keep-alive"],"user-agent":["npm/6.9.0 node/v12.2.0 linux x64"],"npm-in-ci":["false"],"npm-scope":[""],"npm-session":["cbe86d0bebd8e092"],"referer":["install [REDACTED]"],"pacote-req-type":["packument"],"pacote-pkg-id":["registry:graceful-fs"],"accept":["application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*"],"authorization":["Basic dXNlcm5hbWU6cGFzc3dvcmQ="]},"resHeaders":{"date":["Wed, 22 May 2019 12:53:09 GMT"],"content-type":["application/vnd.npm.install-v1+json"],"content-length":["24382"],"connection":["keep-alive"],"set-cookie":["__cfduid=dfa024e90eaf146937b638444b9c027ec1558529589; expires=Thu, 21-May-20 12:53:09 GMT; path=/; domain=.registry.npmjs.org; HttpOnly"],"cf-cache-status":["HIT"],"cache-control":["max-age=300"],"cf-ray":["4daeee701c577604-ARN"],"accept-ranges":["bytes"],"etag":["\"e8c21a1716f338ea27890ded4d47633a\""],"expect-ct":["max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\""],"last-modified":["Fri, 04 Jan 2019 00:30:41 GMT"],"vary":["accept-encoding, accept"],"x-amz-meta-rev":["205-3d32a6d158bd573a1b428659afcb33cd"],"server":["cloudflare"],"x-fetch-attempts":["1"]}}} \ No newline at end of file diff --git a/test/npm_cache/_cacache/index-v5/fe/7e/e4d136986019ebc5360c54baee7ae9bec37f513387665b57ac2bcd167b70 b/test/npm_cache/_cacache/index-v5/fe/7e/e4d136986019ebc5360c54baee7ae9bec37f513387665b57ac2bcd167b70 new file mode 100644 index 0000000000000..d67e5029db502 --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/fe/7e/e4d136986019ebc5360c54baee7ae9bec37f513387665b57ac2bcd167b70 @@ -0,0 +1,2 @@ + +2d537648cf8f192a5df71abbd46f5ef161ce2e22 {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.14.tgz","integrity":"sha1-BweNtfY3f2Mh/Oqu30l94STclGU=","time":1558529589514,"size":4025,"metadata":{"url":"https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.14.tgz","reqHeaders":{"connection":["keep-alive"],"user-agent":["npm/6.9.0 node/v12.2.0 linux x64"],"npm-in-ci":["false"],"npm-scope":[""],"npm-session":["cbe86d0bebd8e092"],"referer":["install [REDACTED]"],"pacote-req-type":["tarball"],"pacote-pkg-id":["registry:graceful-fs@https://registry.npmjs.org/graceful-fs/-/graceful-fs-1.1.14.tgz"],"authorization":["Basic dXNlcm5hbWU6cGFzc3dvcmQ="]},"resHeaders":{"date":["Wed, 22 May 2019 12:53:09 GMT"],"content-type":["application/octet-stream"],"content-length":["4025"],"connection":["keep-alive"],"set-cookie":["__cfduid=da5e36cf875d3903b79f7ea1d5ee365ae1558529589; expires=Thu, 21-May-20 12:53:09 GMT; path=/; domain=.registry.npmjs.org; HttpOnly"],"cf-cache-status":["HIT"],"cache-control":["max-age=432000"],"cf-ray":["4daeee708f5386ef-ARN"],"accept-ranges":["bytes"],"etag":["\"fb46c820a063a666be04b2c416d51b29\""],"expect-ct":["max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\""],"last-modified":["Sun, 27 May 2018 02:39:27 GMT"],"vary":["Accept-Encoding"],"server":["cloudflare"],"x-fetch-attempts":["1"]}}} \ No newline at end of file diff --git a/test/npm_cache/_cacache/index-v5/ff/d3/eca629ba696cac5a91e13f61bb768d7cbf82072f798d17071572ab3943f2 b/test/npm_cache/_cacache/index-v5/ff/d3/eca629ba696cac5a91e13f61bb768d7cbf82072f798d17071572ab3943f2 new file mode 100644 index 0000000000000..05da3a7f14abd --- /dev/null +++ b/test/npm_cache/_cacache/index-v5/ff/d3/eca629ba696cac5a91e13f61bb768d7cbf82072f798d17071572ab3943f2 @@ -0,0 +1,2 @@ + +8a0edf69f050ae5ef0acd49269ee3c2ae052c859 {"key":"make-fetch-happen:request-cache:https://registry.npmjs.org/inherits","integrity":"sha512-IYLqxPg+UPO2qovqVhxd/r3B1mlB4tp4WvQG4EXeVqD8QiA0yn+iq1+pkCLGuGAgPrSFPOhfFfJrlshLjZ5zIA==","time":1558529589462,"size":1494,"metadata":{"url":"https://registry.npmjs.org/inherits","reqHeaders":{"connection":["keep-alive"],"user-agent":["npm/6.9.0 node/v12.2.0 linux x64"],"npm-in-ci":["false"],"npm-scope":[""],"npm-session":["cbe86d0bebd8e092"],"referer":["install [REDACTED]"],"pacote-req-type":["packument"],"pacote-pkg-id":["registry:inherits"],"accept":["application/vnd.npm.install-v1+json; q=1.0, application/json; q=0.8, */*"],"authorization":["Basic dXNlcm5hbWU6cGFzc3dvcmQ="]},"resHeaders":{"date":["Wed, 22 May 2019 12:53:09 GMT"],"content-type":["application/vnd.npm.install-v1+json"],"content-length":["1494"],"connection":["keep-alive"],"set-cookie":["__cfduid=da5e36cf875d3903b79f7ea1d5ee365ae1558529589; expires=Thu, 21-May-20 12:53:09 GMT; path=/; domain=.registry.npmjs.org; HttpOnly"],"cf-cache-status":["HIT"],"cache-control":["max-age=300"],"cf-ray":["4daeee701f0c86ef-ARN"],"accept-ranges":["bytes"],"etag":["\"419f7e0699d401599186150793ffd002\""],"expect-ct":["max-age=604800, report-uri=\"https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct\""],"last-modified":["Fri, 03 Aug 2018 00:38:04 GMT"],"vary":["accept-encoding, accept"],"server":["cloudflare"],"x-fetch-attempts":["1"]}}} \ No newline at end of file diff --git a/test/npm_cache/anonymous-cli-metrics.json b/test/npm_cache/anonymous-cli-metrics.json new file mode 100644 index 0000000000000..dadc943bc9505 --- /dev/null +++ b/test/npm_cache/anonymous-cli-metrics.json @@ -0,0 +1 @@ +{"metricId":"d39b1c2c-e6ff-46cf-9651-ebcc2eab50da","metrics":{"from":"2019-05-22T12:53:09.760Z","to":"2019-05-22T12:53:39.112Z","successfulInstalls":3,"failedInstalls":0}} \ No newline at end of file From 655bc7b6efae1258cf242c6558440c28cbf55c39 Mon Sep 17 00:00:00 2001 From: Hugh Rawlinson Date: Wed, 22 May 2019 15:18:53 +0200 Subject: [PATCH 2/2] (chore) bump npm-lifecycle npm-lifecycle@2.1.0 also depends on node-gyp@3.8.0. Bumping to npm-lifecycle@2.1.1 addresses the issue --- node_modules/block-stream/LICENCE | 25 - node_modules/block-stream/LICENSE | 15 - node_modules/block-stream/README.md | 14 - node_modules/block-stream/block-stream.js | 209 - node_modules/block-stream/package.json | 60 - node_modules/fstream/.travis.yml | 9 - node_modules/fstream/LICENSE | 15 - node_modules/fstream/README.md | 76 - node_modules/fstream/examples/filter-pipe.js | 134 - node_modules/fstream/examples/pipe.js | 118 - node_modules/fstream/examples/reader.js | 68 - .../fstream/examples/symlink-write.js | 27 - node_modules/fstream/fstream.js | 35 - node_modules/fstream/lib/abstract.js | 85 - node_modules/fstream/lib/collect.js | 70 - node_modules/fstream/lib/dir-reader.js | 252 -- node_modules/fstream/lib/dir-writer.js | 174 - node_modules/fstream/lib/file-reader.js | 150 - node_modules/fstream/lib/file-writer.js | 107 - node_modules/fstream/lib/get-type.js | 33 - node_modules/fstream/lib/link-reader.js | 53 - node_modules/fstream/lib/link-writer.js | 95 - node_modules/fstream/lib/proxy-reader.js | 95 - node_modules/fstream/lib/proxy-writer.js | 111 - node_modules/fstream/lib/reader.js | 255 -- node_modules/fstream/lib/socket-reader.js | 36 - node_modules/fstream/lib/writer.js | 390 -- node_modules/fstream/package.json | 62 - node_modules/npm-lifecycle/CHANGELOG.md | 10 + node_modules/npm-lifecycle/index.js | 2 +- .../npm-lifecycle/node_modules/.bin/node-gyp | 1 - .../npm-lifecycle/node_modules/.bin/nopt | 1 - .../npm-lifecycle/node_modules/.bin/semver | 1 - .../node-gyp/.github/ISSUE_TEMPLATE.md | 26 - .../node-gyp/.github/PULL_REQUEST_TEMPLATE.md | 17 - .../node_modules/node-gyp/CHANGELOG.md | 227 - .../node_modules/node-gyp/CONTRIBUTING.md | 34 - .../node_modules/node-gyp/LICENSE | 24 - .../node_modules/node-gyp/README.md | 244 -- .../node_modules/node-gyp/addon.gypi | 147 - .../node_modules/node-gyp/bin/node-gyp.js | 148 - .../node_modules/node-gyp/gyp/AUTHORS | 13 - .../node_modules/node-gyp/gyp/DEPS | 24 - .../node_modules/node-gyp/gyp/LICENSE | 27 - .../node_modules/node-gyp/gyp/OWNERS | 1 - .../node_modules/node-gyp/gyp/PRESUBMIT.py | 139 - .../node-gyp/gyp/codereview.settings | 10 - .../node-gyp/gyp/data/win/large-pdb-shim.cc | 12 - .../node_modules/node-gyp/gyp/gyp | 8 - .../node_modules/node-gyp/gyp/gyp.bat | 5 - .../node_modules/node-gyp/gyp/gyp_main.py | 16 - .../node-gyp/gyp/pylib/gyp/MSVSNew.py | 340 -- .../node-gyp/gyp/pylib/gyp/MSVSProject.py | 208 - .../node-gyp/gyp/pylib/gyp/MSVSSettings.py | 1096 ----- .../gyp/pylib/gyp/MSVSSettings_test.py | 1483 ------- .../node-gyp/gyp/pylib/gyp/MSVSToolFile.py | 58 - .../node-gyp/gyp/pylib/gyp/MSVSUserFile.py | 147 - .../node-gyp/gyp/pylib/gyp/MSVSUtil.py | 270 -- .../node-gyp/gyp/pylib/gyp/MSVSVersion.py | 443 -- .../node-gyp/gyp/pylib/gyp/__init__.py | 548 --- .../node-gyp/gyp/pylib/gyp/common.py | 612 --- .../node-gyp/gyp/pylib/gyp/common_test.py | 72 - .../node-gyp/gyp/pylib/gyp/easy_xml.py | 162 - .../node-gyp/gyp/pylib/gyp/easy_xml_test.py | 103 - .../node-gyp/gyp/pylib/gyp/flock_tool.py | 54 - .../gyp/pylib/gyp/generator/__init__.py | 0 .../gyp/pylib/gyp/generator/analyzer.py | 741 ---- .../gyp/pylib/gyp/generator/android.py | 1095 ----- .../node-gyp/gyp/pylib/gyp/generator/cmake.py | 1221 ------ .../gyp/generator/dump_dependency_json.py | 99 - .../gyp/pylib/gyp/generator/eclipse.py | 425 -- .../node-gyp/gyp/pylib/gyp/generator/gypd.py | 94 - .../node-gyp/gyp/pylib/gyp/generator/gypsh.py | 56 - .../node-gyp/gyp/pylib/gyp/generator/make.py | 2263 ---------- .../node-gyp/gyp/pylib/gyp/generator/msvs.py | 3494 ---------------- .../gyp/pylib/gyp/generator/msvs_test.py | 37 - .../node-gyp/gyp/pylib/gyp/generator/ninja.py | 2422 ----------- .../gyp/pylib/gyp/generator/ninja_test.py | 47 - .../node-gyp/gyp/pylib/gyp/generator/xcode.py | 1300 ------ .../gyp/pylib/gyp/generator/xcode_test.py | 23 - .../node-gyp/gyp/pylib/gyp/input.py | 2902 ------------- .../node-gyp/gyp/pylib/gyp/input_test.py | 90 - .../node-gyp/gyp/pylib/gyp/mac_tool.py | 610 --- .../node-gyp/gyp/pylib/gyp/msvs_emulation.py | 1087 ----- .../node-gyp/gyp/pylib/gyp/ninja_syntax.py | 160 - .../node-gyp/gyp/pylib/gyp/ordered_dict.py | 289 -- .../node-gyp/gyp/pylib/gyp/simple_copy.py | 46 - .../node-gyp/gyp/pylib/gyp/win_tool.py | 314 -- .../node-gyp/gyp/pylib/gyp/xcode_emulation.py | 1653 -------- .../node-gyp/gyp/pylib/gyp/xcode_ninja.py | 270 -- .../node-gyp/gyp/pylib/gyp/xcodeproj_file.py | 2927 ------------- .../node-gyp/gyp/pylib/gyp/xml_fix.py | 69 - .../node_modules/node-gyp/gyp/samples/samples | 81 - .../node-gyp/gyp/samples/samples.bat | 5 - .../node_modules/node-gyp/gyp/setup.py | 19 - .../node_modules/node-gyp/gyp/tools/README | 15 - .../node-gyp/gyp/tools/Xcode/README | 5 - .../tools/Xcode/Specifications/gyp.pbfilespec | 27 - .../tools/Xcode/Specifications/gyp.xclangspec | 226 - .../node-gyp/gyp/tools/emacs/README | 12 - .../node-gyp/gyp/tools/emacs/gyp-tests.el | 63 - .../node-gyp/gyp/tools/emacs/gyp.el | 275 -- .../gyp/tools/emacs/run-unit-tests.sh | 7 - .../gyp/tools/emacs/testdata/media.gyp | 1105 ----- .../tools/emacs/testdata/media.gyp.fontified | 1107 ----- .../node-gyp/gyp/tools/graphviz.py | 100 - .../node-gyp/gyp/tools/pretty_gyp.py | 155 - .../node-gyp/gyp/tools/pretty_sln.py | 169 - .../node-gyp/gyp/tools/pretty_vcproj.py | 329 -- .../node_modules/node-gyp/lib/Find-VS2017.cs | 273 -- .../node_modules/node-gyp/lib/build.js | 270 -- .../node_modules/node-gyp/lib/clean.js | 22 - .../node_modules/node-gyp/lib/configure.js | 524 --- .../node-gyp/lib/find-node-directory.js | 61 - .../node_modules/node-gyp/lib/find-vs2017.js | 46 - .../node_modules/node-gyp/lib/install.js | 475 --- .../node_modules/node-gyp/lib/list.js | 33 - .../node_modules/node-gyp/lib/node-gyp.js | 216 - .../node-gyp/lib/process-release.js | 155 - .../node_modules/node-gyp/lib/rebuild.js | 14 - .../node_modules/node-gyp/lib/remove.js | 52 - .../node_modules/node-gyp/package.json | 85 - .../node-gyp/src/win_delay_load_hook.cc | 36 - .../node_modules/node-gyp/test/docker.sh | 164 - .../node-gyp/test/fixtures/ca-bundle.crt | 40 - .../node-gyp/test/fixtures/ca.crt | 21 - .../node-gyp/test/fixtures/server.crt | 19 - .../node-gyp/test/fixtures/server.key | 28 - .../node-gyp/test/fixtures/test-charmap.py | 22 - .../node-gyp/test/process-exec-sync.js | 138 - .../node-gyp/test/simple-proxy.js | 24 - .../node_modules/node-gyp/test/test-addon.js | 113 - .../node-gyp/test/test-configure-python.js | 74 - .../node-gyp/test/test-download.js | 102 - .../test/test-find-accessible-sync.js | 86 - .../node-gyp/test/test-find-node-directory.js | 115 - .../node-gyp/test/test-find-python.js | 339 -- .../node-gyp/test/test-install.js | 37 - .../node-gyp/test/test-options.js | 25 - .../node-gyp/test/test-process-release.js | 637 --- .../gyp/generator/compile_commands_json.py | 115 - .../node_modules/nopt/.npmignore | 1 - .../node_modules/nopt/.travis.yml | 9 - .../npm-lifecycle/node_modules/nopt/LICENSE | 15 - .../npm-lifecycle/node_modules/nopt/README.md | 211 - .../node_modules/nopt/bin/nopt.js | 54 - .../node_modules/nopt/examples/my-program.js | 30 - .../node_modules/nopt/lib/nopt.js | 415 -- .../node_modules/nopt/package.json | 57 - .../node_modules/nopt/test/basic.js | 273 -- .../npm-lifecycle/node_modules/semver/LICENSE | 15 - .../node_modules/semver/README.md | 350 -- .../node_modules/semver/bin/semver | 133 - .../node_modules/semver/package.json | 54 - .../node_modules/semver/range.bnf | 16 - .../node_modules/semver/semver.js | 1203 ------ .../node_modules/tar/.travis.yml | 4 - .../npm-lifecycle/node_modules/tar/LICENSE | 12 - .../npm-lifecycle/node_modules/tar/README.md | 50 - .../tar/coverage/lcov-report/base.css | 212 - .../tar/coverage/lcov-report/index.html | 106 - .../tar/coverage/lcov-report/prettify.css | 1 - .../tar/coverage/lcov-report/prettify.js | 1 - .../lcov-report/sort-arrow-sprite.png | Bin 209 -> 0 bytes .../tar/coverage/lcov-report/sorter.js | 158 - .../tar/coverage/lcov-report/tar/index.html | 93 - .../coverage/lcov-report/tar/index.js.html | 119 - .../lcov-report/tar/lib/create.js.html | 380 -- .../lcov-report/tar/lib/extract.js.html | 401 -- .../lcov-report/tar/lib/header.js.html | 881 ---- .../tar/lib/high-level-opt.js.html | 152 - .../coverage/lcov-report/tar/lib/index.html | 314 -- .../lcov-report/tar/lib/large-numbers.js.html | 341 -- .../coverage/lcov-report/tar/lib/list.js.html | 449 -- .../lcov-report/tar/lib/mkdir.js.html | 686 --- .../coverage/lcov-report/tar/lib/pack.js.html | 1268 ------ .../lcov-report/tar/lib/parse.js.html | 1310 ------ .../coverage/lcov-report/tar/lib/pax.js.html | 500 --- .../lcov-report/tar/lib/read-entry.js.html | 347 -- .../lcov-report/tar/lib/replace.js.html | 722 ---- .../lcov-report/tar/lib/types.js.html | 197 - .../lcov-report/tar/lib/unpack.js.html | 1604 ------- .../lcov-report/tar/lib/update.js.html | 173 - .../lcov-report/tar/lib/warn-mixin.js.html | 107 - .../lcov-report/tar/lib/winchars.js.html | 134 - .../lcov-report/tar/lib/write-entry.js.html | 1268 ------ .../node_modules/tar/coverage/lcov.info | 3690 ----------------- .../node_modules/tar/examples/extracter.js | 19 - .../node_modules/tar/examples/packer.js | 24 - .../node_modules/tar/examples/reader.js | 36 - .../node_modules/tar/lib/buffer-entry.js | 30 - .../node_modules/tar/lib/entry-writer.js | 169 - .../node_modules/tar/lib/entry.js | 220 - .../tar/lib/extended-header-writer.js | 191 - .../node_modules/tar/lib/extended-header.js | 140 - .../node_modules/tar/lib/extract.js | 94 - .../tar/lib/global-header-writer.js | 14 - .../node_modules/tar/lib/header.js | 385 -- .../node_modules/tar/lib/pack.js | 236 -- .../node_modules/tar/lib/parse.js | 281 -- .../node_modules/tar/package.json | 59 - .../npm-lifecycle/node_modules/tar/tar.js | 173 - .../tar/test/00-setup-fixtures.js | 53 - .../tar/test/cb-never-called-1.0.1.tgz | Bin 4096 -> 0 bytes .../tar/test/dir-normalization.js | 177 - .../tar/test/dir-normalization.tar | Bin 4608 -> 0 bytes .../node_modules/tar/test/error-on-broken.js | 33 - .../node_modules/tar/test/extract-move.js | 132 - .../node_modules/tar/test/extract.js | 367 -- .../node_modules/tar/test/fixtures.tgz | Bin 19352 -> 0 bytes .../node_modules/tar/test/header.js | 183 - .../tar/test/link-file-entry-collision.js | 39 - .../link-file-entry-collision/bad-link.hex | 25 - .../link-file-entry-collision/bad-link.tar | Bin 3584 -> 0 bytes .../tar/test/pack-no-proprietary.js | 886 ---- .../node_modules/tar/test/pack.js | 952 ----- .../node_modules/tar/test/parse-discard.js | 29 - .../node_modules/tar/test/parse.js | 359 -- .../node_modules/tar/test/zz-cleanup.js | 20 - node_modules/npm-lifecycle/package.json | 39 +- package-lock.json | 73 +- package.json | 2 +- 222 files changed, 37 insertions(+), 65220 deletions(-) delete mode 100644 node_modules/block-stream/LICENCE delete mode 100644 node_modules/block-stream/LICENSE delete mode 100644 node_modules/block-stream/README.md delete mode 100644 node_modules/block-stream/block-stream.js delete mode 100644 node_modules/block-stream/package.json delete mode 100644 node_modules/fstream/.travis.yml delete mode 100644 node_modules/fstream/LICENSE delete mode 100644 node_modules/fstream/README.md delete mode 100644 node_modules/fstream/examples/filter-pipe.js delete mode 100644 node_modules/fstream/examples/pipe.js delete mode 100644 node_modules/fstream/examples/reader.js delete mode 100644 node_modules/fstream/examples/symlink-write.js delete mode 100644 node_modules/fstream/fstream.js delete mode 100644 node_modules/fstream/lib/abstract.js delete mode 100644 node_modules/fstream/lib/collect.js delete mode 100644 node_modules/fstream/lib/dir-reader.js delete mode 100644 node_modules/fstream/lib/dir-writer.js delete mode 100644 node_modules/fstream/lib/file-reader.js delete mode 100644 node_modules/fstream/lib/file-writer.js delete mode 100644 node_modules/fstream/lib/get-type.js delete mode 100644 node_modules/fstream/lib/link-reader.js delete mode 100644 node_modules/fstream/lib/link-writer.js delete mode 100644 node_modules/fstream/lib/proxy-reader.js delete mode 100644 node_modules/fstream/lib/proxy-writer.js delete mode 100644 node_modules/fstream/lib/reader.js delete mode 100644 node_modules/fstream/lib/socket-reader.js delete mode 100644 node_modules/fstream/lib/writer.js delete mode 100644 node_modules/fstream/package.json delete mode 120000 node_modules/npm-lifecycle/node_modules/.bin/node-gyp delete mode 120000 node_modules/npm-lifecycle/node_modules/.bin/nopt delete mode 120000 node_modules/npm-lifecycle/node_modules/.bin/semver delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/.github/ISSUE_TEMPLATE.md delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/.github/PULL_REQUEST_TEMPLATE.md delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/CHANGELOG.md delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/CONTRIBUTING.md delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/LICENSE delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/README.md delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/addon.gypi delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/bin/node-gyp.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/AUTHORS delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/DEPS delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/LICENSE delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/OWNERS delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/PRESUBMIT.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/codereview.settings delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp.bat delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp_main.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/__init__.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common_test.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input_test.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ordered_dict.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples.bat delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/setup.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/README delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/README delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.pbfilespec delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.xclangspec delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/emacs/README delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/emacs/gyp-tests.el delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/emacs/gyp.el delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/emacs/run-unit-tests.sh delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/emacs/testdata/media.gyp delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/emacs/testdata/media.gyp.fontified delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/graphviz.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_gyp.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_sln.py delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_vcproj.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/Find-VS2017.cs delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/build.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/clean.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/configure.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-node-directory.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-vs2017.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/install.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/list.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/node-gyp.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/process-release.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/rebuild.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/lib/remove.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/package.json delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/src/win_delay_load_hook.cc delete mode 100755 node_modules/npm-lifecycle/node_modules/node-gyp/test/docker.sh delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca-bundle.crt delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca.crt delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.crt delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.key delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/test-charmap.py delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/process-exec-sync.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/simple-proxy.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-addon.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-configure-python.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-download.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-accessible-sync.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-node-directory.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-python.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-install.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-options.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/test/test-process-release.js delete mode 100644 node_modules/npm-lifecycle/node_modules/node-gyp/tools/gyp/pylib/gyp/generator/compile_commands_json.py delete mode 100644 node_modules/npm-lifecycle/node_modules/nopt/.npmignore delete mode 100644 node_modules/npm-lifecycle/node_modules/nopt/.travis.yml delete mode 100644 node_modules/npm-lifecycle/node_modules/nopt/LICENSE delete mode 100644 node_modules/npm-lifecycle/node_modules/nopt/README.md delete mode 100755 node_modules/npm-lifecycle/node_modules/nopt/bin/nopt.js delete mode 100755 node_modules/npm-lifecycle/node_modules/nopt/examples/my-program.js delete mode 100644 node_modules/npm-lifecycle/node_modules/nopt/lib/nopt.js delete mode 100644 node_modules/npm-lifecycle/node_modules/nopt/package.json delete mode 100644 node_modules/npm-lifecycle/node_modules/nopt/test/basic.js delete mode 100644 node_modules/npm-lifecycle/node_modules/semver/LICENSE delete mode 100644 node_modules/npm-lifecycle/node_modules/semver/README.md delete mode 100755 node_modules/npm-lifecycle/node_modules/semver/bin/semver delete mode 100644 node_modules/npm-lifecycle/node_modules/semver/package.json delete mode 100644 node_modules/npm-lifecycle/node_modules/semver/range.bnf delete mode 100644 node_modules/npm-lifecycle/node_modules/semver/semver.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/.travis.yml delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/LICENSE delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/README.md delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/base.css delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/index.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.css delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/sort-arrow-sprite.png delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/sorter.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/create.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/extract.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/header.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/high-level-opt.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/index.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/large-numbers.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/list.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/mkdir.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pack.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/parse.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pax.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/read-entry.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/replace.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/types.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/unpack.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/update.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/warn-mixin.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/winchars.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/write-entry.js.html delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/coverage/lcov.info delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/examples/extracter.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/examples/packer.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/examples/reader.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/lib/buffer-entry.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/lib/entry-writer.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/lib/entry.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/lib/extended-header-writer.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/lib/extended-header.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/lib/extract.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/lib/global-header-writer.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/lib/header.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/lib/pack.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/lib/parse.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/package.json delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/tar.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/00-setup-fixtures.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/cb-never-called-1.0.1.tgz delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/dir-normalization.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/dir-normalization.tar delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/error-on-broken.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/extract-move.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/extract.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/fixtures.tgz delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/header.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.hex delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.tar delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/pack-no-proprietary.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/pack.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/parse-discard.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/parse.js delete mode 100644 node_modules/npm-lifecycle/node_modules/tar/test/zz-cleanup.js diff --git a/node_modules/block-stream/LICENCE b/node_modules/block-stream/LICENCE deleted file mode 100644 index 74489e2e2658e..0000000000000 --- a/node_modules/block-stream/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/node_modules/block-stream/LICENSE b/node_modules/block-stream/LICENSE deleted file mode 100644 index 19129e315fe59..0000000000000 --- a/node_modules/block-stream/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -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/node_modules/block-stream/README.md b/node_modules/block-stream/README.md deleted file mode 100644 index c16e9c468891d..0000000000000 --- a/node_modules/block-stream/README.md +++ /dev/null @@ -1,14 +0,0 @@ -# block-stream - -A stream of blocks. - -Write data into it, and it'll output data in buffer blocks the size you -specify, padding with zeroes if necessary. - -```javascript -var block = new BlockStream(512) -fs.createReadStream("some-file").pipe(block) -block.pipe(fs.createWriteStream("block-file")) -``` - -When `.end()` or `.flush()` is called, it'll pad the block with zeroes. diff --git a/node_modules/block-stream/block-stream.js b/node_modules/block-stream/block-stream.js deleted file mode 100644 index 008de035c2edc..0000000000000 --- a/node_modules/block-stream/block-stream.js +++ /dev/null @@ -1,209 +0,0 @@ -// write data to it, and it'll emit data in 512 byte blocks. -// if you .end() or .flush(), it'll emit whatever it's got, -// padded with nulls to 512 bytes. - -module.exports = BlockStream - -var Stream = require("stream").Stream - , inherits = require("inherits") - , assert = require("assert").ok - , debug = process.env.DEBUG ? console.error : function () {} - -function BlockStream (size, opt) { - this.writable = this.readable = true - this._opt = opt || {} - this._chunkSize = size || 512 - this._offset = 0 - this._buffer = [] - this._bufferLength = 0 - if (this._opt.nopad) this._zeroes = false - else { - this._zeroes = new Buffer(this._chunkSize) - for (var i = 0; i < this._chunkSize; i ++) { - this._zeroes[i] = 0 - } - } -} - -inherits(BlockStream, Stream) - -BlockStream.prototype.write = function (c) { - // debug(" BS write", c) - if (this._ended) throw new Error("BlockStream: write after end") - if (c && !Buffer.isBuffer(c)) c = new Buffer(c + "") - if (c.length) { - this._buffer.push(c) - this._bufferLength += c.length - } - // debug("pushed onto buffer", this._bufferLength) - if (this._bufferLength >= this._chunkSize) { - if (this._paused) { - // debug(" BS paused, return false, need drain") - this._needDrain = true - return false - } - this._emitChunk() - } - return true -} - -BlockStream.prototype.pause = function () { - // debug(" BS pausing") - this._paused = true -} - -BlockStream.prototype.resume = function () { - // debug(" BS resume") - this._paused = false - return this._emitChunk() -} - -BlockStream.prototype.end = function (chunk) { - // debug("end", chunk) - if (typeof chunk === "function") cb = chunk, chunk = null - if (chunk) this.write(chunk) - this._ended = true - this.flush() -} - -BlockStream.prototype.flush = function () { - this._emitChunk(true) -} - -BlockStream.prototype._emitChunk = function (flush) { - // debug("emitChunk flush=%j emitting=%j paused=%j", flush, this._emitting, this._paused) - - // emit a chunk - if (flush && this._zeroes) { - // debug(" BS push zeroes", this._bufferLength) - // push a chunk of zeroes - var padBytes = (this._bufferLength % this._chunkSize) - if (padBytes !== 0) padBytes = this._chunkSize - padBytes - if (padBytes > 0) { - // debug("padBytes", padBytes, this._zeroes.slice(0, padBytes)) - this._buffer.push(this._zeroes.slice(0, padBytes)) - this._bufferLength += padBytes - // debug(this._buffer[this._buffer.length - 1].length, this._bufferLength) - } - } - - if (this._emitting || this._paused) return - this._emitting = true - - // debug(" BS entering loops") - var bufferIndex = 0 - while (this._bufferLength >= this._chunkSize && - (flush || !this._paused)) { - // debug(" BS data emission loop", this._bufferLength) - - var out - , outOffset = 0 - , outHas = this._chunkSize - - while (outHas > 0 && (flush || !this._paused) ) { - // debug(" BS data inner emit loop", this._bufferLength) - var cur = this._buffer[bufferIndex] - , curHas = cur.length - this._offset - // debug("cur=", cur) - // debug("curHas=%j", curHas) - // If it's not big enough to fill the whole thing, then we'll need - // to copy multiple buffers into one. However, if it is big enough, - // then just slice out the part we want, to save unnecessary copying. - // Also, need to copy if we've already done some copying, since buffers - // can't be joined like cons strings. - if (out || curHas < outHas) { - out = out || new Buffer(this._chunkSize) - cur.copy(out, outOffset, - this._offset, this._offset + Math.min(curHas, outHas)) - } else if (cur.length === outHas && this._offset === 0) { - // shortcut -- cur is exactly long enough, and no offset. - out = cur - } else { - // slice out the piece of cur that we need. - out = cur.slice(this._offset, this._offset + outHas) - } - - if (curHas > outHas) { - // means that the current buffer couldn't be completely output - // update this._offset to reflect how much WAS written - this._offset += outHas - outHas = 0 - } else { - // output the entire current chunk. - // toss it away - outHas -= curHas - outOffset += curHas - bufferIndex ++ - this._offset = 0 - } - } - - this._bufferLength -= this._chunkSize - assert(out.length === this._chunkSize) - // debug("emitting data", out) - // debug(" BS emitting, paused=%j", this._paused, this._bufferLength) - this.emit("data", out) - out = null - } - // debug(" BS out of loops", this._bufferLength) - - // whatever is left, it's not enough to fill up a block, or we're paused - this._buffer = this._buffer.slice(bufferIndex) - if (this._paused) { - // debug(" BS paused, leaving", this._bufferLength) - this._needsDrain = true - this._emitting = false - return - } - - // if flushing, and not using null-padding, then need to emit the last - // chunk(s) sitting in the queue. We know that it's not enough to - // fill up a whole block, because otherwise it would have been emitted - // above, but there may be some offset. - var l = this._buffer.length - if (flush && !this._zeroes && l) { - if (l === 1) { - if (this._offset) { - this.emit("data", this._buffer[0].slice(this._offset)) - } else { - this.emit("data", this._buffer[0]) - } - } else { - var outHas = this._bufferLength - , out = new Buffer(outHas) - , outOffset = 0 - for (var i = 0; i < l; i ++) { - var cur = this._buffer[i] - , curHas = cur.length - this._offset - cur.copy(out, outOffset, this._offset) - this._offset = 0 - outOffset += curHas - this._bufferLength -= curHas - } - this.emit("data", out) - } - // truncate - this._buffer.length = 0 - this._bufferLength = 0 - this._offset = 0 - } - - // now either drained or ended - // debug("either draining, or ended", this._bufferLength, this._ended) - // means that we've flushed out all that we can so far. - if (this._needDrain) { - // debug("emitting drain", this._bufferLength) - this._needDrain = false - this.emit("drain") - } - - if ((this._bufferLength === 0) && this._ended && !this._endEmitted) { - // debug("emitting end", this._bufferLength) - this._endEmitted = true - this.emit("end") - } - - this._emitting = false - - // debug(" BS no longer emitting", flush, this._paused, this._emitting, this._bufferLength, this._chunkSize) -} diff --git a/node_modules/block-stream/package.json b/node_modules/block-stream/package.json deleted file mode 100644 index d7d591cf904b0..0000000000000 --- a/node_modules/block-stream/package.json +++ /dev/null @@ -1,60 +0,0 @@ -{ - "_from": "block-stream@*", - "_id": "block-stream@0.0.9", - "_inBundle": false, - "_integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "_location": "/block-stream", - "_phantomChildren": {}, - "_requested": { - "type": "range", - "registry": true, - "raw": "block-stream@*", - "name": "block-stream", - "escapedName": "block-stream", - "rawSpec": "*", - "saveSpec": null, - "fetchSpec": "*" - }, - "_requiredBy": [ - "/node-gyp/tar" - ], - "_resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "_shasum": "13ebfe778a03205cfe03751481ebb4b3300c126a", - "_spec": "block-stream@*", - "_where": "/Users/rebecca/code/npm/node_modules/node-gyp/node_modules/tar", - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me", - "url": "http://blog.izs.me/" - }, - "bugs": { - "url": "https://github.com/isaacs/block-stream/issues" - }, - "bundleDependencies": false, - "dependencies": { - "inherits": "~2.0.0" - }, - "deprecated": false, - "description": "a stream of blocks", - "devDependencies": { - "tap": "^5.7.1" - }, - "engines": { - "node": "0.4 || >=0.5.8" - }, - "files": [ - "block-stream.js" - ], - "homepage": "https://github.com/isaacs/block-stream#readme", - "license": "ISC", - "main": "block-stream.js", - "name": "block-stream", - "repository": { - "type": "git", - "url": "git://github.com/isaacs/block-stream.git" - }, - "scripts": { - "test": "tap test/*.js --cov" - }, - "version": "0.0.9" -} diff --git a/node_modules/fstream/.travis.yml b/node_modules/fstream/.travis.yml deleted file mode 100644 index 9f5972ab5aa1c..0000000000000 --- a/node_modules/fstream/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: node_js -node_js: - - "6" - - "4" - - "0.10" - - "0.12" -before_install: - - "npm config set spin false" - - "npm install -g npm/npm" diff --git a/node_modules/fstream/LICENSE b/node_modules/fstream/LICENSE deleted file mode 100644 index 19129e315fe59..0000000000000 --- a/node_modules/fstream/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -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/node_modules/fstream/README.md b/node_modules/fstream/README.md deleted file mode 100644 index 9d8cb77e5c30b..0000000000000 --- a/node_modules/fstream/README.md +++ /dev/null @@ -1,76 +0,0 @@ -Like FS streams, but with stat on them, and supporting directories and -symbolic links, as well as normal files. Also, you can use this to set -the stats on a file, even if you don't change its contents, or to create -a symlink, etc. - -So, for example, you can "write" a directory, and it'll call `mkdir`. You -can specify a uid and gid, and it'll call `chown`. You can specify a -`mtime` and `atime`, and it'll call `utimes`. You can call it a symlink -and provide a `linkpath` and it'll call `symlink`. - -Note that it won't automatically resolve symbolic links. So, if you -call `fstream.Reader('/some/symlink')` then you'll get an object -that stats and then ends immediately (since it has no data). To follow -symbolic links, do this: `fstream.Reader({path:'/some/symlink', follow: -true })`. - -There are various checks to make sure that the bytes emitted are the -same as the intended size, if the size is set. - -## Examples - -```javascript -fstream - .Writer({ path: "path/to/file" - , mode: 0755 - , size: 6 - }) - .write("hello\n") - .end() -``` - -This will create the directories if they're missing, and then write -`hello\n` into the file, chmod it to 0755, and assert that 6 bytes have -been written when it's done. - -```javascript -fstream - .Writer({ path: "path/to/file" - , mode: 0755 - , size: 6 - , flags: "a" - }) - .write("hello\n") - .end() -``` - -You can pass flags in, if you want to append to a file. - -```javascript -fstream - .Writer({ path: "path/to/symlink" - , linkpath: "./file" - , SymbolicLink: true - , mode: "0755" // octal strings supported - }) - .end() -``` - -If isSymbolicLink is a function, it'll be called, and if it returns -true, then it'll treat it as a symlink. If it's not a function, then -any truish value will make a symlink, or you can set `type: -'SymbolicLink'`, which does the same thing. - -Note that the linkpath is relative to the symbolic link location, not -the parent dir or cwd. - -```javascript -fstream - .Reader("path/to/dir") - .pipe(fstream.Writer("path/to/other/dir")) -``` - -This will do like `cp -Rp path/to/dir path/to/other/dir`. If the other -dir exists and isn't a directory, then it'll emit an error. It'll also -set the uid, gid, mode, etc. to be identical. In this way, it's more -like `rsync -a` than simply a copy. diff --git a/node_modules/fstream/examples/filter-pipe.js b/node_modules/fstream/examples/filter-pipe.js deleted file mode 100644 index 83dadef8a6f39..0000000000000 --- a/node_modules/fstream/examples/filter-pipe.js +++ /dev/null @@ -1,134 +0,0 @@ -var fstream = require('../fstream.js') -var path = require('path') - -var r = fstream.Reader({ - path: path.dirname(__dirname), - filter: function () { - return !this.basename.match(/^\./) && - !this.basename.match(/^node_modules$/) && - !this.basename.match(/^deep-copy$/) && - !this.basename.match(/^filter-copy$/) - } -}) - -// this writer will only write directories -var w = fstream.Writer({ - path: path.resolve(__dirname, 'filter-copy'), - type: 'Directory', - filter: function () { - return this.type === 'Directory' - } -}) - -var indent = '' - -r.on('entry', appears) -r.on('ready', function () { - console.error('ready to begin!', r.path) -}) - -function appears (entry) { - console.error(indent + 'a %s appears!', entry.type, entry.basename, typeof entry.basename) - if (foggy) { - console.error('FOGGY!') - var p = entry - do { - console.error(p.depth, p.path, p._paused) - p = p.parent - } while (p) - - throw new Error('\u001b[mshould not have entries while foggy') - } - indent += '\t' - entry.on('data', missile(entry)) - entry.on('end', runaway(entry)) - entry.on('entry', appears) -} - -var foggy -function missile (entry) { - function liftFog (who) { - if (!foggy) return - if (who) { - console.error('%s breaks the spell!', who && who.path) - } else { - console.error('the spell expires!') - } - console.error('\u001b[mthe fog lifts!\n') - clearTimeout(foggy) - foggy = null - if (entry._paused) entry.resume() - } - - if (entry.type === 'Directory') { - var ended = false - entry.once('end', function () { ended = true }) - return function (c) { - // throw in some pathological pause()/resume() behavior - // just for extra fun. - process.nextTick(function () { - if (!foggy && !ended) { // && Math.random() < 0.3) { - console.error(indent + '%s casts a spell', entry.basename) - console.error('\na slowing fog comes over the battlefield...\n\u001b[32m') - entry.pause() - entry.once('resume', liftFog) - foggy = setTimeout(liftFog, 1000) - } - }) - } - } - - return function (c) { - var e = Math.random() < 0.5 - console.error(indent + '%s %s for %d damage!', - entry.basename, - e ? 'is struck' : 'fires a chunk', - c.length) - } -} - -function runaway (entry) { - return function () { - var e = Math.random() < 0.5 - console.error(indent + '%s %s', - entry.basename, - e ? 'turns to flee' : 'is vanquished!') - indent = indent.slice(0, -1) - } -} - -w.on('entry', attacks) -// w.on('ready', function () { attacks(w) }) -function attacks (entry) { - console.error(indent + '%s %s!', entry.basename, - entry.type === 'Directory' ? 'calls for backup' : 'attacks') - entry.on('entry', attacks) -} - -var ended = false -var i = 1 -r.on('end', function () { - if (foggy) clearTimeout(foggy) - console.error("\u001b[mIT'S OVER!!") - console.error('A WINNAR IS YOU!') - - console.log('ok ' + (i++) + ' A WINNAR IS YOU') - ended = true - // now go through and verify that everything in there is a dir. - var p = path.resolve(__dirname, 'filter-copy') - var checker = fstream.Reader({ path: p }) - checker.checker = true - checker.on('child', function (e) { - var ok = e.type === 'Directory' - console.log((ok ? '' : 'not ') + 'ok ' + (i++) + - ' should be a dir: ' + - e.path.substr(checker.path.length + 1)) - }) -}) - -process.on('exit', function () { - console.log((ended ? '' : 'not ') + 'ok ' + (i) + ' ended') - console.log('1..' + i) -}) - -r.pipe(w) diff --git a/node_modules/fstream/examples/pipe.js b/node_modules/fstream/examples/pipe.js deleted file mode 100644 index 3de42ef32bfd7..0000000000000 --- a/node_modules/fstream/examples/pipe.js +++ /dev/null @@ -1,118 +0,0 @@ -var fstream = require('../fstream.js') -var path = require('path') - -var r = fstream.Reader({ - path: path.dirname(__dirname), - filter: function () { - return !this.basename.match(/^\./) && - !this.basename.match(/^node_modules$/) && - !this.basename.match(/^deep-copy$/) - } -}) - -var w = fstream.Writer({ - path: path.resolve(__dirname, 'deep-copy'), - type: 'Directory' -}) - -var indent = '' - -r.on('entry', appears) -r.on('ready', function () { - console.error('ready to begin!', r.path) -}) - -function appears (entry) { - console.error(indent + 'a %s appears!', entry.type, entry.basename, typeof entry.basename, entry) - if (foggy) { - console.error('FOGGY!') - var p = entry - do { - console.error(p.depth, p.path, p._paused) - p = p.parent - } while (p) - - throw new Error('\u001b[mshould not have entries while foggy') - } - indent += '\t' - entry.on('data', missile(entry)) - entry.on('end', runaway(entry)) - entry.on('entry', appears) -} - -var foggy -function missile (entry) { - function liftFog (who) { - if (!foggy) return - if (who) { - console.error('%s breaks the spell!', who && who.path) - } else { - console.error('the spell expires!') - } - console.error('\u001b[mthe fog lifts!\n') - clearTimeout(foggy) - foggy = null - if (entry._paused) entry.resume() - } - - if (entry.type === 'Directory') { - var ended = false - entry.once('end', function () { ended = true }) - return function (c) { - // throw in some pathological pause()/resume() behavior - // just for extra fun. - process.nextTick(function () { - if (!foggy && !ended) { // && Math.random() < 0.3) { - console.error(indent + '%s casts a spell', entry.basename) - console.error('\na slowing fog comes over the battlefield...\n\u001b[32m') - entry.pause() - entry.once('resume', liftFog) - foggy = setTimeout(liftFog, 10) - } - }) - } - } - - return function (c) { - var e = Math.random() < 0.5 - console.error(indent + '%s %s for %d damage!', - entry.basename, - e ? 'is struck' : 'fires a chunk', - c.length) - } -} - -function runaway (entry) { - return function () { - var e = Math.random() < 0.5 - console.error(indent + '%s %s', - entry.basename, - e ? 'turns to flee' : 'is vanquished!') - indent = indent.slice(0, -1) - } -} - -w.on('entry', attacks) -// w.on('ready', function () { attacks(w) }) -function attacks (entry) { - console.error(indent + '%s %s!', entry.basename, - entry.type === 'Directory' ? 'calls for backup' : 'attacks') - entry.on('entry', attacks) -} - -var ended = false -r.on('end', function () { - if (foggy) clearTimeout(foggy) - console.error("\u001b[mIT'S OVER!!") - console.error('A WINNAR IS YOU!') - - console.log('ok 1 A WINNAR IS YOU') - ended = true -}) - -process.on('exit', function () { - console.log((ended ? '' : 'not ') + 'ok 2 ended') - console.log('1..2') -}) - -r.pipe(w) diff --git a/node_modules/fstream/examples/reader.js b/node_modules/fstream/examples/reader.js deleted file mode 100644 index 19affbe7e6e23..0000000000000 --- a/node_modules/fstream/examples/reader.js +++ /dev/null @@ -1,68 +0,0 @@ -var fstream = require('../fstream.js') -var tap = require('tap') -var fs = require('fs') -var path = require('path') -var dir = path.dirname(__dirname) - -tap.test('reader test', function (t) { - var children = -1 - var gotReady = false - var ended = false - - var r = fstream.Reader({ - path: dir, - filter: function () { - // return this.parent === r - return this.parent === r || this === r - } - }) - - r.on('ready', function () { - gotReady = true - children = fs.readdirSync(dir).length - console.error('Setting expected children to ' + children) - t.equal(r.type, 'Directory', 'should be a directory') - }) - - r.on('entry', function (entry) { - children-- - if (!gotReady) { - t.fail('children before ready!') - } - t.equal(entry.dirname, r.path, 'basename is parent dir') - }) - - r.on('error', function (er) { - t.fail(er) - t.end() - process.exit(1) - }) - - r.on('end', function () { - t.equal(children, 0, 'should have seen all children') - ended = true - }) - - var closed = false - r.on('close', function () { - t.ok(ended, 'saw end before close') - t.notOk(closed, 'close should only happen once') - closed = true - t.end() - }) -}) - -tap.test('reader error test', function (t) { - // assumes non-root on a *nix system - var r = fstream.Reader({ path: '/etc/shadow' }) - - r.once('error', function (er) { - t.ok(true) - t.end() - }) - - r.on('end', function () { - t.fail('reader ended without error') - t.end() - }) -}) diff --git a/node_modules/fstream/examples/symlink-write.js b/node_modules/fstream/examples/symlink-write.js deleted file mode 100644 index 19e81eea9fe80..0000000000000 --- a/node_modules/fstream/examples/symlink-write.js +++ /dev/null @@ -1,27 +0,0 @@ -var fstream = require('../fstream.js') -var notOpen = false -process.chdir(__dirname) - -fstream - .Writer({ - path: 'path/to/symlink', - linkpath: './file', - isSymbolicLink: true, - mode: '0755' // octal strings supported - }) - .on('close', function () { - notOpen = true - var fs = require('fs') - var s = fs.lstatSync('path/to/symlink') - var isSym = s.isSymbolicLink() - console.log((isSym ? '' : 'not ') + 'ok 1 should be symlink') - var t = fs.readlinkSync('path/to/symlink') - var isTarget = t === './file' - console.log((isTarget ? '' : 'not ') + 'ok 2 should link to ./file') - }) - .end() - -process.on('exit', function () { - console.log((notOpen ? '' : 'not ') + 'ok 3 should be closed') - console.log('1..3') -}) diff --git a/node_modules/fstream/fstream.js b/node_modules/fstream/fstream.js deleted file mode 100644 index c0eb3bea78803..0000000000000 --- a/node_modules/fstream/fstream.js +++ /dev/null @@ -1,35 +0,0 @@ -exports.Abstract = require('./lib/abstract.js') -exports.Reader = require('./lib/reader.js') -exports.Writer = require('./lib/writer.js') - -exports.File = { - Reader: require('./lib/file-reader.js'), - Writer: require('./lib/file-writer.js') -} - -exports.Dir = { - Reader: require('./lib/dir-reader.js'), - Writer: require('./lib/dir-writer.js') -} - -exports.Link = { - Reader: require('./lib/link-reader.js'), - Writer: require('./lib/link-writer.js') -} - -exports.Proxy = { - Reader: require('./lib/proxy-reader.js'), - Writer: require('./lib/proxy-writer.js') -} - -exports.Reader.Dir = exports.DirReader = exports.Dir.Reader -exports.Reader.File = exports.FileReader = exports.File.Reader -exports.Reader.Link = exports.LinkReader = exports.Link.Reader -exports.Reader.Proxy = exports.ProxyReader = exports.Proxy.Reader - -exports.Writer.Dir = exports.DirWriter = exports.Dir.Writer -exports.Writer.File = exports.FileWriter = exports.File.Writer -exports.Writer.Link = exports.LinkWriter = exports.Link.Writer -exports.Writer.Proxy = exports.ProxyWriter = exports.Proxy.Writer - -exports.collect = require('./lib/collect.js') diff --git a/node_modules/fstream/lib/abstract.js b/node_modules/fstream/lib/abstract.js deleted file mode 100644 index 97c120e1d5277..0000000000000 --- a/node_modules/fstream/lib/abstract.js +++ /dev/null @@ -1,85 +0,0 @@ -// the parent class for all fstreams. - -module.exports = Abstract - -var Stream = require('stream').Stream -var inherits = require('inherits') - -function Abstract () { - Stream.call(this) -} - -inherits(Abstract, Stream) - -Abstract.prototype.on = function (ev, fn) { - if (ev === 'ready' && this.ready) { - process.nextTick(fn.bind(this)) - } else { - Stream.prototype.on.call(this, ev, fn) - } - return this -} - -Abstract.prototype.abort = function () { - this._aborted = true - this.emit('abort') -} - -Abstract.prototype.destroy = function () {} - -Abstract.prototype.warn = function (msg, code) { - var self = this - var er = decorate(msg, code, self) - if (!self.listeners('warn')) { - console.error('%s %s\n' + - 'path = %s\n' + - 'syscall = %s\n' + - 'fstream_type = %s\n' + - 'fstream_path = %s\n' + - 'fstream_unc_path = %s\n' + - 'fstream_class = %s\n' + - 'fstream_stack =\n%s\n', - code || 'UNKNOWN', - er.stack, - er.path, - er.syscall, - er.fstream_type, - er.fstream_path, - er.fstream_unc_path, - er.fstream_class, - er.fstream_stack.join('\n')) - } else { - self.emit('warn', er) - } -} - -Abstract.prototype.info = function (msg, code) { - this.emit('info', msg, code) -} - -Abstract.prototype.error = function (msg, code, th) { - var er = decorate(msg, code, this) - if (th) throw er - else this.emit('error', er) -} - -function decorate (er, code, self) { - if (!(er instanceof Error)) er = new Error(er) - er.code = er.code || code - er.path = er.path || self.path - er.fstream_type = er.fstream_type || self.type - er.fstream_path = er.fstream_path || self.path - if (self._path !== self.path) { - er.fstream_unc_path = er.fstream_unc_path || self._path - } - if (self.linkpath) { - er.fstream_linkpath = er.fstream_linkpath || self.linkpath - } - er.fstream_class = er.fstream_class || self.constructor.name - er.fstream_stack = er.fstream_stack || - new Error().stack.split(/\n/).slice(3).map(function (s) { - return s.replace(/^ {4}at /, '') - }) - - return er -} diff --git a/node_modules/fstream/lib/collect.js b/node_modules/fstream/lib/collect.js deleted file mode 100644 index e5d4f35833476..0000000000000 --- a/node_modules/fstream/lib/collect.js +++ /dev/null @@ -1,70 +0,0 @@ -module.exports = collect - -function collect (stream) { - if (stream._collected) return - - if (stream._paused) return stream.on('resume', collect.bind(null, stream)) - - stream._collected = true - stream.pause() - - stream.on('data', save) - stream.on('end', save) - var buf = [] - function save (b) { - if (typeof b === 'string') b = new Buffer(b) - if (Buffer.isBuffer(b) && !b.length) return - buf.push(b) - } - - stream.on('entry', saveEntry) - var entryBuffer = [] - function saveEntry (e) { - collect(e) - entryBuffer.push(e) - } - - stream.on('proxy', proxyPause) - function proxyPause (p) { - p.pause() - } - - // replace the pipe method with a new version that will - // unlock the buffered stuff. if you just call .pipe() - // without a destination, then it'll re-play the events. - stream.pipe = (function (orig) { - return function (dest) { - // console.error(' === open the pipes', dest && dest.path) - - // let the entries flow through one at a time. - // Once they're all done, then we can resume completely. - var e = 0 - ;(function unblockEntry () { - var entry = entryBuffer[e++] - // console.error(" ==== unblock entry", entry && entry.path) - if (!entry) return resume() - entry.on('end', unblockEntry) - if (dest) dest.add(entry) - else stream.emit('entry', entry) - })() - - function resume () { - stream.removeListener('entry', saveEntry) - stream.removeListener('data', save) - stream.removeListener('end', save) - - stream.pipe = orig - if (dest) stream.pipe(dest) - - buf.forEach(function (b) { - if (b) stream.emit('data', b) - else stream.emit('end') - }) - - stream.resume() - } - - return dest - } - })(stream.pipe) -} diff --git a/node_modules/fstream/lib/dir-reader.js b/node_modules/fstream/lib/dir-reader.js deleted file mode 100644 index 820cdc85a8e9c..0000000000000 --- a/node_modules/fstream/lib/dir-reader.js +++ /dev/null @@ -1,252 +0,0 @@ -// A thing that emits "entry" events with Reader objects -// Pausing it causes it to stop emitting entry events, and also -// pauses the current entry if there is one. - -module.exports = DirReader - -var fs = require('graceful-fs') -var inherits = require('inherits') -var path = require('path') -var Reader = require('./reader.js') -var assert = require('assert').ok - -inherits(DirReader, Reader) - -function DirReader (props) { - var self = this - if (!(self instanceof DirReader)) { - throw new Error('DirReader must be called as constructor.') - } - - // should already be established as a Directory type - if (props.type !== 'Directory' || !props.Directory) { - throw new Error('Non-directory type ' + props.type) - } - - self.entries = null - self._index = -1 - self._paused = false - self._length = -1 - - if (props.sort) { - this.sort = props.sort - } - - Reader.call(this, props) -} - -DirReader.prototype._getEntries = function () { - var self = this - - // race condition. might pause() before calling _getEntries, - // and then resume, and try to get them a second time. - if (self._gotEntries) return - self._gotEntries = true - - fs.readdir(self._path, function (er, entries) { - if (er) return self.error(er) - - self.entries = entries - - self.emit('entries', entries) - if (self._paused) self.once('resume', processEntries) - else processEntries() - - function processEntries () { - self._length = self.entries.length - if (typeof self.sort === 'function') { - self.entries = self.entries.sort(self.sort.bind(self)) - } - self._read() - } - }) -} - -// start walking the dir, and emit an "entry" event for each one. -DirReader.prototype._read = function () { - var self = this - - if (!self.entries) return self._getEntries() - - if (self._paused || self._currentEntry || self._aborted) { - // console.error('DR paused=%j, current=%j, aborted=%j', self._paused, !!self._currentEntry, self._aborted) - return - } - - self._index++ - if (self._index >= self.entries.length) { - if (!self._ended) { - self._ended = true - self.emit('end') - self.emit('close') - } - return - } - - // ok, handle this one, then. - - // save creating a proxy, by stat'ing the thing now. - var p = path.resolve(self._path, self.entries[self._index]) - assert(p !== self._path) - assert(self.entries[self._index]) - - // set this to prevent trying to _read() again in the stat time. - self._currentEntry = p - fs[ self.props.follow ? 'stat' : 'lstat' ](p, function (er, stat) { - if (er) return self.error(er) - - var who = self._proxy || self - - stat.path = p - stat.basename = path.basename(p) - stat.dirname = path.dirname(p) - var childProps = self.getChildProps.call(who, stat) - childProps.path = p - childProps.basename = path.basename(p) - childProps.dirname = path.dirname(p) - - var entry = Reader(childProps, stat) - - // console.error("DR Entry", p, stat.size) - - self._currentEntry = entry - - // "entry" events are for direct entries in a specific dir. - // "child" events are for any and all children at all levels. - // This nomenclature is not completely final. - - entry.on('pause', function (who) { - if (!self._paused && !entry._disowned) { - self.pause(who) - } - }) - - entry.on('resume', function (who) { - if (self._paused && !entry._disowned) { - self.resume(who) - } - }) - - entry.on('stat', function (props) { - self.emit('_entryStat', entry, props) - if (entry._aborted) return - if (entry._paused) { - entry.once('resume', function () { - self.emit('entryStat', entry, props) - }) - } else self.emit('entryStat', entry, props) - }) - - entry.on('ready', function EMITCHILD () { - // console.error("DR emit child", entry._path) - if (self._paused) { - // console.error(" DR emit child - try again later") - // pause the child, and emit the "entry" event once we drain. - // console.error("DR pausing child entry") - entry.pause(self) - return self.once('resume', EMITCHILD) - } - - // skip over sockets. they can't be piped around properly, - // so there's really no sense even acknowledging them. - // if someone really wants to see them, they can listen to - // the "socket" events. - if (entry.type === 'Socket') { - self.emit('socket', entry) - } else { - self.emitEntry(entry) - } - }) - - var ended = false - entry.on('close', onend) - entry.on('disown', onend) - function onend () { - if (ended) return - ended = true - self.emit('childEnd', entry) - self.emit('entryEnd', entry) - self._currentEntry = null - if (!self._paused) { - self._read() - } - } - - // XXX Remove this. Works in node as of 0.6.2 or so. - // Long filenames should not break stuff. - entry.on('error', function (er) { - if (entry._swallowErrors) { - self.warn(er) - entry.emit('end') - entry.emit('close') - } else { - self.emit('error', er) - } - }) - - // proxy up some events. - ;[ - 'child', - 'childEnd', - 'warn' - ].forEach(function (ev) { - entry.on(ev, self.emit.bind(self, ev)) - }) - }) -} - -DirReader.prototype.disown = function (entry) { - entry.emit('beforeDisown') - entry._disowned = true - entry.parent = entry.root = null - if (entry === this._currentEntry) { - this._currentEntry = null - } - entry.emit('disown') -} - -DirReader.prototype.getChildProps = function () { - return { - depth: this.depth + 1, - root: this.root || this, - parent: this, - follow: this.follow, - filter: this.filter, - sort: this.props.sort, - hardlinks: this.props.hardlinks - } -} - -DirReader.prototype.pause = function (who) { - var self = this - if (self._paused) return - who = who || self - self._paused = true - if (self._currentEntry && self._currentEntry.pause) { - self._currentEntry.pause(who) - } - self.emit('pause', who) -} - -DirReader.prototype.resume = function (who) { - var self = this - if (!self._paused) return - who = who || self - - self._paused = false - // console.error('DR Emit Resume', self._path) - self.emit('resume', who) - if (self._paused) { - // console.error('DR Re-paused', self._path) - return - } - - if (self._currentEntry) { - if (self._currentEntry.resume) self._currentEntry.resume(who) - } else self._read() -} - -DirReader.prototype.emitEntry = function (entry) { - this.emit('entry', entry) - this.emit('child', entry) -} diff --git a/node_modules/fstream/lib/dir-writer.js b/node_modules/fstream/lib/dir-writer.js deleted file mode 100644 index ec50dca900dcf..0000000000000 --- a/node_modules/fstream/lib/dir-writer.js +++ /dev/null @@ -1,174 +0,0 @@ -// It is expected that, when .add() returns false, the consumer -// of the DirWriter will pause until a "drain" event occurs. Note -// that this is *almost always going to be the case*, unless the -// thing being written is some sort of unsupported type, and thus -// skipped over. - -module.exports = DirWriter - -var Writer = require('./writer.js') -var inherits = require('inherits') -var mkdir = require('mkdirp') -var path = require('path') -var collect = require('./collect.js') - -inherits(DirWriter, Writer) - -function DirWriter (props) { - var self = this - if (!(self instanceof DirWriter)) { - self.error('DirWriter must be called as constructor.', null, true) - } - - // should already be established as a Directory type - if (props.type !== 'Directory' || !props.Directory) { - self.error('Non-directory type ' + props.type + ' ' + - JSON.stringify(props), null, true) - } - - Writer.call(this, props) -} - -DirWriter.prototype._create = function () { - var self = this - mkdir(self._path, Writer.dirmode, function (er) { - if (er) return self.error(er) - // ready to start getting entries! - self.ready = true - self.emit('ready') - self._process() - }) -} - -// a DirWriter has an add(entry) method, but its .write() doesn't -// do anything. Why a no-op rather than a throw? Because this -// leaves open the door for writing directory metadata for -// gnu/solaris style dumpdirs. -DirWriter.prototype.write = function () { - return true -} - -DirWriter.prototype.end = function () { - this._ended = true - this._process() -} - -DirWriter.prototype.add = function (entry) { - var self = this - - // console.error('\tadd', entry._path, '->', self._path) - collect(entry) - if (!self.ready || self._currentEntry) { - self._buffer.push(entry) - return false - } - - // create a new writer, and pipe the incoming entry into it. - if (self._ended) { - return self.error('add after end') - } - - self._buffer.push(entry) - self._process() - - return this._buffer.length === 0 -} - -DirWriter.prototype._process = function () { - var self = this - - // console.error('DW Process p=%j', self._processing, self.basename) - - if (self._processing) return - - var entry = self._buffer.shift() - if (!entry) { - // console.error("DW Drain") - self.emit('drain') - if (self._ended) self._finish() - return - } - - self._processing = true - // console.error("DW Entry", entry._path) - - self.emit('entry', entry) - - // ok, add this entry - // - // don't allow recursive copying - var p = entry - var pp - do { - pp = p._path || p.path - if (pp === self.root._path || pp === self._path || - (pp && pp.indexOf(self._path) === 0)) { - // console.error('DW Exit (recursive)', entry.basename, self._path) - self._processing = false - if (entry._collected) entry.pipe() - return self._process() - } - p = p.parent - } while (p) - - // console.error("DW not recursive") - - // chop off the entry's root dir, replace with ours - var props = { - parent: self, - root: self.root || self, - type: entry.type, - depth: self.depth + 1 - } - - pp = entry._path || entry.path || entry.props.path - if (entry.parent) { - pp = pp.substr(entry.parent._path.length + 1) - } - // get rid of any ../../ shenanigans - props.path = path.join(self.path, path.join('/', pp)) - - // if i have a filter, the child should inherit it. - props.filter = self.filter - - // all the rest of the stuff, copy over from the source. - Object.keys(entry.props).forEach(function (k) { - if (!props.hasOwnProperty(k)) { - props[k] = entry.props[k] - } - }) - - // not sure at this point what kind of writer this is. - var child = self._currentChild = new Writer(props) - child.on('ready', function () { - // console.error("DW Child Ready", child.type, child._path) - // console.error(" resuming", entry._path) - entry.pipe(child) - entry.resume() - }) - - // XXX Make this work in node. - // Long filenames should not break stuff. - child.on('error', function (er) { - if (child._swallowErrors) { - self.warn(er) - child.emit('end') - child.emit('close') - } else { - self.emit('error', er) - } - }) - - // we fire _end internally *after* end, so that we don't move on - // until any "end" listeners have had their chance to do stuff. - child.on('close', onend) - var ended = false - function onend () { - if (ended) return - ended = true - // console.error("* DW Child end", child.basename) - self._currentChild = null - self._processing = false - self._process() - } -} diff --git a/node_modules/fstream/lib/file-reader.js b/node_modules/fstream/lib/file-reader.js deleted file mode 100644 index baa01f4b3db7e..0000000000000 --- a/node_modules/fstream/lib/file-reader.js +++ /dev/null @@ -1,150 +0,0 @@ -// Basically just a wrapper around an fs.ReadStream - -module.exports = FileReader - -var fs = require('graceful-fs') -var inherits = require('inherits') -var Reader = require('./reader.js') -var EOF = {EOF: true} -var CLOSE = {CLOSE: true} - -inherits(FileReader, Reader) - -function FileReader (props) { - // console.error(" FR create", props.path, props.size, new Error().stack) - var self = this - if (!(self instanceof FileReader)) { - throw new Error('FileReader must be called as constructor.') - } - - // should already be established as a File type - // XXX Todo: preserve hardlinks by tracking dev+inode+nlink, - // with a HardLinkReader class. - if (!((props.type === 'Link' && props.Link) || - (props.type === 'File' && props.File))) { - throw new Error('Non-file type ' + props.type) - } - - self._buffer = [] - self._bytesEmitted = 0 - Reader.call(self, props) -} - -FileReader.prototype._getStream = function () { - var self = this - var stream = self._stream = fs.createReadStream(self._path, self.props) - - if (self.props.blksize) { - stream.bufferSize = self.props.blksize - } - - stream.on('open', self.emit.bind(self, 'open')) - - stream.on('data', function (c) { - // console.error('\t\t%d %s', c.length, self.basename) - self._bytesEmitted += c.length - // no point saving empty chunks - if (!c.length) { - return - } else if (self._paused || self._buffer.length) { - self._buffer.push(c) - self._read() - } else self.emit('data', c) - }) - - stream.on('end', function () { - if (self._paused || self._buffer.length) { - // console.error('FR Buffering End', self._path) - self._buffer.push(EOF) - self._read() - } else { - self.emit('end') - } - - if (self._bytesEmitted !== self.props.size) { - self.error("Didn't get expected byte count\n" + - 'expect: ' + self.props.size + '\n' + - 'actual: ' + self._bytesEmitted) - } - }) - - stream.on('close', function () { - if (self._paused || self._buffer.length) { - // console.error('FR Buffering Close', self._path) - self._buffer.push(CLOSE) - self._read() - } else { - // console.error('FR close 1', self._path) - self.emit('close') - } - }) - - stream.on('error', function (e) { - self.emit('error', e) - }) - - self._read() -} - -FileReader.prototype._read = function () { - var self = this - // console.error('FR _read', self._path) - if (self._paused) { - // console.error('FR _read paused', self._path) - return - } - - if (!self._stream) { - // console.error('FR _getStream calling', self._path) - return self._getStream() - } - - // clear out the buffer, if there is one. - if (self._buffer.length) { - // console.error('FR _read has buffer', self._buffer.length, self._path) - var buf = self._buffer - for (var i = 0, l = buf.length; i < l; i++) { - var c = buf[i] - if (c === EOF) { - // console.error('FR Read emitting buffered end', self._path) - self.emit('end') - } else if (c === CLOSE) { - // console.error('FR Read emitting buffered close', self._path) - self.emit('close') - } else { - // console.error('FR Read emitting buffered data', self._path) - self.emit('data', c) - } - - if (self._paused) { - // console.error('FR Read Re-pausing at '+i, self._path) - self._buffer = buf.slice(i) - return - } - } - self._buffer.length = 0 - } -// console.error("FR _read done") -// that's about all there is to it. -} - -FileReader.prototype.pause = function (who) { - var self = this - // console.error('FR Pause', self._path) - if (self._paused) return - who = who || self - self._paused = true - if (self._stream) self._stream.pause() - self.emit('pause', who) -} - -FileReader.prototype.resume = function (who) { - var self = this - // console.error('FR Resume', self._path) - if (!self._paused) return - who = who || self - self.emit('resume', who) - self._paused = false - if (self._stream) self._stream.resume() - self._read() -} diff --git a/node_modules/fstream/lib/file-writer.js b/node_modules/fstream/lib/file-writer.js deleted file mode 100644 index 4c803d8d68d2f..0000000000000 --- a/node_modules/fstream/lib/file-writer.js +++ /dev/null @@ -1,107 +0,0 @@ -module.exports = FileWriter - -var fs = require('graceful-fs') -var Writer = require('./writer.js') -var inherits = require('inherits') -var EOF = {} - -inherits(FileWriter, Writer) - -function FileWriter (props) { - var self = this - if (!(self instanceof FileWriter)) { - throw new Error('FileWriter must be called as constructor.') - } - - // should already be established as a File type - if (props.type !== 'File' || !props.File) { - throw new Error('Non-file type ' + props.type) - } - - self._buffer = [] - self._bytesWritten = 0 - - Writer.call(this, props) -} - -FileWriter.prototype._create = function () { - var self = this - if (self._stream) return - - var so = {} - if (self.props.flags) so.flags = self.props.flags - so.mode = Writer.filemode - if (self._old && self._old.blksize) so.bufferSize = self._old.blksize - - self._stream = fs.createWriteStream(self._path, so) - - self._stream.on('open', function () { - // console.error("FW open", self._buffer, self._path) - self.ready = true - self._buffer.forEach(function (c) { - if (c === EOF) self._stream.end() - else self._stream.write(c) - }) - self.emit('ready') - // give this a kick just in case it needs it. - self.emit('drain') - }) - - self._stream.on('error', function (er) { self.emit('error', er) }) - - self._stream.on('drain', function () { self.emit('drain') }) - - self._stream.on('close', function () { - // console.error('\n\nFW Stream Close', self._path, self.size) - self._finish() - }) -} - -FileWriter.prototype.write = function (c) { - var self = this - - self._bytesWritten += c.length - - if (!self.ready) { - if (!Buffer.isBuffer(c) && typeof c !== 'string') { - throw new Error('invalid write data') - } - self._buffer.push(c) - return false - } - - var ret = self._stream.write(c) - // console.error('\t-- fw wrote, _stream says', ret, self._stream._queue.length) - - // allow 2 buffered writes, because otherwise there's just too - // much stop and go bs. - if (ret === false && self._stream._queue) { - return self._stream._queue.length <= 2 - } else { - return ret - } -} - -FileWriter.prototype.end = function (c) { - var self = this - - if (c) self.write(c) - - if (!self.ready) { - self._buffer.push(EOF) - return false - } - - return self._stream.end() -} - -FileWriter.prototype._finish = function () { - var self = this - if (typeof self.size === 'number' && self._bytesWritten !== self.size) { - self.error( - 'Did not get expected byte count.\n' + - 'expect: ' + self.size + '\n' + - 'actual: ' + self._bytesWritten) - } - Writer.prototype._finish.call(self) -} diff --git a/node_modules/fstream/lib/get-type.js b/node_modules/fstream/lib/get-type.js deleted file mode 100644 index 19f6a657db847..0000000000000 --- a/node_modules/fstream/lib/get-type.js +++ /dev/null @@ -1,33 +0,0 @@ -module.exports = getType - -function getType (st) { - var types = [ - 'Directory', - 'File', - 'SymbolicLink', - 'Link', // special for hardlinks from tarballs - 'BlockDevice', - 'CharacterDevice', - 'FIFO', - 'Socket' - ] - var type - - if (st.type && types.indexOf(st.type) !== -1) { - st[st.type] = true - return st.type - } - - for (var i = 0, l = types.length; i < l; i++) { - type = types[i] - var is = st[type] || st['is' + type] - if (typeof is === 'function') is = is.call(st) - if (is) { - st[type] = true - st.type = type - return type - } - } - - return null -} diff --git a/node_modules/fstream/lib/link-reader.js b/node_modules/fstream/lib/link-reader.js deleted file mode 100644 index fb4cc67a98dc5..0000000000000 --- a/node_modules/fstream/lib/link-reader.js +++ /dev/null @@ -1,53 +0,0 @@ -// Basically just a wrapper around an fs.readlink -// -// XXX: Enhance this to support the Link type, by keeping -// a lookup table of {:}, so that hardlinks -// can be preserved in tarballs. - -module.exports = LinkReader - -var fs = require('graceful-fs') -var inherits = require('inherits') -var Reader = require('./reader.js') - -inherits(LinkReader, Reader) - -function LinkReader (props) { - var self = this - if (!(self instanceof LinkReader)) { - throw new Error('LinkReader must be called as constructor.') - } - - if (!((props.type === 'Link' && props.Link) || - (props.type === 'SymbolicLink' && props.SymbolicLink))) { - throw new Error('Non-link type ' + props.type) - } - - Reader.call(self, props) -} - -// When piping a LinkReader into a LinkWriter, we have to -// already have the linkpath property set, so that has to -// happen *before* the "ready" event, which means we need to -// override the _stat method. -LinkReader.prototype._stat = function (currentStat) { - var self = this - fs.readlink(self._path, function (er, linkpath) { - if (er) return self.error(er) - self.linkpath = self.props.linkpath = linkpath - self.emit('linkpath', linkpath) - Reader.prototype._stat.call(self, currentStat) - }) -} - -LinkReader.prototype._read = function () { - var self = this - if (self._paused) return - // basically just a no-op, since we got all the info we need - // from the _stat method - if (!self._ended) { - self.emit('end') - self.emit('close') - self._ended = true - } -} diff --git a/node_modules/fstream/lib/link-writer.js b/node_modules/fstream/lib/link-writer.js deleted file mode 100644 index af54284008faa..0000000000000 --- a/node_modules/fstream/lib/link-writer.js +++ /dev/null @@ -1,95 +0,0 @@ -module.exports = LinkWriter - -var fs = require('graceful-fs') -var Writer = require('./writer.js') -var inherits = require('inherits') -var path = require('path') -var rimraf = require('rimraf') - -inherits(LinkWriter, Writer) - -function LinkWriter (props) { - var self = this - if (!(self instanceof LinkWriter)) { - throw new Error('LinkWriter must be called as constructor.') - } - - // should already be established as a Link type - if (!((props.type === 'Link' && props.Link) || - (props.type === 'SymbolicLink' && props.SymbolicLink))) { - throw new Error('Non-link type ' + props.type) - } - - if (props.linkpath === '') props.linkpath = '.' - if (!props.linkpath) { - self.error('Need linkpath property to create ' + props.type) - } - - Writer.call(this, props) -} - -LinkWriter.prototype._create = function () { - // console.error(" LW _create") - var self = this - var hard = self.type === 'Link' || process.platform === 'win32' - var link = hard ? 'link' : 'symlink' - var lp = hard ? path.resolve(self.dirname, self.linkpath) : self.linkpath - - // can only change the link path by clobbering - // For hard links, let's just assume that's always the case, since - // there's no good way to read them if we don't already know. - if (hard) return clobber(self, lp, link) - - fs.readlink(self._path, function (er, p) { - // only skip creation if it's exactly the same link - if (p && p === lp) return finish(self) - clobber(self, lp, link) - }) -} - -function clobber (self, lp, link) { - rimraf(self._path, function (er) { - if (er) return self.error(er) - create(self, lp, link) - }) -} - -function create (self, lp, link) { - fs[link](lp, self._path, function (er) { - // if this is a hard link, and we're in the process of writing out a - // directory, it's very possible that the thing we're linking to - // doesn't exist yet (especially if it was intended as a symlink), - // so swallow ENOENT errors here and just soldier in. - // Additionally, an EPERM or EACCES can happen on win32 if it's trying - // to make a link to a directory. Again, just skip it. - // A better solution would be to have fs.symlink be supported on - // windows in some nice fashion. - if (er) { - if ((er.code === 'ENOENT' || - er.code === 'EACCES' || - er.code === 'EPERM') && process.platform === 'win32') { - self.ready = true - self.emit('ready') - self.emit('end') - self.emit('close') - self.end = self._finish = function () {} - } else return self.error(er) - } - finish(self) - }) -} - -function finish (self) { - self.ready = true - self.emit('ready') - if (self._ended && !self._finished) self._finish() -} - -LinkWriter.prototype.end = function () { - // console.error("LW finish in end") - this._ended = true - if (this.ready) { - this._finished = true - this._finish() - } -} diff --git a/node_modules/fstream/lib/proxy-reader.js b/node_modules/fstream/lib/proxy-reader.js deleted file mode 100644 index 4f431c9d9e27d..0000000000000 --- a/node_modules/fstream/lib/proxy-reader.js +++ /dev/null @@ -1,95 +0,0 @@ -// A reader for when we don't yet know what kind of thing -// the thing is. - -module.exports = ProxyReader - -var Reader = require('./reader.js') -var getType = require('./get-type.js') -var inherits = require('inherits') -var fs = require('graceful-fs') - -inherits(ProxyReader, Reader) - -function ProxyReader (props) { - var self = this - if (!(self instanceof ProxyReader)) { - throw new Error('ProxyReader must be called as constructor.') - } - - self.props = props - self._buffer = [] - self.ready = false - - Reader.call(self, props) -} - -ProxyReader.prototype._stat = function () { - var self = this - var props = self.props - // stat the thing to see what the proxy should be. - var stat = props.follow ? 'stat' : 'lstat' - - fs[stat](props.path, function (er, current) { - var type - if (er || !current) { - type = 'File' - } else { - type = getType(current) - } - - props[type] = true - props.type = self.type = type - - self._old = current - self._addProxy(Reader(props, current)) - }) -} - -ProxyReader.prototype._addProxy = function (proxy) { - var self = this - if (self._proxyTarget) { - return self.error('proxy already set') - } - - self._proxyTarget = proxy - proxy._proxy = self - - ;[ - 'error', - 'data', - 'end', - 'close', - 'linkpath', - 'entry', - 'entryEnd', - 'child', - 'childEnd', - 'warn', - 'stat' - ].forEach(function (ev) { - // console.error('~~ proxy event', ev, self.path) - proxy.on(ev, self.emit.bind(self, ev)) - }) - - self.emit('proxy', proxy) - - proxy.on('ready', function () { - // console.error("~~ proxy is ready!", self.path) - self.ready = true - self.emit('ready') - }) - - var calls = self._buffer - self._buffer.length = 0 - calls.forEach(function (c) { - proxy[c[0]].apply(proxy, c[1]) - }) -} - -ProxyReader.prototype.pause = function () { - return this._proxyTarget ? this._proxyTarget.pause() : false -} - -ProxyReader.prototype.resume = function () { - return this._proxyTarget ? this._proxyTarget.resume() : false -} diff --git a/node_modules/fstream/lib/proxy-writer.js b/node_modules/fstream/lib/proxy-writer.js deleted file mode 100644 index a6544621bfbe7..0000000000000 --- a/node_modules/fstream/lib/proxy-writer.js +++ /dev/null @@ -1,111 +0,0 @@ -// A writer for when we don't know what kind of thing -// the thing is. That is, it's not explicitly set, -// so we're going to make it whatever the thing already -// is, or "File" -// -// Until then, collect all events. - -module.exports = ProxyWriter - -var Writer = require('./writer.js') -var getType = require('./get-type.js') -var inherits = require('inherits') -var collect = require('./collect.js') -var fs = require('fs') - -inherits(ProxyWriter, Writer) - -function ProxyWriter (props) { - var self = this - if (!(self instanceof ProxyWriter)) { - throw new Error('ProxyWriter must be called as constructor.') - } - - self.props = props - self._needDrain = false - - Writer.call(self, props) -} - -ProxyWriter.prototype._stat = function () { - var self = this - var props = self.props - // stat the thing to see what the proxy should be. - var stat = props.follow ? 'stat' : 'lstat' - - fs[stat](props.path, function (er, current) { - var type - if (er || !current) { - type = 'File' - } else { - type = getType(current) - } - - props[type] = true - props.type = self.type = type - - self._old = current - self._addProxy(Writer(props, current)) - }) -} - -ProxyWriter.prototype._addProxy = function (proxy) { - // console.error("~~ set proxy", this.path) - var self = this - if (self._proxy) { - return self.error('proxy already set') - } - - self._proxy = proxy - ;[ - 'ready', - 'error', - 'close', - 'pipe', - 'drain', - 'warn' - ].forEach(function (ev) { - proxy.on(ev, self.emit.bind(self, ev)) - }) - - self.emit('proxy', proxy) - - var calls = self._buffer - calls.forEach(function (c) { - // console.error("~~ ~~ proxy buffered call", c[0], c[1]) - proxy[c[0]].apply(proxy, c[1]) - }) - self._buffer.length = 0 - if (self._needsDrain) self.emit('drain') -} - -ProxyWriter.prototype.add = function (entry) { - // console.error("~~ proxy add") - collect(entry) - - if (!this._proxy) { - this._buffer.push(['add', [entry]]) - this._needDrain = true - return false - } - return this._proxy.add(entry) -} - -ProxyWriter.prototype.write = function (c) { - // console.error('~~ proxy write') - if (!this._proxy) { - this._buffer.push(['write', [c]]) - this._needDrain = true - return false - } - return this._proxy.write(c) -} - -ProxyWriter.prototype.end = function (c) { - // console.error('~~ proxy end') - if (!this._proxy) { - this._buffer.push(['end', [c]]) - return false - } - return this._proxy.end(c) -} diff --git a/node_modules/fstream/lib/reader.js b/node_modules/fstream/lib/reader.js deleted file mode 100644 index be4f570eeb281..0000000000000 --- a/node_modules/fstream/lib/reader.js +++ /dev/null @@ -1,255 +0,0 @@ -module.exports = Reader - -var fs = require('graceful-fs') -var Stream = require('stream').Stream -var inherits = require('inherits') -var path = require('path') -var getType = require('./get-type.js') -var hardLinks = Reader.hardLinks = {} -var Abstract = require('./abstract.js') - -// Must do this *before* loading the child classes -inherits(Reader, Abstract) - -var LinkReader = require('./link-reader.js') - -function Reader (props, currentStat) { - var self = this - if (!(self instanceof Reader)) return new Reader(props, currentStat) - - if (typeof props === 'string') { - props = { path: props } - } - - // polymorphism. - // call fstream.Reader(dir) to get a DirReader object, etc. - // Note that, unlike in the Writer case, ProxyReader is going - // to be the *normal* state of affairs, since we rarely know - // the type of a file prior to reading it. - - var type - var ClassType - - if (props.type && typeof props.type === 'function') { - type = props.type - ClassType = type - } else { - type = getType(props) - ClassType = Reader - } - - if (currentStat && !type) { - type = getType(currentStat) - props[type] = true - props.type = type - } - - switch (type) { - case 'Directory': - ClassType = require('./dir-reader.js') - break - - case 'Link': - // XXX hard links are just files. - // However, it would be good to keep track of files' dev+inode - // and nlink values, and create a HardLinkReader that emits - // a linkpath value of the original copy, so that the tar - // writer can preserve them. - // ClassType = HardLinkReader - // break - - case 'File': - ClassType = require('./file-reader.js') - break - - case 'SymbolicLink': - ClassType = LinkReader - break - - case 'Socket': - ClassType = require('./socket-reader.js') - break - - case null: - ClassType = require('./proxy-reader.js') - break - } - - if (!(self instanceof ClassType)) { - return new ClassType(props) - } - - Abstract.call(self) - - if (!props.path) { - self.error('Must provide a path', null, true) - } - - self.readable = true - self.writable = false - - self.type = type - self.props = props - self.depth = props.depth = props.depth || 0 - self.parent = props.parent || null - self.root = props.root || (props.parent && props.parent.root) || self - - self._path = self.path = path.resolve(props.path) - if (process.platform === 'win32') { - self.path = self._path = self.path.replace(/\?/g, '_') - if (self._path.length >= 260) { - // how DOES one create files on the moon? - // if the path has spaces in it, then UNC will fail. - self._swallowErrors = true - // if (self._path.indexOf(" ") === -1) { - self._path = '\\\\?\\' + self.path.replace(/\//g, '\\') - // } - } - } - self.basename = props.basename = path.basename(self.path) - self.dirname = props.dirname = path.dirname(self.path) - - // these have served their purpose, and are now just noisy clutter - props.parent = props.root = null - - // console.error("\n\n\n%s setting size to", props.path, props.size) - self.size = props.size - self.filter = typeof props.filter === 'function' ? props.filter : null - if (props.sort === 'alpha') props.sort = alphasort - - // start the ball rolling. - // this will stat the thing, and then call self._read() - // to start reading whatever it is. - // console.error("calling stat", props.path, currentStat) - self._stat(currentStat) -} - -function alphasort (a, b) { - return a === b ? 0 - : a.toLowerCase() > b.toLowerCase() ? 1 - : a.toLowerCase() < b.toLowerCase() ? -1 - : a > b ? 1 - : -1 -} - -Reader.prototype._stat = function (currentStat) { - var self = this - var props = self.props - var stat = props.follow ? 'stat' : 'lstat' - // console.error("Reader._stat", self._path, currentStat) - if (currentStat) process.nextTick(statCb.bind(null, null, currentStat)) - else fs[stat](self._path, statCb) - - function statCb (er, props_) { - // console.error("Reader._stat, statCb", self._path, props_, props_.nlink) - if (er) return self.error(er) - - Object.keys(props_).forEach(function (k) { - props[k] = props_[k] - }) - - // if it's not the expected size, then abort here. - if (undefined !== self.size && props.size !== self.size) { - return self.error('incorrect size') - } - self.size = props.size - - var type = getType(props) - var handleHardlinks = props.hardlinks !== false - - // special little thing for handling hardlinks. - if (handleHardlinks && type !== 'Directory' && props.nlink && props.nlink > 1) { - var k = props.dev + ':' + props.ino - // console.error("Reader has nlink", self._path, k) - if (hardLinks[k] === self._path || !hardLinks[k]) { - hardLinks[k] = self._path - } else { - // switch into hardlink mode. - type = self.type = self.props.type = 'Link' - self.Link = self.props.Link = true - self.linkpath = self.props.linkpath = hardLinks[k] - // console.error("Hardlink detected, switching mode", self._path, self.linkpath) - // Setting __proto__ would arguably be the "correct" - // approach here, but that just seems too wrong. - self._stat = self._read = LinkReader.prototype._read - } - } - - if (self.type && self.type !== type) { - self.error('Unexpected type: ' + type) - } - - // if the filter doesn't pass, then just skip over this one. - // still have to emit end so that dir-walking can move on. - if (self.filter) { - var who = self._proxy || self - // special handling for ProxyReaders - if (!self.filter.call(who, who, props)) { - if (!self._disowned) { - self.abort() - self.emit('end') - self.emit('close') - } - return - } - } - - // last chance to abort or disown before the flow starts! - var events = ['_stat', 'stat', 'ready'] - var e = 0 - ;(function go () { - if (self._aborted) { - self.emit('end') - self.emit('close') - return - } - - if (self._paused && self.type !== 'Directory') { - self.once('resume', go) - return - } - - var ev = events[e++] - if (!ev) { - return self._read() - } - self.emit(ev, props) - go() - })() - } -} - -Reader.prototype.pipe = function (dest) { - var self = this - if (typeof dest.add === 'function') { - // piping to a multi-compatible, and we've got directory entries. - self.on('entry', function (entry) { - var ret = dest.add(entry) - if (ret === false) { - self.pause() - } - }) - } - - // console.error("R Pipe apply Stream Pipe") - return Stream.prototype.pipe.apply(this, arguments) -} - -Reader.prototype.pause = function (who) { - this._paused = true - who = who || this - this.emit('pause', who) - if (this._stream) this._stream.pause(who) -} - -Reader.prototype.resume = function (who) { - this._paused = false - who = who || this - this.emit('resume', who) - if (this._stream) this._stream.resume(who) - this._read() -} - -Reader.prototype._read = function () { - this.error('Cannot read unknown type: ' + this.type) -} diff --git a/node_modules/fstream/lib/socket-reader.js b/node_modules/fstream/lib/socket-reader.js deleted file mode 100644 index e0456ba890ede..0000000000000 --- a/node_modules/fstream/lib/socket-reader.js +++ /dev/null @@ -1,36 +0,0 @@ -// Just get the stats, and then don't do anything. -// You can't really "read" from a socket. You "connect" to it. -// Mostly, this is here so that reading a dir with a socket in it -// doesn't blow up. - -module.exports = SocketReader - -var inherits = require('inherits') -var Reader = require('./reader.js') - -inherits(SocketReader, Reader) - -function SocketReader (props) { - var self = this - if (!(self instanceof SocketReader)) { - throw new Error('SocketReader must be called as constructor.') - } - - if (!(props.type === 'Socket' && props.Socket)) { - throw new Error('Non-socket type ' + props.type) - } - - Reader.call(self, props) -} - -SocketReader.prototype._read = function () { - var self = this - if (self._paused) return - // basically just a no-op, since we got all the info we have - // from the _stat method - if (!self._ended) { - self.emit('end') - self.emit('close') - self._ended = true - } -} diff --git a/node_modules/fstream/lib/writer.js b/node_modules/fstream/lib/writer.js deleted file mode 100644 index 3f10547820fad..0000000000000 --- a/node_modules/fstream/lib/writer.js +++ /dev/null @@ -1,390 +0,0 @@ -module.exports = Writer - -var fs = require('graceful-fs') -var inherits = require('inherits') -var rimraf = require('rimraf') -var mkdir = require('mkdirp') -var path = require('path') -var umask = process.platform === 'win32' ? 0 : process.umask() -var getType = require('./get-type.js') -var Abstract = require('./abstract.js') - -// Must do this *before* loading the child classes -inherits(Writer, Abstract) - -Writer.dirmode = parseInt('0777', 8) & (~umask) -Writer.filemode = parseInt('0666', 8) & (~umask) - -var DirWriter = require('./dir-writer.js') -var LinkWriter = require('./link-writer.js') -var FileWriter = require('./file-writer.js') -var ProxyWriter = require('./proxy-writer.js') - -// props is the desired state. current is optionally the current stat, -// provided here so that subclasses can avoid statting the target -// more than necessary. -function Writer (props, current) { - var self = this - - if (typeof props === 'string') { - props = { path: props } - } - - // polymorphism. - // call fstream.Writer(dir) to get a DirWriter object, etc. - var type = getType(props) - var ClassType = Writer - - switch (type) { - case 'Directory': - ClassType = DirWriter - break - case 'File': - ClassType = FileWriter - break - case 'Link': - case 'SymbolicLink': - ClassType = LinkWriter - break - case null: - default: - // Don't know yet what type to create, so we wrap in a proxy. - ClassType = ProxyWriter - break - } - - if (!(self instanceof ClassType)) return new ClassType(props) - - // now get down to business. - - Abstract.call(self) - - if (!props.path) self.error('Must provide a path', null, true) - - // props is what we want to set. - // set some convenience properties as well. - self.type = props.type - self.props = props - self.depth = props.depth || 0 - self.clobber = props.clobber === false ? props.clobber : true - self.parent = props.parent || null - self.root = props.root || (props.parent && props.parent.root) || self - - self._path = self.path = path.resolve(props.path) - if (process.platform === 'win32') { - self.path = self._path = self.path.replace(/\?/g, '_') - if (self._path.length >= 260) { - self._swallowErrors = true - self._path = '\\\\?\\' + self.path.replace(/\//g, '\\') - } - } - self.basename = path.basename(props.path) - self.dirname = path.dirname(props.path) - self.linkpath = props.linkpath || null - - props.parent = props.root = null - - // console.error("\n\n\n%s setting size to", props.path, props.size) - self.size = props.size - - if (typeof props.mode === 'string') { - props.mode = parseInt(props.mode, 8) - } - - self.readable = false - self.writable = true - - // buffer until ready, or while handling another entry - self._buffer = [] - self.ready = false - - self.filter = typeof props.filter === 'function' ? props.filter : null - - // start the ball rolling. - // this checks what's there already, and then calls - // self._create() to call the impl-specific creation stuff. - self._stat(current) -} - -// Calling this means that it's something we can't create. -// Just assert that it's already there, otherwise raise a warning. -Writer.prototype._create = function () { - var self = this - fs[self.props.follow ? 'stat' : 'lstat'](self._path, function (er) { - if (er) { - return self.warn('Cannot create ' + self._path + '\n' + - 'Unsupported type: ' + self.type, 'ENOTSUP') - } - self._finish() - }) -} - -Writer.prototype._stat = function (current) { - var self = this - var props = self.props - var stat = props.follow ? 'stat' : 'lstat' - var who = self._proxy || self - - if (current) statCb(null, current) - else fs[stat](self._path, statCb) - - function statCb (er, current) { - if (self.filter && !self.filter.call(who, who, current)) { - self._aborted = true - self.emit('end') - self.emit('close') - return - } - - // if it's not there, great. We'll just create it. - // if it is there, then we'll need to change whatever differs - if (er || !current) { - return create(self) - } - - self._old = current - var currentType = getType(current) - - // if it's a type change, then we need to clobber or error. - // if it's not a type change, then let the impl take care of it. - if (currentType !== self.type || self.type === 'File' && current.nlink > 1) { - return rimraf(self._path, function (er) { - if (er) return self.error(er) - self._old = null - create(self) - }) - } - - // otherwise, just handle in the app-specific way - // this creates a fs.WriteStream, or mkdir's, or whatever - create(self) - } -} - -function create (self) { - // console.error("W create", self._path, Writer.dirmode) - - // XXX Need to clobber non-dirs that are in the way, - // unless { clobber: false } in the props. - mkdir(path.dirname(self._path), Writer.dirmode, function (er, made) { - // console.error("W created", path.dirname(self._path), er) - if (er) return self.error(er) - - // later on, we have to set the mode and owner for these - self._madeDir = made - return self._create() - }) -} - -function endChmod (self, want, current, path, cb) { - var wantMode = want.mode - var chmod = want.follow || self.type !== 'SymbolicLink' - ? 'chmod' : 'lchmod' - - if (!fs[chmod]) return cb() - if (typeof wantMode !== 'number') return cb() - - var curMode = current.mode & parseInt('0777', 8) - wantMode = wantMode & parseInt('0777', 8) - if (wantMode === curMode) return cb() - - fs[chmod](path, wantMode, cb) -} - -function endChown (self, want, current, path, cb) { - // Don't even try it unless root. Too easy to EPERM. - if (process.platform === 'win32') return cb() - if (!process.getuid || process.getuid() !== 0) return cb() - if (typeof want.uid !== 'number' && - typeof want.gid !== 'number') return cb() - - if (current.uid === want.uid && - current.gid === want.gid) return cb() - - var chown = (self.props.follow || self.type !== 'SymbolicLink') - ? 'chown' : 'lchown' - if (!fs[chown]) return cb() - - if (typeof want.uid !== 'number') want.uid = current.uid - if (typeof want.gid !== 'number') want.gid = current.gid - - fs[chown](path, want.uid, want.gid, cb) -} - -function endUtimes (self, want, current, path, cb) { - if (!fs.utimes || process.platform === 'win32') return cb() - - var utimes = (want.follow || self.type !== 'SymbolicLink') - ? 'utimes' : 'lutimes' - - if (utimes === 'lutimes' && !fs[utimes]) { - utimes = 'utimes' - } - - if (!fs[utimes]) return cb() - - var curA = current.atime - var curM = current.mtime - var meA = want.atime - var meM = want.mtime - - if (meA === undefined) meA = curA - if (meM === undefined) meM = curM - - if (!isDate(meA)) meA = new Date(meA) - if (!isDate(meM)) meA = new Date(meM) - - if (meA.getTime() === curA.getTime() && - meM.getTime() === curM.getTime()) return cb() - - fs[utimes](path, meA, meM, cb) -} - -// XXX This function is beastly. Break it up! -Writer.prototype._finish = function () { - var self = this - - if (self._finishing) return - self._finishing = true - - // console.error(" W Finish", self._path, self.size) - - // set up all the things. - // At this point, we're already done writing whatever we've gotta write, - // adding files to the dir, etc. - var todo = 0 - var errState = null - var done = false - - if (self._old) { - // the times will almost *certainly* have changed. - // adds the utimes syscall, but remove another stat. - self._old.atime = new Date(0) - self._old.mtime = new Date(0) - // console.error(" W Finish Stale Stat", self._path, self.size) - setProps(self._old) - } else { - var stat = self.props.follow ? 'stat' : 'lstat' - // console.error(" W Finish Stating", self._path, self.size) - fs[stat](self._path, function (er, current) { - // console.error(" W Finish Stated", self._path, self.size, current) - if (er) { - // if we're in the process of writing out a - // directory, it's very possible that the thing we're linking to - // doesn't exist yet (especially if it was intended as a symlink), - // so swallow ENOENT errors here and just soldier on. - if (er.code === 'ENOENT' && - (self.type === 'Link' || self.type === 'SymbolicLink') && - process.platform === 'win32') { - self.ready = true - self.emit('ready') - self.emit('end') - self.emit('close') - self.end = self._finish = function () {} - return - } else return self.error(er) - } - setProps(self._old = current) - }) - } - - return - - function setProps (current) { - todo += 3 - endChmod(self, self.props, current, self._path, next('chmod')) - endChown(self, self.props, current, self._path, next('chown')) - endUtimes(self, self.props, current, self._path, next('utimes')) - } - - function next (what) { - return function (er) { - // console.error(" W Finish", what, todo) - if (errState) return - if (er) { - er.fstream_finish_call = what - return self.error(errState = er) - } - if (--todo > 0) return - if (done) return - done = true - - // we may still need to set the mode/etc. on some parent dirs - // that were created previously. delay end/close until then. - if (!self._madeDir) return end() - else endMadeDir(self, self._path, end) - - function end (er) { - if (er) { - er.fstream_finish_call = 'setupMadeDir' - return self.error(er) - } - // all the props have been set, so we're completely done. - self.emit('end') - self.emit('close') - } - } - } -} - -function endMadeDir (self, p, cb) { - var made = self._madeDir - // everything *between* made and path.dirname(self._path) - // needs to be set up. Note that this may just be one dir. - var d = path.dirname(p) - - endMadeDir_(self, d, function (er) { - if (er) return cb(er) - if (d === made) { - return cb() - } - endMadeDir(self, d, cb) - }) -} - -function endMadeDir_ (self, p, cb) { - var dirProps = {} - Object.keys(self.props).forEach(function (k) { - dirProps[k] = self.props[k] - - // only make non-readable dirs if explicitly requested. - if (k === 'mode' && self.type !== 'Directory') { - dirProps[k] = dirProps[k] | parseInt('0111', 8) - } - }) - - var todo = 3 - var errState = null - fs.stat(p, function (er, current) { - if (er) return cb(errState = er) - endChmod(self, dirProps, current, p, next) - endChown(self, dirProps, current, p, next) - endUtimes(self, dirProps, current, p, next) - }) - - function next (er) { - if (errState) return - if (er) return cb(errState = er) - if (--todo === 0) return cb() - } -} - -Writer.prototype.pipe = function () { - this.error("Can't pipe from writable stream") -} - -Writer.prototype.add = function () { - this.error("Can't add to non-Directory type") -} - -Writer.prototype.write = function () { - return true -} - -function objectToString (d) { - return Object.prototype.toString.call(d) -} - -function isDate (d) { - return typeof d === 'object' && objectToString(d) === '[object Date]' -} diff --git a/node_modules/fstream/package.json b/node_modules/fstream/package.json deleted file mode 100644 index 041a4342a7164..0000000000000 --- a/node_modules/fstream/package.json +++ /dev/null @@ -1,62 +0,0 @@ -{ - "_from": "fstream@^1.0.0", - "_id": "fstream@1.0.12", - "_inBundle": false, - "_integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "_location": "/fstream", - "_phantomChildren": {}, - "_requested": { - "type": "range", - "registry": true, - "raw": "fstream@^1.0.0", - "name": "fstream", - "escapedName": "fstream", - "rawSpec": "^1.0.0", - "saveSpec": null, - "fetchSpec": "^1.0.0" - }, - "_requiredBy": [ - "/npm-lifecycle/node-gyp", - "/npm-lifecycle/tar" - ], - "_resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "_shasum": "4e8ba8ee2d48be4f7d0de505455548eae5932045", - "_spec": "fstream@^1.0.0", - "_where": "/home/hugh/Development/github.com/npm/cli/node_modules/npm-lifecycle/node_modules/node-gyp", - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me", - "url": "http://blog.izs.me/" - }, - "bugs": { - "url": "https://github.com/npm/fstream/issues" - }, - "bundleDependencies": false, - "dependencies": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - }, - "deprecated": false, - "description": "Advanced file system stream things", - "devDependencies": { - "standard": "^4.0.0", - "tap": "^1.2.0" - }, - "engines": { - "node": ">=0.6" - }, - "homepage": "https://github.com/npm/fstream#readme", - "license": "ISC", - "main": "fstream.js", - "name": "fstream", - "repository": { - "type": "git", - "url": "git+https://github.com/npm/fstream.git" - }, - "scripts": { - "test": "standard && tap examples/*.js" - }, - "version": "1.0.12" -} diff --git a/node_modules/npm-lifecycle/CHANGELOG.md b/node_modules/npm-lifecycle/CHANGELOG.md index 7e7bc92e2922e..fb74ec450c30f 100644 --- a/node_modules/npm-lifecycle/CHANGELOG.md +++ b/node_modules/npm-lifecycle/CHANGELOG.md @@ -2,6 +2,16 @@ All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines. + +## [2.1.1](https://github.com/npm/lifecycle/compare/v2.1.0...v2.1.1) (2019-05-08) + + +### Bug Fixes + +* **test:** update postinstall script for fixture ([220cd70](https://github.com/npm/lifecycle/commit/220cd70)) + + + # [2.1.0](https://github.com/npm/lifecycle/compare/v2.0.3...v2.1.0) (2018-08-13) diff --git a/node_modules/npm-lifecycle/index.js b/node_modules/npm-lifecycle/index.js index 4eb83255a94a2..4a664596047ed 100644 --- a/node_modules/npm-lifecycle/index.js +++ b/node_modules/npm-lifecycle/index.js @@ -167,7 +167,7 @@ function shouldPrependCurrentNodeDirToPATH (opts) { var isWindows = process.platform === 'win32' var foundExecPath try { - foundExecPath = which.sync(path.basename(process.execPath), {pathExt: isWindows ? ';' : ':'}) + foundExecPath = which.sync(path.basename(process.execPath), { pathExt: isWindows ? ';' : ':' }) // Apply `fs.realpath()` here to avoid false positives when `node` is a symlinked executable. isDifferentNodeInPath = fs.realpathSync(process.execPath).toUpperCase() !== fs.realpathSync(foundExecPath).toUpperCase() diff --git a/node_modules/npm-lifecycle/node_modules/.bin/node-gyp b/node_modules/npm-lifecycle/node_modules/.bin/node-gyp deleted file mode 120000 index 9b31a4fe437b3..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/.bin/node-gyp +++ /dev/null @@ -1 +0,0 @@ -../node-gyp/bin/node-gyp.js \ No newline at end of file diff --git a/node_modules/npm-lifecycle/node_modules/.bin/nopt b/node_modules/npm-lifecycle/node_modules/.bin/nopt deleted file mode 120000 index 6b6566ea7febb..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/.bin/nopt +++ /dev/null @@ -1 +0,0 @@ -../nopt/bin/nopt.js \ No newline at end of file diff --git a/node_modules/npm-lifecycle/node_modules/.bin/semver b/node_modules/npm-lifecycle/node_modules/.bin/semver deleted file mode 120000 index 317eb293d8e12..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/.bin/semver +++ /dev/null @@ -1 +0,0 @@ -../semver/bin/semver \ No newline at end of file diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/.github/ISSUE_TEMPLATE.md b/node_modules/npm-lifecycle/node_modules/node-gyp/.github/ISSUE_TEMPLATE.md deleted file mode 100644 index dbd053a90b38f..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/.github/ISSUE_TEMPLATE.md +++ /dev/null @@ -1,26 +0,0 @@ - - -* **Node Version**: -* **Platform**: -* **Compiler**: -* **Module**: - -
    Verbose output (from npm or node-gyp): - - - -``` - -``` - -
    - - - diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/.github/PULL_REQUEST_TEMPLATE.md b/node_modules/npm-lifecycle/node_modules/node-gyp/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index 10156d89af112..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,17 +0,0 @@ - - -##### Checklist - - -- [ ] `npm install && npm test` passes -- [ ] tests are included -- [ ] documentation is changed or added -- [ ] commit message follows [commit guidelines](https://github.com/nodejs/node/blob/master/doc/guides/contributing/pull-requests.md#commit-message-guidelines) - -##### Description of change - - diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/CHANGELOG.md b/node_modules/npm-lifecycle/node_modules/node-gyp/CHANGELOG.md deleted file mode 100644 index 33bbfad5dec9a..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/CHANGELOG.md +++ /dev/null @@ -1,227 +0,0 @@ -v3.8.0 2018-08-09 -================= - -* [[`c5929cb4fe`](https://github.com/nodejs/node-gyp/commit/c5929cb4fe)] - **doc**: update Xcode preferences tab name. (Ivan Daniluk) [#1330](https://github.com/nodejs/node-gyp/pull/1330) -* [[`8b488da8b9`](https://github.com/nodejs/node-gyp/commit/8b488da8b9)] - **doc**: update link to commit guidelines (Jonas Hermsmeier) [#1456](https://github.com/nodejs/node-gyp/pull/1456) -* [[`b4fe8c16f9`](https://github.com/nodejs/node-gyp/commit/b4fe8c16f9)] - **doc**: fix visual studio links (Bartosz Sosnowski) [#1490](https://github.com/nodejs/node-gyp/pull/1490) -* [[`536759c7e9`](https://github.com/nodejs/node-gyp/commit/536759c7e9)] - **configure**: use sys.version\_info to get python version (Yang Guo) [#1504](https://github.com/nodejs/node-gyp/pull/1504) -* [[`94c39c604e`](https://github.com/nodejs/node-gyp/commit/94c39c604e)] - **gyp**: fix ninja build failure (GYP patch) (Daniel Bevenius) [nodejs/node#12484](https://github.com/nodejs/node/pull/12484) -* [[`e8ea74e0fa`](https://github.com/nodejs/node-gyp/commit/e8ea74e0fa)] - **tools**: patch gyp to avoid xcrun errors (Ujjwal Sharma) [nodejs/node#21520](https://github.com/nodejs/node/pull/21520) -* [[`ea9aff44f2`](https://github.com/nodejs/node-gyp/commit/ea9aff44f2)] - **tools**: fix "the the" typos in comments (Masashi Hirano) [nodejs/node#20716](https://github.com/nodejs/node/pull/20716) -* [[`207e5aa4fd`](https://github.com/nodejs/node-gyp/commit/207e5aa4fd)] - **gyp**: implement LD/LDXX for ninja and FIPS (Sam Roberts) -* [[`b416c5f4b7`](https://github.com/nodejs/node-gyp/commit/b416c5f4b7)] - **gyp**: enable cctest to use objects (gyp part) (Daniel Bevenius) [nodejs/node#12450](https://github.com/nodejs/node/pull/12450) -* [[`40692d016b`](https://github.com/nodejs/node-gyp/commit/40692d016b)] - **gyp**: add compile\_commands.json gyp generator (Ben Noordhuis) [nodejs/node#12450](https://github.com/nodejs/node/pull/12450) -* [[`fc3c4e2b10`](https://github.com/nodejs/node-gyp/commit/fc3c4e2b10)] - **gyp**: float gyp patch for long filenames (Anna Henningsen) [nodejs/node#7963](https://github.com/nodejs/node/pull/7963) -* [[`8aedbfdef6`](https://github.com/nodejs/node-gyp/commit/8aedbfdef6)] - **gyp**: backport GYP fix to fix AIX shared suffix (Stewart Addison) -* [[`6cd84b84fc`](https://github.com/nodejs/node-gyp/commit/6cd84b84fc)] - **test**: formatting and minor fixes for execFileSync replacement (Rod Vagg) [#1521](https://github.com/nodejs/node-gyp/pull/1521) -* [[`60e421363f`](https://github.com/nodejs/node-gyp/commit/60e421363f)] - **test**: added test/processExecSync.js for when execFileSync is not available. (Rohit Hazra) [#1492](https://github.com/nodejs/node-gyp/pull/1492) -* [[`969447c5bd`](https://github.com/nodejs/node-gyp/commit/969447c5bd)] - **deps**: bump request to 2.8.7, fixes heok/hawk issues (Rohit Hazra) [#1492](https://github.com/nodejs/node-gyp/pull/1492) -* [[`340403ccfe`](https://github.com/nodejs/node-gyp/commit/340403ccfe)] - **win**: improve parsing of SDK version (Alessandro Vergani) [#1516](https://github.com/nodejs/node-gyp/pull/1516) - -v3.7.0 2018-06-08 -================= - -* [[`84cea7b30d`](https://github.com/nodejs/node-gyp/commit/84cea7b30d)] - Remove unused gyp test scripts. (Ben Noordhuis) [#1458](https://github.com/nodejs/node-gyp/pull/1458) -* [[`0540e4ec63`](https://github.com/nodejs/node-gyp/commit/0540e4ec63)] - **gyp**: escape spaces in filenames in make generator (Jeff Senn) [#1436](https://github.com/nodejs/node-gyp/pull/1436) -* [[`88fc6fa0ec`](https://github.com/nodejs/node-gyp/commit/88fc6fa0ec)] - Drop dependency on minimatch. (Brian Woodward) [#1158](https://github.com/nodejs/node-gyp/pull/1158) -* [[`1e203c5148`](https://github.com/nodejs/node-gyp/commit/1e203c5148)] - Fix include path when pointing to Node.js source (Richard Lau) [#1055](https://github.com/nodejs/node-gyp/pull/1055) -* [[`53d8cb967c`](https://github.com/nodejs/node-gyp/commit/53d8cb967c)] - Prefix build targets with /t: on Windows (Natalie Wolfe) [#1164](https://github.com/nodejs/node-gyp/pull/1164) -* [[`53a5f8ff38`](https://github.com/nodejs/node-gyp/commit/53a5f8ff38)] - **gyp**: add support for .mm files to msvs generator (Julien Racle) [#1167](https://github.com/nodejs/node-gyp/pull/1167) -* [[`dd8561e528`](https://github.com/nodejs/node-gyp/commit/dd8561e528)] - **zos**: don't use universal-new-lines mode (John Barboza) [#1451](https://github.com/nodejs/node-gyp/pull/1451) -* [[`e5a69010ed`](https://github.com/nodejs/node-gyp/commit/e5a69010ed)] - **zos**: add search locations for libnode.x (John Barboza) [#1451](https://github.com/nodejs/node-gyp/pull/1451) -* [[`79febace53`](https://github.com/nodejs/node-gyp/commit/79febace53)] - **doc**: update macOS information in README (Josh Parnham) [#1323](https://github.com/nodejs/node-gyp/pull/1323) -* [[`9425448945`](https://github.com/nodejs/node-gyp/commit/9425448945)] - **gyp**: don't print xcodebuild not found errors (Gibson Fahnestock) [#1370](https://github.com/nodejs/node-gyp/pull/1370) -* [[`6f1286f5b2`](https://github.com/nodejs/node-gyp/commit/6f1286f5b2)] - Fix infinite install loop. (Ben Noordhuis) [#1384](https://github.com/nodejs/node-gyp/pull/1384) -* [[`2580b9139e`](https://github.com/nodejs/node-gyp/commit/2580b9139e)] - Update `--nodedir` description in README. (Ben Noordhuis) [#1372](https://github.com/nodejs/node-gyp/pull/1372) -* [[`a61360391a`](https://github.com/nodejs/node-gyp/commit/a61360391a)] - Update README with another way to install on windows (JeffAtDeere) [#1352](https://github.com/nodejs/node-gyp/pull/1352) -* [[`47496bf6dc`](https://github.com/nodejs/node-gyp/commit/47496bf6dc)] - Fix IndexError when parsing GYP files. (Ben Noordhuis) [#1267](https://github.com/nodejs/node-gyp/pull/1267) -* [[`b2024dee7b`](https://github.com/nodejs/node-gyp/commit/b2024dee7b)] - **zos**: support platform (John Barboza) [#1276](https://github.com/nodejs/node-gyp/pull/1276) -* [[`90d86512f4`](https://github.com/nodejs/node-gyp/commit/90d86512f4)] - **win**: run PS with `-NoProfile` (Refael Ackermann) [#1292](https://github.com/nodejs/node-gyp/pull/1292) -* [[`2da5f86ef7`](https://github.com/nodejs/node-gyp/commit/2da5f86ef7)] - **doc**: add github PR and Issue templates (Gibson Fahnestock) [#1228](https://github.com/nodejs/node-gyp/pull/1228) -* [[`a46a770d68`](https://github.com/nodejs/node-gyp/commit/a46a770d68)] - **doc**: update proposed DCO and CoC (Mikeal Rogers) [#1229](https://github.com/nodejs/node-gyp/pull/1229) -* [[`7e803d58e0`](https://github.com/nodejs/node-gyp/commit/7e803d58e0)] - **doc**: headerify the Install instructions (Nick Schonning) [#1225](https://github.com/nodejs/node-gyp/pull/1225) -* [[`f27599193a`](https://github.com/nodejs/node-gyp/commit/f27599193a)] - **gyp**: update xml string encoding conversion (Liu Chao) [#1203](https://github.com/nodejs/node-gyp/pull/1203) -* [[`0a07e481f7`](https://github.com/nodejs/node-gyp/commit/0a07e481f7)] - **configure**: don't set ensure if tarball is set (Gibson Fahnestock) [#1220](https://github.com/nodejs/node-gyp/pull/1220) - -v3.6.3 2018-06-08 -================= - -* [[`90cd2e8da9`](https://github.com/nodejs/node-gyp/commit/90cd2e8da9)] - **gyp**: fix regex to match multi-digit versions (Jonas Hermsmeier) [#1455](https://github.com/nodejs/node-gyp/pull/1455) -* [[`7900122337`](https://github.com/nodejs/node-gyp/commit/7900122337)] - deps: pin `request` version range (Refael Ackerman) [#1300](https://github.com/nodejs/node-gyp/pull/1300) - -v3.6.2 2017-06-01 -================= - -* [[`72afdd62cd`](https://github.com/nodejs/node-gyp/commit/72afdd62cd)] - **build**: rename copyNodeLib() to doBuild() (Liu Chao) [#1206](https://github.com/nodejs/node-gyp/pull/1206) -* [[`bad903ac70`](https://github.com/nodejs/node-gyp/commit/bad903ac70)] - **win**: more robust parsing of SDK version (Refael Ackermann) [#1198](https://github.com/nodejs/node-gyp/pull/1198) -* [[`241752f381`](https://github.com/nodejs/node-gyp/commit/241752f381)] - Log dist-url. (Ben Noordhuis) [#1170](https://github.com/nodejs/node-gyp/pull/1170) -* [[`386746c7d1`](https://github.com/nodejs/node-gyp/commit/386746c7d1)] - **configure**: use full path in node_lib_file GYP var (Pavel Medvedev) [#964](https://github.com/nodejs/node-gyp/pull/964) -* [[`0913b2dd99`](https://github.com/nodejs/node-gyp/commit/0913b2dd99)] - **build, win**: use target_arch to link with node.lib (Pavel Medvedev) [#964](https://github.com/nodejs/node-gyp/pull/964) -* [[`c307b302f7`](https://github.com/nodejs/node-gyp/commit/c307b302f7)] - **doc**: blorb about setting `npm_config_OPTION_NAME` (Refael Ackermann) [#1185](https://github.com/nodejs/node-gyp/pull/1185) - -v3.6.1 2017-04-30 -================= - -* [[`49801716c2`](https://github.com/nodejs/node-gyp/commit/49801716c2)] - **test**: fix test-find-python on v0.10.x buildbot. (Ben Noordhuis) [#1172](https://github.com/nodejs/node-gyp/pull/1172) -* [[`a83a3801fc`](https://github.com/nodejs/node-gyp/commit/a83a3801fc)] - **test**: fix test/test-configure-python on AIX (Richard Lau) [#1131](https://github.com/nodejs/node-gyp/pull/1131) -* [[`8a767145c9`](https://github.com/nodejs/node-gyp/commit/8a767145c9)] - **gyp**: Revert quote_cmd workaround (Kunal Pathak) [#1153](https://github.com/nodejs/node-gyp/pull/1153) -* [[`c09cf7671e`](https://github.com/nodejs/node-gyp/commit/c09cf7671e)] - **doc**: add a note for using `configure` on Windows (Vse Mozhet Byt) [#1152](https://github.com/nodejs/node-gyp/pull/1152) -* [[`da9cb5f411`](https://github.com/nodejs/node-gyp/commit/da9cb5f411)] - Delete superfluous .patch files. (Ben Noordhuis) [#1122](https://github.com/nodejs/node-gyp/pull/1122) - -v3.6.0 2017-03-16 -================= - -* [[`ae141e1906`](https://github.com/nodejs/node-gyp/commit/ae141e1906)] - **win**: find and setup for VS2017 (Refael Ackermann) [#1130](https://github.com/nodejs/node-gyp/pull/1130) -* [[`ec5fc36a80`](https://github.com/nodejs/node-gyp/commit/ec5fc36a80)] - Add support to build node.js with chakracore for ARM. (Kunal Pathak) [#873](https://github.com/nodejs/node-gyp/pull/873) -* [[`a04ea3051a`](https://github.com/nodejs/node-gyp/commit/a04ea3051a)] - Add support to build node.js with chakracore. (Kunal Pathak) [#873](https://github.com/nodejs/node-gyp/pull/873) -* [[`93d7fa83c8`](https://github.com/nodejs/node-gyp/commit/93d7fa83c8)] - Upgrade semver dependency. (Ben Noordhuis) [#1107](https://github.com/nodejs/node-gyp/pull/1107) -* [[`ff9a6fadfd`](https://github.com/nodejs/node-gyp/commit/ff9a6fadfd)] - Update link of gyp as Google code is shutting down (Peter Dave Hello) [#1061](https://github.com/nodejs/node-gyp/pull/1061) - - -v3.5.0 2017-01-10 -================= - -* [[`762d19a39e`](https://github.com/nodejs/node-gyp/commit/762d19a39e)] - \[doc\] merge History.md and CHANGELOG.md (Rod Vagg) -* [[`80fc5c3d31`](https://github.com/nodejs/node-gyp/commit/80fc5c3d31)] - Fix deprecated dependency warning (Simone Primarosa) [#1069](https://github.com/nodejs/node-gyp/pull/1069) -* [[`05c44944fd`](https://github.com/nodejs/node-gyp/commit/05c44944fd)] - Open the build file with universal-newlines mode (Guy Margalit) [#1053](https://github.com/nodejs/node-gyp/pull/1053) -* [[`37ae7be114`](https://github.com/nodejs/node-gyp/commit/37ae7be114)] - Try python launcher when stock python is python 3. (Ben Noordhuis) [#992](https://github.com/nodejs/node-gyp/pull/992) -* [[`e3778d9907`](https://github.com/nodejs/node-gyp/commit/e3778d9907)] - Add lots of findPython() tests. (Ben Noordhuis) [#992](https://github.com/nodejs/node-gyp/pull/992) -* [[`afc766adf6`](https://github.com/nodejs/node-gyp/commit/afc766adf6)] - Unset executable bit for .bat files (Pavel Medvedev) [#969](https://github.com/nodejs/node-gyp/pull/969) -* [[`ddac348991`](https://github.com/nodejs/node-gyp/commit/ddac348991)] - Use push on PYTHONPATH and add tests (Michael Hart) [#990](https://github.com/nodejs/node-gyp/pull/990) -* [[`b182a19042`](https://github.com/nodejs/node-gyp/commit/b182a19042)] - ***Revert*** "add "path-array" dep" (Michael Hart) [#990](https://github.com/nodejs/node-gyp/pull/990) -* [[`7c08b85c5a`](https://github.com/nodejs/node-gyp/commit/7c08b85c5a)] - ***Revert*** "**configure**: use "path-array" for PYTHONPATH" (Michael Hart) [#990](https://github.com/nodejs/node-gyp/pull/990) -* [[`9c8d275526`](https://github.com/nodejs/node-gyp/commit/9c8d275526)] - Add --devdir flag. (Ben Noordhuis) [#916](https://github.com/nodejs/node-gyp/pull/916) -* [[`f6eab1f9e4`](https://github.com/nodejs/node-gyp/commit/f6eab1f9e4)] - **doc**: add windows-build-tools to readme (Felix Rieseberg) [#970](https://github.com/nodejs/node-gyp/pull/970) - -v3.4.0 2016-06-28 -================= - -* [[`ce5fd04e94`](https://github.com/nodejs/node-gyp/commit/ce5fd04e94)] - **deps**: update minimatch version (delphiactual) [#961](https://github.com/nodejs/node-gyp/pull/961) -* [[`77383ddd85`](https://github.com/nodejs/node-gyp/commit/77383ddd85)] - Replace fs.accessSync call to fs.statSync (Richard Lau) [#955](https://github.com/nodejs/node-gyp/pull/955) -* [[`0dba4bda57`](https://github.com/nodejs/node-gyp/commit/0dba4bda57)] - **test**: add simple addon test (Richard Lau) [#955](https://github.com/nodejs/node-gyp/pull/955) -* [[`c4344b3889`](https://github.com/nodejs/node-gyp/commit/c4344b3889)] - **doc**: add --target option to README (Gibson Fahnestock) [#958](https://github.com/nodejs/node-gyp/pull/958) -* [[`cc778e9215`](https://github.com/nodejs/node-gyp/commit/cc778e9215)] - Override BUILDING_UV_SHARED, BUILDING_V8_SHARED. (Ben Noordhuis) [#915](https://github.com/nodejs/node-gyp/pull/915) -* [[`af35b2ad32`](https://github.com/nodejs/node-gyp/commit/af35b2ad32)] - Move VC++ Build Tools to Build Tools landing page. (Andrew Pardoe) [#953](https://github.com/nodejs/node-gyp/pull/953) -* [[`f31482e226`](https://github.com/nodejs/node-gyp/commit/f31482e226)] - **win**: work around __pfnDliNotifyHook2 type change (Alexis Campailla) [#952](https://github.com/nodejs/node-gyp/pull/952) -* [[`3df8222fa5`](https://github.com/nodejs/node-gyp/commit/3df8222fa5)] - Allow for npmlog@3.x (Rebecca Turner) [#950](https://github.com/nodejs/node-gyp/pull/950) -* [[`a4fa07b390`](https://github.com/nodejs/node-gyp/commit/a4fa07b390)] - More verbose error on locating msbuild.exe failure. (Mateusz Jaworski) [#930](https://github.com/nodejs/node-gyp/pull/930) -* [[`4ee31329e0`](https://github.com/nodejs/node-gyp/commit/4ee31329e0)] - **doc**: add command options to README.md (Gibson Fahnestock) [#937](https://github.com/nodejs/node-gyp/pull/937) -* [[`c8c7ca86b9`](https://github.com/nodejs/node-gyp/commit/c8c7ca86b9)] - Add --silent option for zero output. (Gibson Fahnestock) [#937](https://github.com/nodejs/node-gyp/pull/937) -* [[`ac29d23a7c`](https://github.com/nodejs/node-gyp/commit/ac29d23a7c)] - Upgrade to glob@7.0.3. (Ben Noordhuis) [#943](https://github.com/nodejs/node-gyp/pull/943) -* [[`15fd56be3d`](https://github.com/nodejs/node-gyp/commit/15fd56be3d)] - Enable V8 deprecation warnings for native modules (Matt Loring) [#920](https://github.com/nodejs/node-gyp/pull/920) -* [[`7f1c1b960c`](https://github.com/nodejs/node-gyp/commit/7f1c1b960c)] - **gyp**: improvements for android generator (Robert Chiras) [#935](https://github.com/nodejs/node-gyp/pull/935) -* [[`088082766c`](https://github.com/nodejs/node-gyp/commit/088082766c)] - Update Windows install instructions (Sara Itani) [#867](https://github.com/nodejs/node-gyp/pull/867) -* [[`625c1515f9`](https://github.com/nodejs/node-gyp/commit/625c1515f9)] - **gyp**: inherit CC/CXX for CC/CXX.host (Johan Bergström) [#908](https://github.com/nodejs/node-gyp/pull/908) -* [[`3bcb1720e4`](https://github.com/nodejs/node-gyp/commit/3bcb1720e4)] - Add support for the Python launcher on Windows (Patrick Westerhoff) [#894](https://github.com/nodejs/node-gyp/pull/894 - -v3.3.1 2016-03-04 -================= - -* [[`a981ef847a`](https://github.com/nodejs/node-gyp/commit/a981ef847a)] - **gyp**: fix android generator (Robert Chiras) [#889](https://github.com/nodejs/node-gyp/pull/889) - -v3.3.0 2016-02-16 -================= - -* [[`818d854a4d`](https://github.com/nodejs/node-gyp/commit/818d854a4d)] - Introduce NODEJS_ORG_MIRROR and IOJS_ORG_MIRROR (Rod Vagg) [#878](https://github.com/nodejs/node-gyp/pull/878) -* [[`d1e4cc4b62`](https://github.com/nodejs/node-gyp/commit/d1e4cc4b62)] - **(SEMVER-MINOR)** Download headers tarball for ~0.12.10 || ~0.10.42 (Rod Vagg) [#877](https://github.com/nodejs/node-gyp/pull/877) -* [[`6e28ad1bea`](https://github.com/nodejs/node-gyp/commit/6e28ad1bea)] - Allow for npmlog@2.x (Rebecca Turner) [#861](https://github.com/nodejs/node-gyp/pull/861) -* [[`07371e5812`](https://github.com/nodejs/node-gyp/commit/07371e5812)] - Use -fPIC for NetBSD. (Marcin Cieślak) [#856](https://github.com/nodejs/node-gyp/pull/856) -* [[`8c4b0ffa50`](https://github.com/nodejs/node-gyp/commit/8c4b0ffa50)] - **(SEMVER-MINOR)** Add --cafile command line option. (Ben Noordhuis) [#837](https://github.com/nodejs/node-gyp/pull/837) -* [[`b3ad43498e`](https://github.com/nodejs/node-gyp/commit/b3ad43498e)] - **(SEMVER-MINOR)** Make download() function testable. (Ben Noordhuis) [#837](https://github.com/nodejs/node-gyp/pull/837) - -v3.2.1 2015-12-03 -================= - -* [[`ab89b477c4`](https://github.com/nodejs/node-gyp/commit/ab89b477c4)] - Upgrade gyp to b3cef02. (Ben Noordhuis) [#831](https://github.com/nodejs/node-gyp/pull/831) -* [[`90078ecb17`](https://github.com/nodejs/node-gyp/commit/90078ecb17)] - Define WIN32_LEAN_AND_MEAN conditionally. (Ben Noordhuis) [#824](https://github.com/nodejs/node-gyp/pull/824) - -v3.2.0 2015-11-25 -================= - -* [[`268f1ca4c7`](https://github.com/nodejs/node-gyp/commit/268f1ca4c7)] - Use result of `which` when searching for python. (Refael Ackermann) [#668](https://github.com/nodejs/node-gyp/pull/668) -* [[`817ed9bd78`](https://github.com/nodejs/node-gyp/commit/817ed9bd78)] - Add test for python executable search logic. (Ben Noordhuis) [#756](https://github.com/nodejs/node-gyp/pull/756) -* [[`0e2dfda1f3`](https://github.com/nodejs/node-gyp/commit/0e2dfda1f3)] - Fix test/test-options when run through `npm test`. (Ben Noordhuis) [#755](https://github.com/nodejs/node-gyp/pull/755) -* [[`9bfa0876b4`](https://github.com/nodejs/node-gyp/commit/9bfa0876b4)] - Add support for AIX (Michael Dawson) [#753](https://github.com/nodejs/node-gyp/pull/753) -* [[`a8d441a0a2`](https://github.com/nodejs/node-gyp/commit/a8d441a0a2)] - Update README for Windows 10 support. (Jason Williams) [#766](https://github.com/nodejs/node-gyp/pull/766) -* [[`d1d6015276`](https://github.com/nodejs/node-gyp/commit/d1d6015276)] - Update broken links and switch to HTTPS. (andrew morton) - -v3.1.0 2015-11-14 -================= - -* [[`9049241f91`](https://github.com/nodejs/node-gyp/commit/9049241f91)] - **gyp**: don't use links at all, just copy the files instead (Nathan Zadoks) -* [[`8ef90348d1`](https://github.com/nodejs/node-gyp/commit/8ef90348d1)] - **gyp**: apply https://codereview.chromium.org/11361103/ (Nathan Rajlich) -* [[`a2ed0df84e`](https://github.com/nodejs/node-gyp/commit/a2ed0df84e)] - **gyp**: always install into $PRODUCT_DIR (Nathan Rajlich) -* [[`cc8b2fa83e`](https://github.com/nodejs/node-gyp/commit/cc8b2fa83e)] - Update gyp to b3cef02. (Imran Iqbal) [#781](https://github.com/nodejs/node-gyp/pull/781) -* [[`f5d86eb84e`](https://github.com/nodejs/node-gyp/commit/f5d86eb84e)] - Update to tar@2.0.0. (Edgar Muentes) [#797](https://github.com/nodejs/node-gyp/pull/797) -* [[`2ac7de02c4`](https://github.com/nodejs/node-gyp/commit/2ac7de02c4)] - Fix infinite loop with zero-length options. (Ben Noordhuis) [#745](https://github.com/nodejs/node-gyp/pull/745) -* [[`101bed639b`](https://github.com/nodejs/node-gyp/commit/101bed639b)] - This platform value came from debian package, and now the value (Jérémy Lal) [#738](https://github.com/nodejs/node-gyp/pull/738) - -v3.0.3 2015-09-14 -================= - -* [[`ad827cda30`](https://github.com/nodejs/node-gyp/commit/ad827cda30)] - tarballUrl global and && when checking for iojs (Lars-Magnus Skog) [#729](https://github.com/nodejs/node-gyp/pull/729) - -v3.0.2 2015-09-12 -================= - -* [[`6e8c3bf3c6`](https://github.com/nodejs/node-gyp/commit/6e8c3bf3c6)] - add back support for passing additional cmdline args (Rod Vagg) [#723](https://github.com/nodejs/node-gyp/pull/723) -* [[`ff82f2f3b9`](https://github.com/nodejs/node-gyp/commit/ff82f2f3b9)] - fixed broken link in docs to Visual Studio 2013 download (simon-p-r) [#722](https://github.com/nodejs/node-gyp/pull/722) - -v3.0.1 2015-09-08 -================= - -* [[`846337e36b`](https://github.com/nodejs/node-gyp/commit/846337e36b)] - normalise versions for target == this comparison (Rod Vagg) [#716](https://github.com/nodejs/node-gyp/pull/716) - -v3.0.0 2015-09-08 -================= - -* [[`9720d0373c`](https://github.com/nodejs/node-gyp/commit/9720d0373c)] - remove node_modules from tree (Rod Vagg) [#711](https://github.com/nodejs/node-gyp/pull/711) -* [[`6dcf220db7`](https://github.com/nodejs/node-gyp/commit/6dcf220db7)] - test version major directly, don't use semver.satisfies() (Rod Vagg) [#711](https://github.com/nodejs/node-gyp/pull/711) -* [[`938dd18d1c`](https://github.com/nodejs/node-gyp/commit/938dd18d1c)] - refactor for clarity, fix dist-url, add env var dist-url functionality (Rod Vagg) [#711](https://github.com/nodejs/node-gyp/pull/711) -* [[`9e9df66a06`](https://github.com/nodejs/node-gyp/commit/9e9df66a06)] - use process.release, make aware of io.js & node v4 differences (Rod Vagg) [#711](https://github.com/nodejs/node-gyp/pull/711) -* [[`1ea7ed01f4`](https://github.com/nodejs/node-gyp/commit/1ea7ed01f4)] - **deps**: update graceful-fs dependency to the latest (Sakthipriyan Vairamani) [#714](https://github.com/nodejs/node-gyp/pull/714) -* [[`0fbc387b35`](https://github.com/nodejs/node-gyp/commit/0fbc387b35)] - Update repository URLs. (Ben Noordhuis) [#715](https://github.com/nodejs/node-gyp/pull/715) -* [[`bbedb8868b`](https://github.com/nodejs/node-gyp/commit/bbedb8868b)] - **(SEMVER-MAJOR)** **win**: enable delay-load hook by default (Jeremiah Senkpiel) [#708](https://github.com/nodejs/node-gyp/pull/708) -* [[`85ed107565`](https://github.com/nodejs/node-gyp/commit/85ed107565)] - Merge pull request #664 from othiym23/othiym23/allow-semver-5 (Nathan Rajlich) -* [[`0c720d234c`](https://github.com/nodejs/node-gyp/commit/0c720d234c)] - allow semver@5 (Forrest L Norvell) - -2.0.2 / 2015-07-14 -================== - - * Use HTTPS for dist url (#656, @SonicHedgehog) - * Merge pull request #648 from nevosegal/master - * Merge pull request #650 from magic890/patch-1 - * Updated Installation section on README - * Updated link to gyp user documentation - * Fix download error message spelling (#643, @tomxtobin) - * Merge pull request #637 from lygstate/master - * Set NODE_GYP_DIR for addon.gypi to setting absolute path for - src/win_delay_load_hook.c, and fixes of the long relative path issue on Win32. - Fixes #636 (#637, @lygstate). - -2.0.1 / 2015-05-28 -================== - - * configure: try/catch the semver range.test() call - * README: update for visual studio 2013 (#510, @samccone) - -2.0.0 / 2015-05-24 -================== - - * configure: check for python2 executable by default, fallback to python - * configure: don't clobber existing $PYTHONPATH - * configure: use "path-array" for PYTHONPATH - * gyp: fix for non-acsii userprofile name on Windows - * gyp: always install into $PRODUCT_DIR - * gyp: apply https://codereview.chromium.org/11361103/ - * gyp: don't use links at all, just copy the files instead - * gyp: update gyp to e1c8fcf7 - * Updated README.md with updated Windows build info - * Show URL when a download fails - * package: add a "license" field - * move HMODULE m declaration to top - * Only add "-undefined dynamic_lookup" to loadable_module targets - * win: optionally allow node.exe/iojs.exe to be renamed - * Avoid downloading shasums if using tarPath - * Add target name preprocessor define: `NODE_GYP_MODULE_NAME` - * Show better error message in case of bad network settings diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/CONTRIBUTING.md b/node_modules/npm-lifecycle/node_modules/node-gyp/CONTRIBUTING.md deleted file mode 100644 index f48786bd84af3..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/CONTRIBUTING.md +++ /dev/null @@ -1,34 +0,0 @@ -# Contributing to node-gyp - -## Code of Conduct - -Please read the -[Code of Conduct](https://github.com/nodejs/TSC/blob/master/CODE_OF_CONDUCT.md) -which explains the minimum behavior expectations for node-gyp contributors. - - -## Developer's Certificate of Origin 1.1 - -By making a contribution to this project, I certify that: - -* (a) The contribution was created in whole or in part by me and I - have the right to submit it under the open source license - indicated in the file; or - -* (b) The contribution is based upon previous work that, to the best - of my knowledge, is covered under an appropriate open source - license and I have the right under that license to submit that - work with modifications, whether created in whole or in part - by me, under the same open source license (unless I am - permitted to submit under a different license), as indicated - in the file; or - -* (c) The contribution was provided directly to me by some other - person who certified (a), (b) or (c) and I have not modified - it. - -* (d) I understand and agree that this project and the contribution - are public and that a record of the contribution (including all - personal information I submit with it, including my sign-off) is - maintained indefinitely and may be redistributed consistent with - this project or the open source license(s) involved. diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/LICENSE b/node_modules/npm-lifecycle/node_modules/node-gyp/LICENSE deleted file mode 100644 index 2ea4dc5efb872..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/LICENSE +++ /dev/null @@ -1,24 +0,0 @@ -(The MIT License) - -Copyright (c) 2012 Nathan Rajlich - -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. diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/README.md b/node_modules/npm-lifecycle/node_modules/node-gyp/README.md deleted file mode 100644 index 0fed03c54322a..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/README.md +++ /dev/null @@ -1,244 +0,0 @@ -node-gyp -========= -## Node.js native addon build tool - -`node-gyp` is a cross-platform command-line tool written in Node.js for compiling -native addon modules for Node.js. It bundles the [gyp](https://gyp.gsrc.io) -project used by the Chromium team and takes away the pain of dealing with the -various differences in build platforms. It is the replacement to the `node-waf` -program which is removed for node `v0.8`. If you have a native addon for node that -still has a `wscript` file, then you should definitely add a `binding.gyp` file -to support the latest versions of node. - -Multiple target versions of node are supported (i.e. `0.8`, ..., `4`, `5`, `6`, -etc.), regardless of what version of node is actually installed on your system -(`node-gyp` downloads the necessary development files or headers for the target version). - -## Features - - * Easy to use, consistent interface - * Same commands to build your module on every platform - * Supports multiple target versions of Node - - -Installation ------------- - -You can install with `npm`: - -``` bash -$ npm install -g node-gyp -``` - -You will also need to install: - -### On Unix - - * `python` (`v2.7` recommended, `v3.x.x` is __*not*__ supported) - * `make` - * A proper C/C++ compiler toolchain, like [GCC](https://gcc.gnu.org) - -### On macOS - - * `python` (`v2.7` recommended, `v3.x.x` is __*not*__ supported) (already installed on macOS) - * [Xcode](https://developer.apple.com/xcode/download/) - * You also need to install the `Command Line Tools` via Xcode. You can find this under the menu `Xcode -> Preferences -> Locations` (or by running `xcode-select --install` in your Terminal) - * This step will install `gcc` and the related toolchain containing `make` - -### On Windows - -#### Option 1 - -Install all the required tools and configurations using Microsoft's [windows-build-tools](https://github.com/felixrieseberg/windows-build-tools) using `npm install --global --production windows-build-tools` from an elevated PowerShell or CMD.exe (run as Administrator). - -#### Option 2 - -Install tools and configuration manually: - * Install Visual C++ Build Environment: [Visual Studio Build Tools](https://visualstudio.microsoft.com/thank-you-downloading-visual-studio/?sku=BuildTools) - (using "Visual C++ build tools" workload) or [Visual Studio 2017 Community](https://visualstudio.microsoft.com/pl/thank-you-downloading-visual-studio/?sku=Community) - (using the "Desktop development with C++" workload) - * Install [Python 2.7](https://www.python.org/downloads/) (`v3.x.x` is not supported), and run `npm config set python python2.7` (or see below for further instructions on specifying the proper Python version and path.) - * Launch cmd, `npm config set msvs_version 2017` - - If the above steps didn't work for you, please visit [Microsoft's Node.js Guidelines for Windows](https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules) for additional tips. - -If you have multiple Python versions installed, you can identify which Python -version `node-gyp` uses by setting the '--python' variable: - -``` bash -$ node-gyp --python /path/to/python2.7 -``` - -If `node-gyp` is called by way of `npm` *and* you have multiple versions of -Python installed, then you can set `npm`'s 'python' config key to the appropriate -value: - -``` bash -$ npm config set python /path/to/executable/python2.7 -``` - -How to Use ----------- - -To compile your native addon, first go to its root directory: - -``` bash -$ cd my_node_addon -``` - -The next step is to generate the appropriate project build files for the current -platform. Use `configure` for that: - -``` bash -$ node-gyp configure -``` - -Auto-detection fails for Visual C++ Build Tools 2015, so `--msvs_version=2015` -needs to be added (not needed when run by npm as configured above): -``` bash -$ node-gyp configure --msvs_version=2015 -``` - -__Note__: The `configure` step looks for the `binding.gyp` file in the current -directory to process. See below for instructions on creating the `binding.gyp` file. - -Now you will have either a `Makefile` (on Unix platforms) or a `vcxproj` file -(on Windows) in the `build/` directory. Next invoke the `build` command: - -``` bash -$ node-gyp build -``` - -Now you have your compiled `.node` bindings file! The compiled bindings end up -in `build/Debug/` or `build/Release/`, depending on the build mode. At this point -you can require the `.node` file with Node and run your tests! - -__Note:__ To create a _Debug_ build of the bindings file, pass the `--debug` (or -`-d`) switch when running either the `configure`, `build` or `rebuild` command. - - -The "binding.gyp" file ----------------------- - -Previously when node had `node-waf` you had to write a `wscript` file. The -replacement for that is the `binding.gyp` file, which describes the configuration -to build your module in a JSON-like format. This file gets placed in the root of -your package, alongside the `package.json` file. - -A barebones `gyp` file appropriate for building a node addon looks like: - -``` python -{ - "targets": [ - { - "target_name": "binding", - "sources": [ "src/binding.cc" ] - } - ] -} -``` - -Some additional resources for addons and writing `gyp` files: - - * ["Going Native" a nodeschool.io tutorial](http://nodeschool.io/#goingnative) - * ["Hello World" node addon example](https://github.com/nodejs/node/tree/master/test/addons/hello-world) - * [gyp user documentation](https://gyp.gsrc.io/docs/UserDocumentation.md) - * [gyp input format reference](https://gyp.gsrc.io/docs/InputFormatReference.md) - * [*"binding.gyp" files out in the wild* wiki page](https://github.com/nodejs/node-gyp/wiki/%22binding.gyp%22-files-out-in-the-wild) - - -Commands --------- - -`node-gyp` responds to the following commands: - -| **Command** | **Description** -|:--------------|:--------------------------------------------------------------- -| `help` | Shows the help dialog -| `build` | Invokes `make`/`msbuild.exe` and builds the native addon -| `clean` | Removes the `build` directory if it exists -| `configure` | Generates project build files for the current platform -| `rebuild` | Runs `clean`, `configure` and `build` all in a row -| `install` | Installs node header files for the given version -| `list` | Lists the currently installed node header versions -| `remove` | Removes the node header files for the given version - - -Command Options --------- - -`node-gyp` accepts the following command options: - -| **Command** | **Description** -|:----------------------------------|:------------------------------------------ -| `-j n`, `--jobs n` | Run make in parallel -| `--target=v6.2.1` | Node version to build for (default=process.version) -| `--silly`, `--loglevel=silly` | Log all progress to console -| `--verbose`, `--loglevel=verbose` | Log most progress to console -| `--silent`, `--loglevel=silent` | Don't log anything to console -| `debug`, `--debug` | Make Debug build (default=Release) -| `--release`, `--no-debug` | Make Release build -| `-C $dir`, `--directory=$dir` | Run command in different directory -| `--make=$make` | Override make command (e.g. gmake) -| `--thin=yes` | Enable thin static libraries -| `--arch=$arch` | Set target architecture (e.g. ia32) -| `--tarball=$path` | Get headers from a local tarball -| `--devdir=$path` | SDK download directory (default=~/.node-gyp) -| `--ensure` | Don't reinstall headers if already present -| `--dist-url=$url` | Download header tarball from custom URL -| `--proxy=$url` | Set HTTP proxy for downloading header tarball -| `--cafile=$cafile` | Override default CA chain (to download tarball) -| `--nodedir=$path` | Set the path to the node source code -| `--python=$path` | Set path to the python (2) binary -| `--msvs_version=$version` | Set Visual Studio version (win) -| `--solution=$solution` | Set Visual Studio Solution version (win) - - -Configuration --------- - -__`node-gyp` responds to environment variables or `npm` configuration__ -1. Environment variables take the form `npm_config_OPTION_NAME` for any of the - options listed above (dashes in option names should be replaced by underscores). - These work also when `node-gyp` is invoked directly: - `$ export npm_config_devdir=/tmp/.gyp` - or on Windows - `> set npm_config_devdir=c:\temp\.gyp` -2. As `npm` configuration, variables take the form `OPTION_NAME`. - This way only works when `node-gyp` is executed by `npm`: - `$ npm config set [--global] devdir /tmp/.gyp` - `$ npm i buffertools` - - - -License -------- - -(The MIT License) - -Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net> - -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. - - -[python-v2.7.10]: https://www.python.org/downloads/release/python-2710/ -[msvc2013]: https://www.microsoft.com/en-gb/download/details.aspx?id=44914 -[win7sdk]: https://www.microsoft.com/en-us/download/details.aspx?id=8279 -[compiler update for the Windows SDK 7.1]: https://www.microsoft.com/en-us/download/details.aspx?id=4422 diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/addon.gypi b/node_modules/npm-lifecycle/node_modules/node-gyp/addon.gypi deleted file mode 100644 index 55fb3211186f4..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/addon.gypi +++ /dev/null @@ -1,147 +0,0 @@ -{ - 'variables' : { - 'node_engine_include_dir%': 'deps/v8/include', - }, - 'target_defaults': { - 'type': 'loadable_module', - 'win_delay_load_hook': 'true', - 'product_prefix': '', - - 'conditions': [ - [ 'node_engine=="chakracore"', { - 'variables': { - 'node_engine_include_dir%': 'deps/chakrashim/include' - }, - }] - ], - - 'include_dirs': [ - '<(node_root_dir)/include/node', - '<(node_root_dir)/src', - '<(node_root_dir)/deps/openssl/config', - '<(node_root_dir)/deps/openssl/openssl/include', - '<(node_root_dir)/deps/uv/include', - '<(node_root_dir)/deps/zlib', - '<(node_root_dir)/<(node_engine_include_dir)' - ], - 'defines!': [ - 'BUILDING_UV_SHARED=1', # Inherited from common.gypi. - 'BUILDING_V8_SHARED=1', # Inherited from common.gypi. - ], - 'defines': [ - 'NODE_GYP_MODULE_NAME=>(_target_name)', - 'USING_UV_SHARED=1', - 'USING_V8_SHARED=1', - # Warn when using deprecated V8 APIs. - 'V8_DEPRECATION_WARNINGS=1' - ], - - 'target_conditions': [ - ['_type=="loadable_module"', { - 'product_extension': 'node', - 'defines': [ - 'BUILDING_NODE_EXTENSION' - ], - 'xcode_settings': { - 'OTHER_LDFLAGS': [ - '-undefined dynamic_lookup' - ], - }, - }], - - ['_type=="static_library"', { - # set to `1` to *disable* the -T thin archive 'ld' flag. - # older linkers don't support this flag. - 'standalone_static_library': '<(standalone_static_library)' - }], - - ['_win_delay_load_hook=="true"', { - # If the addon specifies `'win_delay_load_hook': 'true'` in its - # binding.gyp, link a delay-load hook into the DLL. This hook ensures - # that the addon will work regardless of whether the node/iojs binary - # is named node.exe, iojs.exe, or something else. - 'conditions': [ - [ 'OS=="win"', { - 'sources': [ - '<(node_gyp_dir)/src/win_delay_load_hook.cc', - ], - 'msvs_settings': { - 'VCLinkerTool': { - 'DelayLoadDLLs': [ 'iojs.exe', 'node.exe' ], - # Don't print a linker warning when no imports from either .exe - # are used. - 'AdditionalOptions': [ '/ignore:4199' ], - }, - }, - }], - ], - }], - ], - - 'conditions': [ - [ 'OS=="mac"', { - 'defines': [ - '_DARWIN_USE_64_BIT_INODE=1' - ], - 'xcode_settings': { - 'DYLIB_INSTALL_NAME_BASE': '@rpath' - }, - }], - [ 'OS=="aix"', { - 'ldflags': [ - '-Wl,-bimport:<(node_exp_file)' - ], - }], - [ 'OS=="zos"', { - 'cflags': [ - '-q64', - '-Wc,DLL', - '-qlonglong' - ], - 'ldflags': [ - '-q64', - '<(node_exp_file)' - ], - }], - [ 'OS=="win"', { - 'conditions': [ - ['node_engine=="chakracore"', { - 'library_dirs': [ '<(node_root_dir)/$(ConfigurationName)' ], - 'libraries': [ '<@(node_engine_libs)' ], - }], - ], - 'libraries': [ - '-lkernel32.lib', - '-luser32.lib', - '-lgdi32.lib', - '-lwinspool.lib', - '-lcomdlg32.lib', - '-ladvapi32.lib', - '-lshell32.lib', - '-lole32.lib', - '-loleaut32.lib', - '-luuid.lib', - '-lodbc32.lib', - '-lDelayImp.lib', - '-l"<(node_lib_file)"' - ], - 'msvs_disabled_warnings': [ - # warning C4251: 'node::ObjectWrap::handle_' : class 'v8::Persistent' - # needs to have dll-interface to be used by - # clients of class 'node::ObjectWrap' - 4251 - ], - }, { - # OS!="win" - 'defines': [ - '_LARGEFILE_SOURCE', - '_FILE_OFFSET_BITS=64' - ], - }], - [ 'OS in "freebsd openbsd netbsd solaris" or \ - (OS=="linux" and target_arch!="ia32")', { - 'cflags': [ '-fPIC' ], - }] - ] - } -} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/bin/node-gyp.js b/node_modules/npm-lifecycle/node_modules/node-gyp/bin/node-gyp.js deleted file mode 100755 index 70d7d502628bc..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/bin/node-gyp.js +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env node - -/** - * Set the title. - */ - -process.title = 'node-gyp' - -/** - * Module dependencies. - */ - -var gyp = require('../') -var log = require('npmlog') -var osenv = require('osenv') -var path = require('path') - -/** - * Process and execute the selected commands. - */ - -var prog = gyp() -var completed = false -prog.parseArgv(process.argv) -prog.devDir = prog.opts.devdir - -var homeDir = osenv.home() -if (prog.devDir) { - prog.devDir = prog.devDir.replace(/^~/, homeDir) -} else if (homeDir) { - prog.devDir = path.resolve(homeDir, '.node-gyp') -} else { - throw new Error( - "node-gyp requires that the user's home directory is specified " + - "in either of the environmental variables HOME or USERPROFILE. " + - "Overide with: --devdir /path/to/.node-gyp") -} - -if (prog.todo.length === 0) { - if (~process.argv.indexOf('-v') || ~process.argv.indexOf('--version')) { - console.log('v%s', prog.version) - } else { - console.log('%s', prog.usage()) - } - return process.exit(0) -} - -log.info('it worked if it ends with', 'ok') -log.verbose('cli', process.argv) -log.info('using', 'node-gyp@%s', prog.version) -log.info('using', 'node@%s | %s | %s', process.versions.node, process.platform, process.arch) - - -/** - * Change dir if -C/--directory was passed. - */ - -var dir = prog.opts.directory -if (dir) { - var fs = require('fs') - try { - var stat = fs.statSync(dir) - if (stat.isDirectory()) { - log.info('chdir', dir) - process.chdir(dir) - } else { - log.warn('chdir', dir + ' is not a directory') - } - } catch (e) { - if (e.code === 'ENOENT') { - log.warn('chdir', dir + ' is not a directory') - } else { - log.warn('chdir', 'error during chdir() "%s"', e.message) - } - } -} - -function run () { - var command = prog.todo.shift() - if (!command) { - // done! - completed = true - log.info('ok') - return - } - - prog.commands[command.name](command.args, function (err) { - if (err) { - log.error(command.name + ' error') - log.error('stack', err.stack) - errorMessage() - log.error('not ok') - return process.exit(1) - } - if (command.name == 'list') { - var versions = arguments[1] - if (versions.length > 0) { - versions.forEach(function (version) { - console.log(version) - }) - } else { - console.log('No node development files installed. Use `node-gyp install` to install a version.') - } - } else if (arguments.length >= 2) { - console.log.apply(console, [].slice.call(arguments, 1)) - } - - // now run the next command in the queue - process.nextTick(run) - }) -} - -process.on('exit', function (code) { - if (!completed && !code) { - log.error('Completion callback never invoked!') - issueMessage() - process.exit(6) - } -}) - -process.on('uncaughtException', function (err) { - log.error('UNCAUGHT EXCEPTION') - log.error('stack', err.stack) - issueMessage() - process.exit(7) -}) - -function errorMessage () { - // copied from npm's lib/util/error-handler.js - var os = require('os') - log.error('System', os.type() + ' ' + os.release()) - log.error('command', process.argv - .map(JSON.stringify).join(' ')) - log.error('cwd', process.cwd()) - log.error('node -v', process.version) - log.error('node-gyp -v', 'v' + prog.package.version) -} - -function issueMessage () { - errorMessage() - log.error('', [ 'This is a bug in `node-gyp`.' - , 'Try to update node-gyp and file an Issue if it does not help:' - , ' ' - ].join('\n')) -} - -// start running the given commands! -run() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/AUTHORS b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/AUTHORS deleted file mode 100644 index d76d8cd7683f2..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/AUTHORS +++ /dev/null @@ -1,13 +0,0 @@ -# Names should be added to this file like so: -# Name or Organization - -Google Inc. <*@google.com> -Bloomberg Finance L.P. <*@bloomberg.net> -IBM Inc. <*@*.ibm.com> -Yandex LLC <*@yandex-team.ru> - -Steven Knight -Ryan Norton -David J. Sankel -Eric N. Vander Weele -Tom Freudenberg diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/DEPS b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/DEPS deleted file mode 100644 index 2e1120f274687..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/DEPS +++ /dev/null @@ -1,24 +0,0 @@ -# DEPS file for gclient use in buildbot execution of gyp tests. -# -# (You don't need to use gclient for normal GYP development work.) - -vars = { - "chrome_trunk": "http://src.chromium.org/svn/trunk", - "googlecode_url": "http://%s.googlecode.com/svn", -} - -deps = { -} - -deps_os = { - "win": { - "third_party/cygwin": - Var("chrome_trunk") + "/deps/third_party/cygwin@66844", - - "third_party/python_26": - Var("chrome_trunk") + "/tools/third_party/python_26@89111", - - "src/third_party/pefile": - (Var("googlecode_url") % "pefile") + "/trunk@63", - }, -} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/LICENSE b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/LICENSE deleted file mode 100644 index ab6b011a10933..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/LICENSE +++ /dev/null @@ -1,27 +0,0 @@ -Copyright (c) 2009 Google Inc. All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are -met: - - * Redistributions of source code must retain the above copyright -notice, this list of conditions and the following disclaimer. - * 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. - * Neither the name of Google Inc. nor the names of its -contributors may be used to endorse or promote products derived from -this software without specific prior written permission. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT -OWNER 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/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/OWNERS b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/OWNERS deleted file mode 100644 index 72e8ffc0db8aa..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/OWNERS +++ /dev/null @@ -1 +0,0 @@ -* diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/PRESUBMIT.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/PRESUBMIT.py deleted file mode 100644 index f6c8a357afe14..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/PRESUBMIT.py +++ /dev/null @@ -1,139 +0,0 @@ -# Copyright (c) 2012 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. - - -"""Top-level presubmit script for GYP. - -See http://dev.chromium.org/developers/how-tos/depottools/presubmit-scripts -for more details about the presubmit API built into gcl. -""" - - -PYLINT_BLACKLIST = [ - # TODO: fix me. - # From SCons, not done in google style. - 'test/lib/TestCmd.py', - 'test/lib/TestCommon.py', - 'test/lib/TestGyp.py', -] - - -PYLINT_DISABLED_WARNINGS = [ - # TODO: fix me. - # Many tests include modules they don't use. - 'W0611', - # Possible unbalanced tuple unpacking with sequence. - 'W0632', - # Attempting to unpack a non-sequence. - 'W0633', - # Include order doesn't properly include local files? - 'F0401', - # Some use of built-in names. - 'W0622', - # Some unused variables. - 'W0612', - # Operator not preceded/followed by space. - 'C0323', - 'C0322', - # Unnecessary semicolon. - 'W0301', - # Unused argument. - 'W0613', - # String has no effect (docstring in wrong place). - 'W0105', - # map/filter on lambda could be replaced by comprehension. - 'W0110', - # Use of eval. - 'W0123', - # Comma not followed by space. - 'C0324', - # Access to a protected member. - 'W0212', - # Bad indent. - 'W0311', - # Line too long. - 'C0301', - # Undefined variable. - 'E0602', - # Not exception type specified. - 'W0702', - # No member of that name. - 'E1101', - # Dangerous default {}. - 'W0102', - # Cyclic import. - 'R0401', - # Others, too many to sort. - 'W0201', 'W0232', 'E1103', 'W0621', 'W0108', 'W0223', 'W0231', - 'R0201', 'E0101', 'C0321', - # ************* Module copy - # W0104:427,12:_test.odict.__setitem__: Statement seems to have no effect - 'W0104', -] - - -def _LicenseHeader(input_api): - # Accept any year number from 2009 to the current year. - current_year = int(input_api.time.strftime('%Y')) - allowed_years = (str(s) for s in reversed(xrange(2009, current_year + 1))) - - years_re = '(' + '|'.join(allowed_years) + ')' - - # The (c) is deprecated, but tolerate it until it's removed from all files. - return ( - r'.*? Copyright (\(c\) )?%(year)s Google Inc\. All rights reserved\.\n' - r'.*? Use of this source code is governed by a BSD-style license that ' - r'can be\n' - r'.*? found in the LICENSE file\.\n' - ) % { - 'year': years_re, - } - -def CheckChangeOnUpload(input_api, output_api): - report = [] - report.extend(input_api.canned_checks.PanProjectChecks( - input_api, output_api, license_header=_LicenseHeader(input_api))) - return report - - -def CheckChangeOnCommit(input_api, output_api): - report = [] - - report.extend(input_api.canned_checks.PanProjectChecks( - input_api, output_api, license_header=_LicenseHeader(input_api))) - report.extend(input_api.canned_checks.CheckTreeIsOpen( - 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=blacklist, - disabled_warnings=PYLINT_DISABLED_WARNINGS)) - finally: - sys.path = old_sys_path - return report - - -TRYBOTS = [ - 'linux_try', - 'mac_try', - 'win_try', -] - - -def GetPreferredTryMasters(_, change): - return { - 'client.gyp': { t: set(['defaulttests']) for t in TRYBOTS }, - } diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/codereview.settings b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/codereview.settings deleted file mode 100644 index faf37f1145f17..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/codereview.settings +++ /dev/null @@ -1,10 +0,0 @@ -# This file is used by gcl to get repository specific information. -CODE_REVIEW_SERVER: codereview.chromium.org -CC_LIST: gyp-developer@googlegroups.com -VIEW_VC: https://chromium.googlesource.com/external/gyp/+/ -TRY_ON_UPLOAD: False -TRYSERVER_PROJECT: gyp -TRYSERVER_PATCHLEVEL: 1 -TRYSERVER_ROOT: gyp -TRYSERVER_SVN_URL: svn://svn.chromium.org/chrome-try/try-nacl -PROJECT: gyp diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc deleted file mode 100644 index 8bca510815e0a..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/data/win/large-pdb-shim.cc +++ /dev/null @@ -1,12 +0,0 @@ -// 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. - -// This file is used to generate an empty .pdb -- with a 4KB pagesize -- that is -// then used during the final link for modules that have large PDBs. Otherwise, -// the linker will generate a pdb with a page size of 1KB, which imposes a limit -// of 1GB on the .pdb. By generating an initial empty .pdb with the compiler -// (rather than the linker), this limit is avoided. With this in place PDBs may -// grow to 2GB. -// -// This file is referenced by the msvs_large_pdb mechanism in MSVSUtil.py. diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp deleted file mode 100755 index 1b8b9bdfb05f5..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp +++ /dev/null @@ -1,8 +0,0 @@ -#!/bin/sh -# Copyright 2013 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -set -e -base=$(dirname "$0") -exec python "${base}/gyp_main.py" "$@" diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp.bat b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp.bat deleted file mode 100644 index c0b4ca24e5df0..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp.bat +++ /dev/null @@ -1,5 +0,0 @@ -@rem Copyright (c) 2009 Google Inc. All rights reserved. -@rem Use of this source code is governed by a BSD-style license that can be -@rem found in the LICENSE file. - -@python "%~dp0gyp_main.py" %* diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp_main.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp_main.py deleted file mode 100755 index 25a6eba94aae7..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/gyp_main.py +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 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. - -import os -import sys - -# Make sure we're using the version of pylib in this repo, not one installed -# elsewhere on the system. -sys.path.insert(0, os.path.join(os.path.dirname(sys.argv[0]), 'pylib')) -import gyp - -if __name__ == '__main__': - sys.exit(gyp.script_main()) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py deleted file mode 100644 index 593f0e5b0b2e8..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSNew.py +++ /dev/null @@ -1,340 +0,0 @@ -# Copyright (c) 2012 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. - -"""New implementation of Visual Studio project generation.""" - -import os -import random - -import gyp.common - -# hashlib is supplied as of Python 2.5 as the replacement interface for md5 -# and other secure hashes. In 2.6, md5 is deprecated. Import hashlib if -# available, avoiding a deprecation warning under 2.6. Import md5 otherwise, -# preserving 2.4 compatibility. -try: - import hashlib - _new_md5 = hashlib.md5 -except ImportError: - import md5 - _new_md5 = md5.new - - -# Initialize random number generator -random.seed() - -# GUIDs for project types -ENTRY_TYPE_GUIDS = { - 'project': '{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}', - 'folder': '{2150E333-8FDC-42A3-9474-1A3956D46DE8}', -} - -#------------------------------------------------------------------------------ -# Helper functions - - -def MakeGuid(name, seed='msvs_new'): - """Returns a GUID for the specified target name. - - Args: - name: Target name. - seed: Seed for MD5 hash. - Returns: - A GUID-line string calculated from the name and seed. - - This generates something which looks like a GUID, but depends only on the - name and seed. This means the same name/seed will always generate the same - GUID, so that projects and solutions which refer to each other can explicitly - determine the GUID to refer to explicitly. It also means that the GUID will - not change when the project for a target is rebuilt. - """ - # Calculate a MD5 signature for the seed and name. - d = _new_md5(str(seed) + str(name)).hexdigest().upper() - # Convert most of the signature to GUID form (discard the rest) - guid = ('{' + d[:8] + '-' + d[8:12] + '-' + d[12:16] + '-' + d[16:20] - + '-' + d[20:32] + '}') - return guid - -#------------------------------------------------------------------------------ - - -class MSVSSolutionEntry(object): - def __cmp__(self, other): - # Sort by name then guid (so things are in order on vs2008). - return cmp((self.name, self.get_guid()), (other.name, other.get_guid())) - - -class MSVSFolder(MSVSSolutionEntry): - """Folder in a Visual Studio project or solution.""" - - def __init__(self, path, name = None, entries = None, - guid = None, items = None): - """Initializes the folder. - - Args: - path: Full path to the folder. - name: Name of the folder. - entries: List of folder entries to nest inside this folder. May contain - Folder or Project objects. May be None, if the folder is empty. - guid: GUID to use for folder, if not None. - items: List of solution items to include in the folder project. May be - None, if the folder does not directly contain items. - """ - if name: - self.name = name - else: - # Use last layer. - self.name = os.path.basename(path) - - self.path = path - self.guid = guid - - # Copy passed lists (or set to empty lists) - self.entries = sorted(list(entries or [])) - self.items = list(items or []) - - self.entry_type_guid = ENTRY_TYPE_GUIDS['folder'] - - def get_guid(self): - if self.guid is None: - # Use consistent guids for folders (so things don't regenerate). - self.guid = MakeGuid(self.path, seed='msvs_folder') - return self.guid - - -#------------------------------------------------------------------------------ - - -class MSVSProject(MSVSSolutionEntry): - """Visual Studio project.""" - - def __init__(self, path, name = None, dependencies = None, guid = None, - spec = None, build_file = None, config_platform_overrides = None, - fixpath_prefix = None): - """Initializes the project. - - Args: - path: Absolute path to the project file. - name: Name of project. If None, the name will be the same as the base - name of the project file. - dependencies: List of other Project objects this project is dependent - upon, if not None. - guid: GUID to use for project, if not None. - spec: Dictionary specifying how to build this project. - build_file: Filename of the .gyp file that the vcproj file comes from. - config_platform_overrides: optional dict of configuration platforms to - used in place of the default for this target. - fixpath_prefix: the path used to adjust the behavior of _fixpath - """ - self.path = path - self.guid = guid - self.spec = spec - self.build_file = build_file - # Use project filename if name not specified - self.name = name or os.path.splitext(os.path.basename(path))[0] - - # Copy passed lists (or set to empty lists) - self.dependencies = list(dependencies or []) - - self.entry_type_guid = ENTRY_TYPE_GUIDS['project'] - - if config_platform_overrides: - self.config_platform_overrides = config_platform_overrides - else: - self.config_platform_overrides = {} - self.fixpath_prefix = fixpath_prefix - self.msbuild_toolset = None - - def set_dependencies(self, dependencies): - self.dependencies = list(dependencies or []) - - def get_guid(self): - if self.guid is None: - # Set GUID from path - # TODO(rspangler): This is fragile. - # 1. We can't just use the project filename sans path, since there could - # be multiple projects with the same base name (for example, - # foo/unittest.vcproj and bar/unittest.vcproj). - # 2. The path needs to be relative to $SOURCE_ROOT, so that the project - # GUID is the same whether it's included from base/base.sln or - # foo/bar/baz/baz.sln. - # 3. The GUID needs to be the same each time this builder is invoked, so - # that we don't need to rebuild the solution when the project changes. - # 4. We should be able to handle pre-built project files by reading the - # GUID from the files. - self.guid = MakeGuid(self.name) - return self.guid - - def set_msbuild_toolset(self, msbuild_toolset): - self.msbuild_toolset = msbuild_toolset - -#------------------------------------------------------------------------------ - - -class MSVSSolution(object): - """Visual Studio solution.""" - - def __init__(self, path, version, entries=None, variants=None, - websiteProperties=True): - """Initializes the solution. - - Args: - path: Path to solution file. - version: Format version to emit. - entries: List of entries in solution. May contain Folder or Project - objects. May be None, if the folder is empty. - variants: List of build variant strings. If none, a default list will - be used. - websiteProperties: Flag to decide if the website properties section - is generated. - """ - self.path = path - self.websiteProperties = websiteProperties - self.version = version - - # Copy passed lists (or set to empty lists) - self.entries = list(entries or []) - - if variants: - # Copy passed list - self.variants = variants[:] - else: - # Use default - self.variants = ['Debug|Win32', 'Release|Win32'] - # TODO(rspangler): Need to be able to handle a mapping of solution config - # to project config. Should we be able to handle variants being a dict, - # or add a separate variant_map variable? If it's a dict, we can't - # guarantee the order of variants since dict keys aren't ordered. - - - # TODO(rspangler): Automatically write to disk for now; should delay until - # node-evaluation time. - self.Write() - - - def Write(self, writer=gyp.common.WriteOnDiff): - """Writes the solution file to disk. - - Raises: - IndexError: An entry appears multiple times. - """ - # Walk the entry tree and collect all the folders and projects. - all_entries = set() - entries_to_check = self.entries[:] - while entries_to_check: - e = entries_to_check.pop(0) - - # If this entry has been visited, nothing to do. - if e in all_entries: - continue - - all_entries.add(e) - - # If this is a folder, check its entries too. - if isinstance(e, MSVSFolder): - entries_to_check += e.entries - - all_entries = sorted(all_entries) - - # Open file and print header - f = writer(self.path) - f.write('Microsoft Visual Studio Solution File, ' - 'Format Version %s\r\n' % self.version.SolutionVersion()) - f.write('# %s\r\n' % self.version.Description()) - - # Project entries - sln_root = os.path.split(self.path)[0] - for e in all_entries: - relative_path = gyp.common.RelativePath(e.path, sln_root) - # msbuild does not accept an empty folder_name. - # use '.' in case relative_path is empty. - folder_name = relative_path.replace('/', '\\') or '.' - f.write('Project("%s") = "%s", "%s", "%s"\r\n' % ( - e.entry_type_guid, # Entry type GUID - e.name, # Folder name - folder_name, # Folder name (again) - e.get_guid(), # Entry GUID - )) - - # TODO(rspangler): Need a way to configure this stuff - if self.websiteProperties: - f.write('\tProjectSection(WebsiteProperties) = preProject\r\n' - '\t\tDebug.AspNetCompiler.Debug = "True"\r\n' - '\t\tRelease.AspNetCompiler.Debug = "False"\r\n' - '\tEndProjectSection\r\n') - - if isinstance(e, MSVSFolder): - if e.items: - f.write('\tProjectSection(SolutionItems) = preProject\r\n') - for i in e.items: - f.write('\t\t%s = %s\r\n' % (i, i)) - f.write('\tEndProjectSection\r\n') - - if isinstance(e, MSVSProject): - if e.dependencies: - f.write('\tProjectSection(ProjectDependencies) = postProject\r\n') - for d in e.dependencies: - f.write('\t\t%s = %s\r\n' % (d.get_guid(), d.get_guid())) - f.write('\tEndProjectSection\r\n') - - f.write('EndProject\r\n') - - # Global section - f.write('Global\r\n') - - # Configurations (variants) - f.write('\tGlobalSection(SolutionConfigurationPlatforms) = preSolution\r\n') - for v in self.variants: - f.write('\t\t%s = %s\r\n' % (v, v)) - f.write('\tEndGlobalSection\r\n') - - # Sort config guids for easier diffing of solution changes. - config_guids = [] - config_guids_overrides = {} - for e in all_entries: - if isinstance(e, MSVSProject): - config_guids.append(e.get_guid()) - config_guids_overrides[e.get_guid()] = e.config_platform_overrides - config_guids.sort() - - f.write('\tGlobalSection(ProjectConfigurationPlatforms) = postSolution\r\n') - for g in config_guids: - for v in self.variants: - nv = config_guids_overrides[g].get(v, v) - # Pick which project configuration to build for this solution - # configuration. - f.write('\t\t%s.%s.ActiveCfg = %s\r\n' % ( - g, # Project GUID - v, # Solution build configuration - nv, # Project build config for that solution config - )) - - # Enable project in this solution configuration. - f.write('\t\t%s.%s.Build.0 = %s\r\n' % ( - g, # Project GUID - v, # Solution build configuration - nv, # Project build config for that solution config - )) - f.write('\tEndGlobalSection\r\n') - - # TODO(rspangler): Should be able to configure this stuff too (though I've - # never seen this be any different) - f.write('\tGlobalSection(SolutionProperties) = preSolution\r\n') - f.write('\t\tHideSolutionNode = FALSE\r\n') - f.write('\tEndGlobalSection\r\n') - - # Folder mappings - # Omit this section if there are no folders - if any([e.entries for e in all_entries if isinstance(e, MSVSFolder)]): - f.write('\tGlobalSection(NestedProjects) = preSolution\r\n') - for e in all_entries: - if not isinstance(e, MSVSFolder): - continue # Does not apply to projects, only folders - for subentry in e.entries: - f.write('\t\t%s = %s\r\n' % (subentry.get_guid(), e.get_guid())) - f.write('\tEndGlobalSection\r\n') - - f.write('EndGlobal\r\n') - - f.close() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py deleted file mode 100644 index db1ceede344c6..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSProject.py +++ /dev/null @@ -1,208 +0,0 @@ -# Copyright (c) 2012 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. - -"""Visual Studio project reader/writer.""" - -import gyp.common -import gyp.easy_xml as easy_xml - -#------------------------------------------------------------------------------ - - -class Tool(object): - """Visual Studio tool.""" - - def __init__(self, name, attrs=None): - """Initializes the tool. - - Args: - name: Tool name. - attrs: Dict of tool attributes; may be None. - """ - self._attrs = attrs or {} - self._attrs['Name'] = name - - def _GetSpecification(self): - """Creates an element for the tool. - - Returns: - A new xml.dom.Element for the tool. - """ - return ['Tool', self._attrs] - -class Filter(object): - """Visual Studio filter - that is, a virtual folder.""" - - def __init__(self, name, contents=None): - """Initializes the folder. - - Args: - name: Filter (folder) name. - contents: List of filenames and/or Filter objects contained. - """ - self.name = name - self.contents = list(contents or []) - - -#------------------------------------------------------------------------------ - - -class Writer(object): - """Visual Studio XML project writer.""" - - def __init__(self, project_path, version, name, guid=None, platforms=None): - """Initializes the project. - - Args: - project_path: Path to the project file. - version: Format version to emit. - name: Name of the project. - guid: GUID to use for project, if not None. - platforms: Array of string, the supported platforms. If null, ['Win32'] - """ - self.project_path = project_path - self.version = version - self.name = name - self.guid = guid - - # Default to Win32 for platforms. - if not platforms: - platforms = ['Win32'] - - # Initialize the specifications of the various sections. - self.platform_section = ['Platforms'] - for platform in platforms: - self.platform_section.append(['Platform', {'Name': platform}]) - self.tool_files_section = ['ToolFiles'] - self.configurations_section = ['Configurations'] - self.files_section = ['Files'] - - # Keep a dict keyed on filename to speed up access. - self.files_dict = dict() - - def AddToolFile(self, path): - """Adds a tool file to the project. - - Args: - path: Relative path from project to tool file. - """ - self.tool_files_section.append(['ToolFile', {'RelativePath': path}]) - - def _GetSpecForConfiguration(self, config_type, config_name, attrs, tools): - """Returns the specification for a configuration. - - Args: - config_type: Type of configuration node. - config_name: Configuration name. - attrs: Dict of configuration attributes; may be None. - tools: List of tools (strings or Tool objects); may be None. - Returns: - """ - # Handle defaults - if not attrs: - attrs = {} - if not tools: - tools = [] - - # Add configuration node and its attributes - node_attrs = attrs.copy() - node_attrs['Name'] = config_name - specification = [config_type, node_attrs] - - # Add tool nodes and their attributes - if tools: - for t in tools: - if isinstance(t, Tool): - specification.append(t._GetSpecification()) - else: - specification.append(Tool(t)._GetSpecification()) - return specification - - - def AddConfig(self, name, attrs=None, tools=None): - """Adds a configuration to the project. - - Args: - name: Configuration name. - attrs: Dict of configuration attributes; may be None. - tools: List of tools (strings or Tool objects); may be None. - """ - spec = self._GetSpecForConfiguration('Configuration', name, attrs, tools) - self.configurations_section.append(spec) - - def _AddFilesToNode(self, parent, files): - """Adds files and/or filters to the parent node. - - Args: - parent: Destination node - files: A list of Filter objects and/or relative paths to files. - - Will call itself recursively, if the files list contains Filter objects. - """ - for f in files: - if isinstance(f, Filter): - node = ['Filter', {'Name': f.name}] - self._AddFilesToNode(node, f.contents) - else: - node = ['File', {'RelativePath': f}] - self.files_dict[f] = node - parent.append(node) - - def AddFiles(self, files): - """Adds files to the project. - - Args: - files: A list of Filter objects and/or relative paths to files. - - This makes a copy of the file/filter tree at the time of this call. If you - later add files to a Filter object which was passed into a previous call - to AddFiles(), it will not be reflected in this project. - """ - self._AddFilesToNode(self.files_section, files) - # TODO(rspangler) This also doesn't handle adding files to an existing - # filter. That is, it doesn't merge the trees. - - def AddFileConfig(self, path, config, attrs=None, tools=None): - """Adds a configuration to a file. - - Args: - path: Relative path to the file. - config: Name of configuration to add. - attrs: Dict of configuration attributes; may be None. - tools: List of tools (strings or Tool objects); may be None. - - Raises: - ValueError: Relative path does not match any file added via AddFiles(). - """ - # Find the file node with the right relative path - parent = self.files_dict.get(path) - if not parent: - raise ValueError('AddFileConfig: file "%s" not in project.' % path) - - # Add the config to the file node - spec = self._GetSpecForConfiguration('FileConfiguration', config, attrs, - tools) - parent.append(spec) - - def WriteIfChanged(self): - """Writes the project file.""" - # First create XML content definition - content = [ - 'VisualStudioProject', - {'ProjectType': 'Visual C++', - 'Version': self.version.ProjectVersion(), - 'Name': self.name, - 'ProjectGUID': self.guid, - 'RootNamespace': self.name, - 'Keyword': 'Win32Proj' - }, - self.platform_section, - self.tool_files_section, - self.configurations_section, - ['References'], # empty section - self.files_section, - ['Globals'] # empty section - ] - easy_xml.WriteXmlIfChanged(content, self.project_path, - encoding="Windows-1252") diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py deleted file mode 100644 index a08cc154d7398..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings.py +++ /dev/null @@ -1,1096 +0,0 @@ -# Copyright (c) 2012 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. - -r"""Code to validate and convert settings of the Microsoft build tools. - -This file contains code to validate and convert settings of the Microsoft -build tools. The function ConvertToMSBuildSettings(), ValidateMSVSSettings(), -and ValidateMSBuildSettings() are the entry points. - -This file was created by comparing the projects created by Visual Studio 2008 -and Visual Studio 2010 for all available settings through the user interface. -The MSBuild schemas were also considered. They are typically found in the -MSBuild install directory, e.g. c:\Program Files (x86)\MSBuild -""" - -import sys -import re - -# Dictionaries of settings validators. The key is the tool name, the value is -# a dictionary mapping setting names to validation functions. -_msvs_validators = {} -_msbuild_validators = {} - - -# A dictionary of settings converters. The key is the tool name, the value is -# a dictionary mapping setting names to conversion functions. -_msvs_to_msbuild_converters = {} - - -# Tool name mapping from MSVS to MSBuild. -_msbuild_name_of_tool = {} - - -class _Tool(object): - """Represents a tool used by MSVS or MSBuild. - - Attributes: - msvs_name: The name of the tool in MSVS. - msbuild_name: The name of the tool in MSBuild. - """ - - def __init__(self, msvs_name, msbuild_name): - self.msvs_name = msvs_name - self.msbuild_name = msbuild_name - - -def _AddTool(tool): - """Adds a tool to the four dictionaries used to process settings. - - This only defines the tool. Each setting also needs to be added. - - Args: - tool: The _Tool object to be added. - """ - _msvs_validators[tool.msvs_name] = {} - _msbuild_validators[tool.msbuild_name] = {} - _msvs_to_msbuild_converters[tool.msvs_name] = {} - _msbuild_name_of_tool[tool.msvs_name] = tool.msbuild_name - - -def _GetMSBuildToolSettings(msbuild_settings, tool): - """Returns an MSBuild tool dictionary. Creates it if needed.""" - return msbuild_settings.setdefault(tool.msbuild_name, {}) - - -class _Type(object): - """Type of settings (Base class).""" - - def ValidateMSVS(self, value): - """Verifies that the value is legal for MSVS. - - Args: - value: the value to check for this type. - - Raises: - ValueError if value is not valid for MSVS. - """ - - def ValidateMSBuild(self, value): - """Verifies that the value is legal for MSBuild. - - Args: - value: the value to check for this type. - - Raises: - ValueError if value is not valid for MSBuild. - """ - - def ConvertToMSBuild(self, value): - """Returns the MSBuild equivalent of the MSVS value given. - - Args: - value: the MSVS value to convert. - - Returns: - the MSBuild equivalent. - - Raises: - ValueError if value is not valid. - """ - return value - - -class _String(_Type): - """A setting that's just a string.""" - - def ValidateMSVS(self, value): - if not isinstance(value, basestring): - raise ValueError('expected string; got %r' % value) - - def ValidateMSBuild(self, value): - if not isinstance(value, basestring): - raise ValueError('expected string; got %r' % value) - - def ConvertToMSBuild(self, value): - # Convert the macros - return ConvertVCMacrosToMSBuild(value) - - -class _StringList(_Type): - """A settings that's a list of strings.""" - - def ValidateMSVS(self, value): - if not isinstance(value, basestring) and not isinstance(value, list): - raise ValueError('expected string list; got %r' % value) - - def ValidateMSBuild(self, value): - if not isinstance(value, basestring) and not isinstance(value, list): - raise ValueError('expected string list; got %r' % value) - - def ConvertToMSBuild(self, value): - # Convert the macros - if isinstance(value, list): - return [ConvertVCMacrosToMSBuild(i) for i in value] - else: - return ConvertVCMacrosToMSBuild(value) - - -class _Boolean(_Type): - """Boolean settings, can have the values 'false' or 'true'.""" - - def _Validate(self, value): - if value != 'true' and value != 'false': - raise ValueError('expected bool; got %r' % value) - - def ValidateMSVS(self, value): - self._Validate(value) - - def ValidateMSBuild(self, value): - self._Validate(value) - - def ConvertToMSBuild(self, value): - self._Validate(value) - return value - - -class _Integer(_Type): - """Integer settings.""" - - def __init__(self, msbuild_base=10): - _Type.__init__(self) - self._msbuild_base = msbuild_base - - def ValidateMSVS(self, value): - # Try to convert, this will raise ValueError if invalid. - self.ConvertToMSBuild(value) - - def ValidateMSBuild(self, value): - # Try to convert, this will raise ValueError if invalid. - int(value, self._msbuild_base) - - def ConvertToMSBuild(self, value): - msbuild_format = (self._msbuild_base == 10) and '%d' or '0x%04x' - return msbuild_format % int(value) - - -class _Enumeration(_Type): - """Type of settings that is an enumeration. - - In MSVS, the values are indexes like '0', '1', and '2'. - MSBuild uses text labels that are more representative, like 'Win32'. - - Constructor args: - label_list: an array of MSBuild labels that correspond to the MSVS index. - In the rare cases where MSVS has skipped an index value, None is - used in the array to indicate the unused spot. - new: an array of labels that are new to MSBuild. - """ - - def __init__(self, label_list, new=None): - _Type.__init__(self) - self._label_list = label_list - self._msbuild_values = set(value for value in label_list - if value is not None) - if new is not None: - self._msbuild_values.update(new) - - def ValidateMSVS(self, value): - # Try to convert. It will raise an exception if not valid. - self.ConvertToMSBuild(value) - - def ValidateMSBuild(self, value): - if value not in self._msbuild_values: - raise ValueError('unrecognized enumerated value %s' % value) - - def ConvertToMSBuild(self, value): - index = int(value) - if index < 0 or index >= len(self._label_list): - raise ValueError('index value (%d) not in expected range [0, %d)' % - (index, len(self._label_list))) - label = self._label_list[index] - if label is None: - raise ValueError('converted value for %s not specified.' % value) - return label - - -# Instantiate the various generic types. -_boolean = _Boolean() -_integer = _Integer() -# For now, we don't do any special validation on these types: -_string = _String() -_file_name = _String() -_folder_name = _String() -_file_list = _StringList() -_folder_list = _StringList() -_string_list = _StringList() -# Some boolean settings went from numerical values to boolean. The -# mapping is 0: default, 1: false, 2: true. -_newly_boolean = _Enumeration(['', 'false', 'true']) - - -def _Same(tool, name, setting_type): - """Defines a setting that has the same name in MSVS and MSBuild. - - Args: - tool: a dictionary that gives the names of the tool for MSVS and MSBuild. - name: the name of the setting. - setting_type: the type of this setting. - """ - _Renamed(tool, name, name, setting_type) - - -def _Renamed(tool, msvs_name, msbuild_name, setting_type): - """Defines a setting for which the name has changed. - - Args: - tool: a dictionary that gives the names of the tool for MSVS and MSBuild. - msvs_name: the name of the MSVS setting. - msbuild_name: the name of the MSBuild setting. - setting_type: the type of this setting. - """ - - def _Translate(value, msbuild_settings): - msbuild_tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool) - msbuild_tool_settings[msbuild_name] = setting_type.ConvertToMSBuild(value) - - _msvs_validators[tool.msvs_name][msvs_name] = setting_type.ValidateMSVS - _msbuild_validators[tool.msbuild_name][msbuild_name] = ( - setting_type.ValidateMSBuild) - _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate - - -def _Moved(tool, settings_name, msbuild_tool_name, setting_type): - _MovedAndRenamed(tool, settings_name, msbuild_tool_name, settings_name, - setting_type) - - -def _MovedAndRenamed(tool, msvs_settings_name, msbuild_tool_name, - msbuild_settings_name, setting_type): - """Defines a setting that may have moved to a new section. - - Args: - tool: a dictionary that gives the names of the tool for MSVS and MSBuild. - msvs_settings_name: the MSVS name of the setting. - msbuild_tool_name: the name of the MSBuild tool to place the setting under. - msbuild_settings_name: the MSBuild name of the setting. - setting_type: the type of this setting. - """ - - def _Translate(value, msbuild_settings): - tool_settings = msbuild_settings.setdefault(msbuild_tool_name, {}) - tool_settings[msbuild_settings_name] = setting_type.ConvertToMSBuild(value) - - _msvs_validators[tool.msvs_name][msvs_settings_name] = ( - setting_type.ValidateMSVS) - validator = setting_type.ValidateMSBuild - _msbuild_validators[msbuild_tool_name][msbuild_settings_name] = validator - _msvs_to_msbuild_converters[tool.msvs_name][msvs_settings_name] = _Translate - - -def _MSVSOnly(tool, name, setting_type): - """Defines a setting that is only found in MSVS. - - Args: - tool: a dictionary that gives the names of the tool for MSVS and MSBuild. - name: the name of the setting. - setting_type: the type of this setting. - """ - - def _Translate(unused_value, unused_msbuild_settings): - # Since this is for MSVS only settings, no translation will happen. - pass - - _msvs_validators[tool.msvs_name][name] = setting_type.ValidateMSVS - _msvs_to_msbuild_converters[tool.msvs_name][name] = _Translate - - -def _MSBuildOnly(tool, name, setting_type): - """Defines a setting that is only found in MSBuild. - - Args: - tool: a dictionary that gives the names of the tool for MSVS and MSBuild. - name: the name of the setting. - setting_type: the type of this setting. - """ - - def _Translate(value, msbuild_settings): - # Let msbuild-only properties get translated as-is from msvs_settings. - tool_settings = msbuild_settings.setdefault(tool.msbuild_name, {}) - tool_settings[name] = value - - _msbuild_validators[tool.msbuild_name][name] = setting_type.ValidateMSBuild - _msvs_to_msbuild_converters[tool.msvs_name][name] = _Translate - - -def _ConvertedToAdditionalOption(tool, msvs_name, flag): - """Defines a setting that's handled via a command line option in MSBuild. - - Args: - tool: a dictionary that gives the names of the tool for MSVS and MSBuild. - msvs_name: the name of the MSVS setting that if 'true' becomes a flag - flag: the flag to insert at the end of the AdditionalOptions - """ - - def _Translate(value, msbuild_settings): - if value == 'true': - tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool) - if 'AdditionalOptions' in tool_settings: - new_flags = '%s %s' % (tool_settings['AdditionalOptions'], flag) - else: - new_flags = flag - tool_settings['AdditionalOptions'] = new_flags - _msvs_validators[tool.msvs_name][msvs_name] = _boolean.ValidateMSVS - _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate - - -def _CustomGeneratePreprocessedFile(tool, msvs_name): - def _Translate(value, msbuild_settings): - tool_settings = _GetMSBuildToolSettings(msbuild_settings, tool) - if value == '0': - tool_settings['PreprocessToFile'] = 'false' - tool_settings['PreprocessSuppressLineNumbers'] = 'false' - elif value == '1': # /P - tool_settings['PreprocessToFile'] = 'true' - tool_settings['PreprocessSuppressLineNumbers'] = 'false' - elif value == '2': # /EP /P - tool_settings['PreprocessToFile'] = 'true' - tool_settings['PreprocessSuppressLineNumbers'] = 'true' - else: - raise ValueError('value must be one of [0, 1, 2]; got %s' % value) - # Create a bogus validator that looks for '0', '1', or '2' - msvs_validator = _Enumeration(['a', 'b', 'c']).ValidateMSVS - _msvs_validators[tool.msvs_name][msvs_name] = msvs_validator - msbuild_validator = _boolean.ValidateMSBuild - msbuild_tool_validators = _msbuild_validators[tool.msbuild_name] - msbuild_tool_validators['PreprocessToFile'] = msbuild_validator - msbuild_tool_validators['PreprocessSuppressLineNumbers'] = msbuild_validator - _msvs_to_msbuild_converters[tool.msvs_name][msvs_name] = _Translate - - -fix_vc_macro_slashes_regex_list = ('IntDir', 'OutDir') -fix_vc_macro_slashes_regex = re.compile( - r'(\$\((?:%s)\))(?:[\\/]+)' % "|".join(fix_vc_macro_slashes_regex_list) -) - -# Regular expression to detect keys that were generated by exclusion lists -_EXCLUDED_SUFFIX_RE = re.compile('^(.*)_excluded$') - - -def _ValidateExclusionSetting(setting, settings, error_msg, stderr=sys.stderr): - """Verify that 'setting' is valid if it is generated from an exclusion list. - - If the setting appears to be generated from an exclusion list, the root name - is checked. - - Args: - setting: A string that is the setting name to validate - settings: A dictionary where the keys are valid settings - error_msg: The message to emit in the event of error - stderr: The stream receiving the error messages. - """ - # This may be unrecognized because it's an exclusion list. If the - # setting name has the _excluded suffix, then check the root name. - unrecognized = True - m = re.match(_EXCLUDED_SUFFIX_RE, setting) - if m: - root_setting = m.group(1) - unrecognized = root_setting not in settings - - if unrecognized: - # We don't know this setting. Give a warning. - print >> stderr, error_msg - - -def FixVCMacroSlashes(s): - """Replace macros which have excessive following slashes. - - These macros are known to have a built-in trailing slash. Furthermore, many - scripts hiccup on processing paths with extra slashes in the middle. - - This list is probably not exhaustive. Add as needed. - """ - if '$' in s: - s = fix_vc_macro_slashes_regex.sub(r'\1', s) - return s - - -def ConvertVCMacrosToMSBuild(s): - """Convert the MSVS macros found in the string to the MSBuild equivalent. - - This list is probably not exhaustive. Add as needed. - """ - if '$' in s: - replace_map = { - '$(ConfigurationName)': '$(Configuration)', - '$(InputDir)': '%(RelativeDir)', - '$(InputExt)': '%(Extension)', - '$(InputFileName)': '%(Filename)%(Extension)', - '$(InputName)': '%(Filename)', - '$(InputPath)': '%(Identity)', - '$(ParentName)': '$(ProjectFileName)', - '$(PlatformName)': '$(Platform)', - '$(SafeInputName)': '%(Filename)', - } - for old, new in replace_map.iteritems(): - s = s.replace(old, new) - s = FixVCMacroSlashes(s) - return s - - -def ConvertToMSBuildSettings(msvs_settings, stderr=sys.stderr): - """Converts MSVS settings (VS2008 and earlier) to MSBuild settings (VS2010+). - - Args: - msvs_settings: A dictionary. The key is the tool name. The values are - themselves dictionaries of settings and their values. - stderr: The stream receiving the error messages. - - Returns: - A dictionary of MSBuild settings. The key is either the MSBuild tool name - or the empty string (for the global settings). The values are themselves - dictionaries of settings and their values. - """ - msbuild_settings = {} - for msvs_tool_name, msvs_tool_settings in msvs_settings.iteritems(): - if msvs_tool_name in _msvs_to_msbuild_converters: - msvs_tool = _msvs_to_msbuild_converters[msvs_tool_name] - for msvs_setting, msvs_value in msvs_tool_settings.iteritems(): - if msvs_setting in msvs_tool: - # Invoke the translation function. - try: - msvs_tool[msvs_setting](msvs_value, msbuild_settings) - except ValueError, e: - print >> stderr, ('Warning: while converting %s/%s to MSBuild, ' - '%s' % (msvs_tool_name, msvs_setting, e)) - else: - _ValidateExclusionSetting(msvs_setting, - msvs_tool, - ('Warning: unrecognized setting %s/%s ' - 'while converting to MSBuild.' % - (msvs_tool_name, msvs_setting)), - stderr) - else: - print >> stderr, ('Warning: unrecognized tool %s while converting to ' - 'MSBuild.' % msvs_tool_name) - return msbuild_settings - - -def ValidateMSVSSettings(settings, stderr=sys.stderr): - """Validates that the names of the settings are valid for MSVS. - - Args: - settings: A dictionary. The key is the tool name. The values are - themselves dictionaries of settings and their values. - stderr: The stream receiving the error messages. - """ - _ValidateSettings(_msvs_validators, settings, stderr) - - -def ValidateMSBuildSettings(settings, stderr=sys.stderr): - """Validates that the names of the settings are valid for MSBuild. - - Args: - settings: A dictionary. The key is the tool name. The values are - themselves dictionaries of settings and their values. - stderr: The stream receiving the error messages. - """ - _ValidateSettings(_msbuild_validators, settings, stderr) - - -def _ValidateSettings(validators, settings, stderr): - """Validates that the settings are valid for MSBuild or MSVS. - - We currently only validate the names of the settings, not their values. - - Args: - validators: A dictionary of tools and their validators. - settings: A dictionary. The key is the tool name. The values are - themselves dictionaries of settings and their values. - stderr: The stream receiving the error messages. - """ - for tool_name in settings: - if tool_name in validators: - tool_validators = validators[tool_name] - for setting, value in settings[tool_name].iteritems(): - if setting in tool_validators: - try: - tool_validators[setting](value) - except ValueError, e: - print >> stderr, ('Warning: for %s/%s, %s' % - (tool_name, setting, e)) - else: - _ValidateExclusionSetting(setting, - tool_validators, - ('Warning: unrecognized setting %s/%s' % - (tool_name, setting)), - stderr) - - else: - print >> stderr, ('Warning: unrecognized tool %s' % tool_name) - - -# MSVS and MBuild names of the tools. -_compile = _Tool('VCCLCompilerTool', 'ClCompile') -_link = _Tool('VCLinkerTool', 'Link') -_midl = _Tool('VCMIDLTool', 'Midl') -_rc = _Tool('VCResourceCompilerTool', 'ResourceCompile') -_lib = _Tool('VCLibrarianTool', 'Lib') -_manifest = _Tool('VCManifestTool', 'Manifest') -_masm = _Tool('MASM', 'MASM') - - -_AddTool(_compile) -_AddTool(_link) -_AddTool(_midl) -_AddTool(_rc) -_AddTool(_lib) -_AddTool(_manifest) -_AddTool(_masm) -# Add sections only found in the MSBuild settings. -_msbuild_validators[''] = {} -_msbuild_validators['ProjectReference'] = {} -_msbuild_validators['ManifestResourceCompile'] = {} - -# Descriptions of the compiler options, i.e. VCCLCompilerTool in MSVS and -# ClCompile in MSBuild. -# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\cl.xml" for -# the schema of the MSBuild ClCompile settings. - -# Options that have the same name in MSVS and MSBuild -_Same(_compile, 'AdditionalIncludeDirectories', _folder_list) # /I -_Same(_compile, 'AdditionalOptions', _string_list) -_Same(_compile, 'AdditionalUsingDirectories', _folder_list) # /AI -_Same(_compile, 'AssemblerListingLocation', _file_name) # /Fa -_Same(_compile, 'BrowseInformationFile', _file_name) -_Same(_compile, 'BufferSecurityCheck', _boolean) # /GS -_Same(_compile, 'DisableLanguageExtensions', _boolean) # /Za -_Same(_compile, 'DisableSpecificWarnings', _string_list) # /wd -_Same(_compile, 'EnableFiberSafeOptimizations', _boolean) # /GT -_Same(_compile, 'EnablePREfast', _boolean) # /analyze Visible='false' -_Same(_compile, 'ExpandAttributedSource', _boolean) # /Fx -_Same(_compile, 'FloatingPointExceptions', _boolean) # /fp:except -_Same(_compile, 'ForceConformanceInForLoopScope', _boolean) # /Zc:forScope -_Same(_compile, 'ForcedIncludeFiles', _file_list) # /FI -_Same(_compile, 'ForcedUsingFiles', _file_list) # /FU -_Same(_compile, 'GenerateXMLDocumentationFiles', _boolean) # /doc -_Same(_compile, 'IgnoreStandardIncludePath', _boolean) # /X -_Same(_compile, 'MinimalRebuild', _boolean) # /Gm -_Same(_compile, 'OmitDefaultLibName', _boolean) # /Zl -_Same(_compile, 'OmitFramePointers', _boolean) # /Oy -_Same(_compile, 'PreprocessorDefinitions', _string_list) # /D -_Same(_compile, 'ProgramDataBaseFileName', _file_name) # /Fd -_Same(_compile, 'RuntimeTypeInfo', _boolean) # /GR -_Same(_compile, 'ShowIncludes', _boolean) # /showIncludes -_Same(_compile, 'SmallerTypeCheck', _boolean) # /RTCc -_Same(_compile, 'StringPooling', _boolean) # /GF -_Same(_compile, 'SuppressStartupBanner', _boolean) # /nologo -_Same(_compile, 'TreatWChar_tAsBuiltInType', _boolean) # /Zc:wchar_t -_Same(_compile, 'UndefineAllPreprocessorDefinitions', _boolean) # /u -_Same(_compile, 'UndefinePreprocessorDefinitions', _string_list) # /U -_Same(_compile, 'UseFullPaths', _boolean) # /FC -_Same(_compile, 'WholeProgramOptimization', _boolean) # /GL -_Same(_compile, 'XMLDocumentationFileName', _file_name) - -_Same(_compile, 'AssemblerOutput', - _Enumeration(['NoListing', - 'AssemblyCode', # /FA - 'All', # /FAcs - 'AssemblyAndMachineCode', # /FAc - 'AssemblyAndSourceCode'])) # /FAs -_Same(_compile, 'BasicRuntimeChecks', - _Enumeration(['Default', - 'StackFrameRuntimeCheck', # /RTCs - 'UninitializedLocalUsageCheck', # /RTCu - 'EnableFastChecks'])) # /RTC1 -_Same(_compile, 'BrowseInformation', - _Enumeration(['false', - 'true', # /FR - 'true'])) # /Fr -_Same(_compile, 'CallingConvention', - _Enumeration(['Cdecl', # /Gd - 'FastCall', # /Gr - 'StdCall', # /Gz - 'VectorCall'])) # /Gv -_Same(_compile, 'CompileAs', - _Enumeration(['Default', - 'CompileAsC', # /TC - 'CompileAsCpp'])) # /TP -_Same(_compile, 'DebugInformationFormat', - _Enumeration(['', # Disabled - 'OldStyle', # /Z7 - None, - 'ProgramDatabase', # /Zi - 'EditAndContinue'])) # /ZI -_Same(_compile, 'EnableEnhancedInstructionSet', - _Enumeration(['NotSet', - 'StreamingSIMDExtensions', # /arch:SSE - 'StreamingSIMDExtensions2', # /arch:SSE2 - 'AdvancedVectorExtensions', # /arch:AVX (vs2012+) - 'NoExtensions', # /arch:IA32 (vs2012+) - # This one only exists in the new msbuild format. - 'AdvancedVectorExtensions2', # /arch:AVX2 (vs2013r2+) - ])) -_Same(_compile, 'ErrorReporting', - _Enumeration(['None', # /errorReport:none - 'Prompt', # /errorReport:prompt - 'Queue'], # /errorReport:queue - new=['Send'])) # /errorReport:send" -_Same(_compile, 'ExceptionHandling', - _Enumeration(['false', - 'Sync', # /EHsc - 'Async'], # /EHa - new=['SyncCThrow'])) # /EHs -_Same(_compile, 'FavorSizeOrSpeed', - _Enumeration(['Neither', - 'Speed', # /Ot - 'Size'])) # /Os -_Same(_compile, 'FloatingPointModel', - _Enumeration(['Precise', # /fp:precise - 'Strict', # /fp:strict - 'Fast'])) # /fp:fast -_Same(_compile, 'InlineFunctionExpansion', - _Enumeration(['Default', - 'OnlyExplicitInline', # /Ob1 - 'AnySuitable'], # /Ob2 - new=['Disabled'])) # /Ob0 -_Same(_compile, 'Optimization', - _Enumeration(['Disabled', # /Od - 'MinSpace', # /O1 - 'MaxSpeed', # /O2 - 'Full'])) # /Ox -_Same(_compile, 'RuntimeLibrary', - _Enumeration(['MultiThreaded', # /MT - 'MultiThreadedDebug', # /MTd - 'MultiThreadedDLL', # /MD - 'MultiThreadedDebugDLL'])) # /MDd -_Same(_compile, 'StructMemberAlignment', - _Enumeration(['Default', - '1Byte', # /Zp1 - '2Bytes', # /Zp2 - '4Bytes', # /Zp4 - '8Bytes', # /Zp8 - '16Bytes'])) # /Zp16 -_Same(_compile, 'WarningLevel', - _Enumeration(['TurnOffAllWarnings', # /W0 - 'Level1', # /W1 - 'Level2', # /W2 - 'Level3', # /W3 - 'Level4'], # /W4 - new=['EnableAllWarnings'])) # /Wall - -# Options found in MSVS that have been renamed in MSBuild. -_Renamed(_compile, 'EnableFunctionLevelLinking', 'FunctionLevelLinking', - _boolean) # /Gy -_Renamed(_compile, 'EnableIntrinsicFunctions', 'IntrinsicFunctions', - _boolean) # /Oi -_Renamed(_compile, 'KeepComments', 'PreprocessKeepComments', _boolean) # /C -_Renamed(_compile, 'ObjectFile', 'ObjectFileName', _file_name) # /Fo -_Renamed(_compile, 'OpenMP', 'OpenMPSupport', _boolean) # /openmp -_Renamed(_compile, 'PrecompiledHeaderThrough', 'PrecompiledHeaderFile', - _file_name) # Used with /Yc and /Yu -_Renamed(_compile, 'PrecompiledHeaderFile', 'PrecompiledHeaderOutputFile', - _file_name) # /Fp -_Renamed(_compile, 'UsePrecompiledHeader', 'PrecompiledHeader', - _Enumeration(['NotUsing', # VS recognized '' for this value too. - 'Create', # /Yc - 'Use'])) # /Yu -_Renamed(_compile, 'WarnAsError', 'TreatWarningAsError', _boolean) # /WX - -_ConvertedToAdditionalOption(_compile, 'DefaultCharIsUnsigned', '/J') - -# MSVS options not found in MSBuild. -_MSVSOnly(_compile, 'Detect64BitPortabilityProblems', _boolean) -_MSVSOnly(_compile, 'UseUnicodeResponseFiles', _boolean) - -# MSBuild options not found in MSVS. -_MSBuildOnly(_compile, 'BuildingInIDE', _boolean) -_MSBuildOnly(_compile, 'CompileAsManaged', - _Enumeration([], new=['false', - 'true'])) # /clr -_MSBuildOnly(_compile, 'CreateHotpatchableImage', _boolean) # /hotpatch -_MSBuildOnly(_compile, 'MultiProcessorCompilation', _boolean) # /MP -_MSBuildOnly(_compile, 'PreprocessOutputPath', _string) # /Fi -_MSBuildOnly(_compile, 'ProcessorNumber', _integer) # the number of processors -_MSBuildOnly(_compile, 'TrackerLogDirectory', _folder_name) -_MSBuildOnly(_compile, 'TreatSpecificWarningsAsErrors', _string_list) # /we -_MSBuildOnly(_compile, 'UseUnicodeForAssemblerListing', _boolean) # /FAu - -# Defines a setting that needs very customized processing -_CustomGeneratePreprocessedFile(_compile, 'GeneratePreprocessedFile') - - -# Directives for converting MSVS VCLinkerTool to MSBuild Link. -# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\link.xml" for -# the schema of the MSBuild Link settings. - -# Options that have the same name in MSVS and MSBuild -_Same(_link, 'AdditionalDependencies', _file_list) -_Same(_link, 'AdditionalLibraryDirectories', _folder_list) # /LIBPATH -# /MANIFESTDEPENDENCY: -_Same(_link, 'AdditionalManifestDependencies', _file_list) -_Same(_link, 'AdditionalOptions', _string_list) -_Same(_link, 'AddModuleNamesToAssembly', _file_list) # /ASSEMBLYMODULE -_Same(_link, 'AllowIsolation', _boolean) # /ALLOWISOLATION -_Same(_link, 'AssemblyLinkResource', _file_list) # /ASSEMBLYLINKRESOURCE -_Same(_link, 'BaseAddress', _string) # /BASE -_Same(_link, 'CLRUnmanagedCodeCheck', _boolean) # /CLRUNMANAGEDCODECHECK -_Same(_link, 'DelayLoadDLLs', _file_list) # /DELAYLOAD -_Same(_link, 'DelaySign', _boolean) # /DELAYSIGN -_Same(_link, 'EmbedManagedResourceFile', _file_list) # /ASSEMBLYRESOURCE -_Same(_link, 'EnableUAC', _boolean) # /MANIFESTUAC -_Same(_link, 'EntryPointSymbol', _string) # /ENTRY -_Same(_link, 'ForceSymbolReferences', _file_list) # /INCLUDE -_Same(_link, 'FunctionOrder', _file_name) # /ORDER -_Same(_link, 'GenerateDebugInformation', _boolean) # /DEBUG -_Same(_link, 'GenerateMapFile', _boolean) # /MAP -_Same(_link, 'HeapCommitSize', _string) -_Same(_link, 'HeapReserveSize', _string) # /HEAP -_Same(_link, 'IgnoreAllDefaultLibraries', _boolean) # /NODEFAULTLIB -_Same(_link, 'IgnoreEmbeddedIDL', _boolean) # /IGNOREIDL -_Same(_link, 'ImportLibrary', _file_name) # /IMPLIB -_Same(_link, 'KeyContainer', _file_name) # /KEYCONTAINER -_Same(_link, 'KeyFile', _file_name) # /KEYFILE -_Same(_link, 'ManifestFile', _file_name) # /ManifestFile -_Same(_link, 'MapExports', _boolean) # /MAPINFO:EXPORTS -_Same(_link, 'MapFileName', _file_name) -_Same(_link, 'MergedIDLBaseFileName', _file_name) # /IDLOUT -_Same(_link, 'MergeSections', _string) # /MERGE -_Same(_link, 'MidlCommandFile', _file_name) # /MIDL -_Same(_link, 'ModuleDefinitionFile', _file_name) # /DEF -_Same(_link, 'OutputFile', _file_name) # /OUT -_Same(_link, 'PerUserRedirection', _boolean) -_Same(_link, 'Profile', _boolean) # /PROFILE -_Same(_link, 'ProfileGuidedDatabase', _file_name) # /PGD -_Same(_link, 'ProgramDatabaseFile', _file_name) # /PDB -_Same(_link, 'RegisterOutput', _boolean) -_Same(_link, 'SetChecksum', _boolean) # /RELEASE -_Same(_link, 'StackCommitSize', _string) -_Same(_link, 'StackReserveSize', _string) # /STACK -_Same(_link, 'StripPrivateSymbols', _file_name) # /PDBSTRIPPED -_Same(_link, 'SupportUnloadOfDelayLoadedDLL', _boolean) # /DELAY:UNLOAD -_Same(_link, 'SuppressStartupBanner', _boolean) # /NOLOGO -_Same(_link, 'SwapRunFromCD', _boolean) # /SWAPRUN:CD -_Same(_link, 'TurnOffAssemblyGeneration', _boolean) # /NOASSEMBLY -_Same(_link, 'TypeLibraryFile', _file_name) # /TLBOUT -_Same(_link, 'TypeLibraryResourceID', _integer) # /TLBID -_Same(_link, 'UACUIAccess', _boolean) # /uiAccess='true' -_Same(_link, 'Version', _string) # /VERSION - -_Same(_link, 'EnableCOMDATFolding', _newly_boolean) # /OPT:ICF -_Same(_link, 'FixedBaseAddress', _newly_boolean) # /FIXED -_Same(_link, 'LargeAddressAware', _newly_boolean) # /LARGEADDRESSAWARE -_Same(_link, 'OptimizeReferences', _newly_boolean) # /OPT:REF -_Same(_link, 'RandomizedBaseAddress', _newly_boolean) # /DYNAMICBASE -_Same(_link, 'TerminalServerAware', _newly_boolean) # /TSAWARE - -_subsystem_enumeration = _Enumeration( - ['NotSet', - 'Console', # /SUBSYSTEM:CONSOLE - 'Windows', # /SUBSYSTEM:WINDOWS - 'Native', # /SUBSYSTEM:NATIVE - 'EFI Application', # /SUBSYSTEM:EFI_APPLICATION - 'EFI Boot Service Driver', # /SUBSYSTEM:EFI_BOOT_SERVICE_DRIVER - 'EFI ROM', # /SUBSYSTEM:EFI_ROM - 'EFI Runtime', # /SUBSYSTEM:EFI_RUNTIME_DRIVER - 'WindowsCE'], # /SUBSYSTEM:WINDOWSCE - new=['POSIX']) # /SUBSYSTEM:POSIX - -_target_machine_enumeration = _Enumeration( - ['NotSet', - 'MachineX86', # /MACHINE:X86 - None, - 'MachineARM', # /MACHINE:ARM - 'MachineEBC', # /MACHINE:EBC - 'MachineIA64', # /MACHINE:IA64 - None, - 'MachineMIPS', # /MACHINE:MIPS - 'MachineMIPS16', # /MACHINE:MIPS16 - 'MachineMIPSFPU', # /MACHINE:MIPSFPU - 'MachineMIPSFPU16', # /MACHINE:MIPSFPU16 - None, - None, - None, - 'MachineSH4', # /MACHINE:SH4 - None, - 'MachineTHUMB', # /MACHINE:THUMB - 'MachineX64']) # /MACHINE:X64 - -_Same(_link, 'AssemblyDebug', - _Enumeration(['', - 'true', # /ASSEMBLYDEBUG - 'false'])) # /ASSEMBLYDEBUG:DISABLE -_Same(_link, 'CLRImageType', - _Enumeration(['Default', - 'ForceIJWImage', # /CLRIMAGETYPE:IJW - 'ForcePureILImage', # /Switch="CLRIMAGETYPE:PURE - 'ForceSafeILImage'])) # /Switch="CLRIMAGETYPE:SAFE -_Same(_link, 'CLRThreadAttribute', - _Enumeration(['DefaultThreadingAttribute', # /CLRTHREADATTRIBUTE:NONE - 'MTAThreadingAttribute', # /CLRTHREADATTRIBUTE:MTA - 'STAThreadingAttribute'])) # /CLRTHREADATTRIBUTE:STA -_Same(_link, 'DataExecutionPrevention', - _Enumeration(['', - 'false', # /NXCOMPAT:NO - 'true'])) # /NXCOMPAT -_Same(_link, 'Driver', - _Enumeration(['NotSet', - 'Driver', # /Driver - 'UpOnly', # /DRIVER:UPONLY - 'WDM'])) # /DRIVER:WDM -_Same(_link, 'LinkTimeCodeGeneration', - _Enumeration(['Default', - 'UseLinkTimeCodeGeneration', # /LTCG - 'PGInstrument', # /LTCG:PGInstrument - 'PGOptimization', # /LTCG:PGOptimize - 'PGUpdate'])) # /LTCG:PGUpdate -_Same(_link, 'ShowProgress', - _Enumeration(['NotSet', - 'LinkVerbose', # /VERBOSE - 'LinkVerboseLib'], # /VERBOSE:Lib - new=['LinkVerboseICF', # /VERBOSE:ICF - 'LinkVerboseREF', # /VERBOSE:REF - 'LinkVerboseSAFESEH', # /VERBOSE:SAFESEH - 'LinkVerboseCLR'])) # /VERBOSE:CLR -_Same(_link, 'SubSystem', _subsystem_enumeration) -_Same(_link, 'TargetMachine', _target_machine_enumeration) -_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. -_Renamed(_link, 'ErrorReporting', 'LinkErrorReporting', - _Enumeration(['NoErrorReport', # /ERRORREPORT:NONE - 'PromptImmediately', # /ERRORREPORT:PROMPT - 'QueueForNextLogin'], # /ERRORREPORT:QUEUE - new=['SendErrorReport'])) # /ERRORREPORT:SEND -_Renamed(_link, 'IgnoreDefaultLibraryNames', 'IgnoreSpecificDefaultLibraries', - _file_list) # /NODEFAULTLIB -_Renamed(_link, 'ResourceOnlyDLL', 'NoEntryPoint', _boolean) # /NOENTRY -_Renamed(_link, 'SwapRunFromNet', 'SwapRunFromNET', _boolean) # /SWAPRUN:NET - -_Moved(_link, 'GenerateManifest', '', _boolean) -_Moved(_link, 'IgnoreImportLibrary', '', _boolean) -_Moved(_link, 'LinkIncremental', '', _newly_boolean) -_Moved(_link, 'LinkLibraryDependencies', 'ProjectReference', _boolean) -_Moved(_link, 'UseLibraryDependencyInputs', 'ProjectReference', _boolean) - -# MSVS options not found in MSBuild. -_MSVSOnly(_link, 'OptimizeForWindows98', _newly_boolean) -_MSVSOnly(_link, 'UseUnicodeResponseFiles', _boolean) - -# MSBuild options not found in MSVS. -_MSBuildOnly(_link, 'BuildingInIDE', _boolean) -_MSBuildOnly(_link, 'ImageHasSafeExceptionHandlers', _boolean) # /SAFESEH -_MSBuildOnly(_link, 'LinkDLL', _boolean) # /DLL Visible='false' -_MSBuildOnly(_link, 'LinkStatus', _boolean) # /LTCG:STATUS -_MSBuildOnly(_link, 'PreventDllBinding', _boolean) # /ALLOWBIND -_MSBuildOnly(_link, 'SupportNobindOfDelayLoadedDLL', _boolean) # /DELAY:NOBIND -_MSBuildOnly(_link, 'TrackerLogDirectory', _folder_name) -_MSBuildOnly(_link, 'MSDOSStubFileName', _file_name) # /STUB Visible='false' -_MSBuildOnly(_link, 'SectionAlignment', _integer) # /ALIGN -_MSBuildOnly(_link, 'SpecifySectionAttributes', _string) # /SECTION -_MSBuildOnly(_link, 'ForceFileOutput', - _Enumeration([], new=['Enabled', # /FORCE - # /FORCE:MULTIPLE - 'MultiplyDefinedSymbolOnly', - 'UndefinedSymbolOnly'])) # /FORCE:UNRESOLVED -_MSBuildOnly(_link, 'CreateHotPatchableImage', - _Enumeration([], new=['Enabled', # /FUNCTIONPADMIN - 'X86Image', # /FUNCTIONPADMIN:5 - 'X64Image', # /FUNCTIONPADMIN:6 - 'ItaniumImage'])) # /FUNCTIONPADMIN:16 -_MSBuildOnly(_link, 'CLRSupportLastError', - _Enumeration([], new=['Enabled', # /CLRSupportLastError - 'Disabled', # /CLRSupportLastError:NO - # /CLRSupportLastError:SYSTEMDLL - 'SystemDlls'])) - - -# Directives for converting VCResourceCompilerTool to ResourceCompile. -# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\rc.xml" for -# the schema of the MSBuild ResourceCompile settings. - -_Same(_rc, 'AdditionalOptions', _string_list) -_Same(_rc, 'AdditionalIncludeDirectories', _folder_list) # /I -_Same(_rc, 'Culture', _Integer(msbuild_base=16)) -_Same(_rc, 'IgnoreStandardIncludePath', _boolean) # /X -_Same(_rc, 'PreprocessorDefinitions', _string_list) # /D -_Same(_rc, 'ResourceOutputFileName', _string) # /fo -_Same(_rc, 'ShowProgress', _boolean) # /v -# There is no UI in VisualStudio 2008 to set the following properties. -# However they are found in CL and other tools. Include them here for -# completeness, as they are very likely to have the same usage pattern. -_Same(_rc, 'SuppressStartupBanner', _boolean) # /nologo -_Same(_rc, 'UndefinePreprocessorDefinitions', _string_list) # /u - -# MSBuild options not found in MSVS. -_MSBuildOnly(_rc, 'NullTerminateStrings', _boolean) # /n -_MSBuildOnly(_rc, 'TrackerLogDirectory', _folder_name) - - -# Directives for converting VCMIDLTool to Midl. -# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\midl.xml" for -# the schema of the MSBuild Midl settings. - -_Same(_midl, 'AdditionalIncludeDirectories', _folder_list) # /I -_Same(_midl, 'AdditionalOptions', _string_list) -_Same(_midl, 'CPreprocessOptions', _string) # /cpp_opt -_Same(_midl, 'ErrorCheckAllocations', _boolean) # /error allocation -_Same(_midl, 'ErrorCheckBounds', _boolean) # /error bounds_check -_Same(_midl, 'ErrorCheckEnumRange', _boolean) # /error enum -_Same(_midl, 'ErrorCheckRefPointers', _boolean) # /error ref -_Same(_midl, 'ErrorCheckStubData', _boolean) # /error stub_data -_Same(_midl, 'GenerateStublessProxies', _boolean) # /Oicf -_Same(_midl, 'GenerateTypeLibrary', _boolean) -_Same(_midl, 'HeaderFileName', _file_name) # /h -_Same(_midl, 'IgnoreStandardIncludePath', _boolean) # /no_def_idir -_Same(_midl, 'InterfaceIdentifierFileName', _file_name) # /iid -_Same(_midl, 'MkTypLibCompatible', _boolean) # /mktyplib203 -_Same(_midl, 'OutputDirectory', _string) # /out -_Same(_midl, 'PreprocessorDefinitions', _string_list) # /D -_Same(_midl, 'ProxyFileName', _file_name) # /proxy -_Same(_midl, 'RedirectOutputAndErrors', _file_name) # /o -_Same(_midl, 'SuppressStartupBanner', _boolean) # /nologo -_Same(_midl, 'TypeLibraryName', _file_name) # /tlb -_Same(_midl, 'UndefinePreprocessorDefinitions', _string_list) # /U -_Same(_midl, 'WarnAsError', _boolean) # /WX - -_Same(_midl, 'DefaultCharType', - _Enumeration(['Unsigned', # /char unsigned - 'Signed', # /char signed - 'Ascii'])) # /char ascii7 -_Same(_midl, 'TargetEnvironment', - _Enumeration(['NotSet', - 'Win32', # /env win32 - 'Itanium', # /env ia64 - 'X64'])) # /env x64 -_Same(_midl, 'EnableErrorChecks', - _Enumeration(['EnableCustom', - 'None', # /error none - 'All'])) # /error all -_Same(_midl, 'StructMemberAlignment', - _Enumeration(['NotSet', - '1', # Zp1 - '2', # Zp2 - '4', # Zp4 - '8'])) # Zp8 -_Same(_midl, 'WarningLevel', - _Enumeration(['0', # /W0 - '1', # /W1 - '2', # /W2 - '3', # /W3 - '4'])) # /W4 - -_Renamed(_midl, 'DLLDataFileName', 'DllDataFileName', _file_name) # /dlldata -_Renamed(_midl, 'ValidateParameters', 'ValidateAllParameters', - _boolean) # /robust - -# MSBuild options not found in MSVS. -_MSBuildOnly(_midl, 'ApplicationConfigurationMode', _boolean) # /app_config -_MSBuildOnly(_midl, 'ClientStubFile', _file_name) # /cstub -_MSBuildOnly(_midl, 'GenerateClientFiles', - _Enumeration([], new=['Stub', # /client stub - 'None'])) # /client none -_MSBuildOnly(_midl, 'GenerateServerFiles', - _Enumeration([], new=['Stub', # /client stub - 'None'])) # /client none -_MSBuildOnly(_midl, 'LocaleID', _integer) # /lcid DECIMAL -_MSBuildOnly(_midl, 'ServerStubFile', _file_name) # /sstub -_MSBuildOnly(_midl, 'SuppressCompilerWarnings', _boolean) # /no_warn -_MSBuildOnly(_midl, 'TrackerLogDirectory', _folder_name) -_MSBuildOnly(_midl, 'TypeLibFormat', - _Enumeration([], new=['NewFormat', # /newtlb - 'OldFormat'])) # /oldtlb - - -# Directives for converting VCLibrarianTool to Lib. -# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\lib.xml" for -# the schema of the MSBuild Lib settings. - -_Same(_lib, 'AdditionalDependencies', _file_list) -_Same(_lib, 'AdditionalLibraryDirectories', _folder_list) # /LIBPATH -_Same(_lib, 'AdditionalOptions', _string_list) -_Same(_lib, 'ExportNamedFunctions', _string_list) # /EXPORT -_Same(_lib, 'ForceSymbolReferences', _string) # /INCLUDE -_Same(_lib, 'IgnoreAllDefaultLibraries', _boolean) # /NODEFAULTLIB -_Same(_lib, 'IgnoreSpecificDefaultLibraries', _file_list) # /NODEFAULTLIB -_Same(_lib, 'ModuleDefinitionFile', _file_name) # /DEF -_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. -_Moved(_lib, 'LinkLibraryDependencies', 'ProjectReference', _boolean) - -_MSBuildOnly(_lib, 'DisplayLibrary', _string) # /LIST Visible='false' -_MSBuildOnly(_lib, 'ErrorReporting', - _Enumeration([], new=['PromptImmediately', # /ERRORREPORT:PROMPT - 'QueueForNextLogin', # /ERRORREPORT:QUEUE - 'SendErrorReport', # /ERRORREPORT:SEND - 'NoErrorReport'])) # /ERRORREPORT:NONE -_MSBuildOnly(_lib, 'MinimumRequiredVersion', _string) -_MSBuildOnly(_lib, 'Name', _file_name) # /NAME -_MSBuildOnly(_lib, 'RemoveObjects', _file_list) # /REMOVE -_MSBuildOnly(_lib, 'SubSystem', _subsystem_enumeration) -_MSBuildOnly(_lib, 'TrackerLogDirectory', _folder_name) -_MSBuildOnly(_lib, 'TreatLibWarningAsErrors', _boolean) # /WX -_MSBuildOnly(_lib, 'Verbose', _boolean) - - -# Directives for converting VCManifestTool to Mt. -# See "c:\Program Files (x86)\MSBuild\Microsoft.Cpp\v4.0\1033\mt.xml" for -# the schema of the MSBuild Lib settings. - -# Options that have the same name in MSVS and MSBuild -_Same(_manifest, 'AdditionalManifestFiles', _file_list) # /manifest -_Same(_manifest, 'AdditionalOptions', _string_list) -_Same(_manifest, 'AssemblyIdentity', _string) # /identity: -_Same(_manifest, 'ComponentFileName', _file_name) # /dll -_Same(_manifest, 'GenerateCatalogFiles', _boolean) # /makecdfs -_Same(_manifest, 'InputResourceManifests', _string) # /inputresource -_Same(_manifest, 'OutputManifestFile', _file_name) # /out -_Same(_manifest, 'RegistrarScriptFile', _file_name) # /rgs -_Same(_manifest, 'ReplacementsFile', _file_name) # /replacements -_Same(_manifest, 'SuppressStartupBanner', _boolean) # /nologo -_Same(_manifest, 'TypeLibraryFile', _file_name) # /tlb: -_Same(_manifest, 'UpdateFileHashes', _boolean) # /hashupdate -_Same(_manifest, 'UpdateFileHashesSearchPath', _file_name) -_Same(_manifest, 'VerboseOutput', _boolean) # /verbose - -# Options that have moved location. -_MovedAndRenamed(_manifest, 'ManifestResourceFile', - 'ManifestResourceCompile', - 'ResourceOutputFileName', - _file_name) -_Moved(_manifest, 'EmbedManifest', '', _boolean) - -# MSVS options not found in MSBuild. -_MSVSOnly(_manifest, 'DependencyInformationFile', _file_name) -_MSVSOnly(_manifest, 'UseFAT32Workaround', _boolean) -_MSVSOnly(_manifest, 'UseUnicodeResponseFiles', _boolean) - -# MSBuild options not found in MSVS. -_MSBuildOnly(_manifest, 'EnableDPIAwareness', _boolean) -_MSBuildOnly(_manifest, 'GenerateCategoryTags', _boolean) # /category -_MSBuildOnly(_manifest, 'ManifestFromManagedAssembly', - _file_name) # /managedassemblyname -_MSBuildOnly(_manifest, 'OutputResourceManifests', _string) # /outputresource -_MSBuildOnly(_manifest, 'SuppressDependencyElement', _boolean) # /nodependency -_MSBuildOnly(_manifest, 'TrackerLogDirectory', _folder_name) - - -# Directives for MASM. -# See "$(VCTargetsPath)\BuildCustomizations\masm.xml" for the schema of the -# MSBuild MASM settings. - -# Options that have the same name in MSVS and MSBuild. -_Same(_masm, 'UseSafeExceptionHandlers', _boolean) # /safeseh diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py deleted file mode 100755 index bf6ea6b802ff9..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSSettings_test.py +++ /dev/null @@ -1,1483 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2012 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. - -"""Unit tests for the MSVSSettings.py file.""" - -import StringIO -import unittest -import gyp.MSVSSettings as MSVSSettings - - -class TestSequenceFunctions(unittest.TestCase): - - def setUp(self): - self.stderr = StringIO.StringIO() - - def _ExpectedWarnings(self, expected): - """Compares recorded lines to expected warnings.""" - self.stderr.seek(0) - actual = self.stderr.read().split('\n') - actual = [line for line in actual if line] - self.assertEqual(sorted(expected), sorted(actual)) - - def testValidateMSVSSettings_tool_names(self): - """Tests that only MSVS tool names are allowed.""" - MSVSSettings.ValidateMSVSSettings( - {'VCCLCompilerTool': {}, - 'VCLinkerTool': {}, - 'VCMIDLTool': {}, - 'foo': {}, - 'VCResourceCompilerTool': {}, - 'VCLibrarianTool': {}, - 'VCManifestTool': {}, - 'ClCompile': {}}, - self.stderr) - self._ExpectedWarnings([ - 'Warning: unrecognized tool foo', - 'Warning: unrecognized tool ClCompile']) - - def testValidateMSVSSettings_settings(self): - """Tests that for invalid MSVS settings.""" - MSVSSettings.ValidateMSVSSettings( - {'VCCLCompilerTool': { - 'AdditionalIncludeDirectories': 'folder1;folder2', - 'AdditionalOptions': ['string1', 'string2'], - 'AdditionalUsingDirectories': 'folder1;folder2', - 'AssemblerListingLocation': 'a_file_name', - 'AssemblerOutput': '0', - 'BasicRuntimeChecks': '5', - 'BrowseInformation': 'fdkslj', - 'BrowseInformationFile': 'a_file_name', - 'BufferSecurityCheck': 'true', - 'CallingConvention': '-1', - 'CompileAs': '1', - 'DebugInformationFormat': '2', - 'DefaultCharIsUnsigned': 'true', - 'Detect64BitPortabilityProblems': 'true', - 'DisableLanguageExtensions': 'true', - 'DisableSpecificWarnings': 'string1;string2', - 'EnableEnhancedInstructionSet': '1', - 'EnableFiberSafeOptimizations': 'true', - 'EnableFunctionLevelLinking': 'true', - 'EnableIntrinsicFunctions': 'true', - 'EnablePREfast': 'true', - 'Enableprefast': 'bogus', - 'ErrorReporting': '1', - 'ExceptionHandling': '1', - 'ExpandAttributedSource': 'true', - 'FavorSizeOrSpeed': '1', - 'FloatingPointExceptions': 'true', - 'FloatingPointModel': '1', - 'ForceConformanceInForLoopScope': 'true', - 'ForcedIncludeFiles': 'file1;file2', - 'ForcedUsingFiles': 'file1;file2', - 'GeneratePreprocessedFile': '1', - 'GenerateXMLDocumentationFiles': 'true', - 'IgnoreStandardIncludePath': 'true', - 'InlineFunctionExpansion': '1', - 'KeepComments': 'true', - 'MinimalRebuild': 'true', - 'ObjectFile': 'a_file_name', - 'OmitDefaultLibName': 'true', - 'OmitFramePointers': 'true', - 'OpenMP': 'true', - 'Optimization': '1', - 'PrecompiledHeaderFile': 'a_file_name', - 'PrecompiledHeaderThrough': 'a_file_name', - 'PreprocessorDefinitions': 'string1;string2', - 'ProgramDataBaseFileName': 'a_file_name', - 'RuntimeLibrary': '1', - 'RuntimeTypeInfo': 'true', - 'ShowIncludes': 'true', - 'SmallerTypeCheck': 'true', - 'StringPooling': 'true', - 'StructMemberAlignment': '1', - 'SuppressStartupBanner': 'true', - 'TreatWChar_tAsBuiltInType': 'true', - 'UndefineAllPreprocessorDefinitions': 'true', - 'UndefinePreprocessorDefinitions': 'string1;string2', - 'UseFullPaths': 'true', - 'UsePrecompiledHeader': '1', - 'UseUnicodeResponseFiles': 'true', - 'WarnAsError': 'true', - 'WarningLevel': '1', - 'WholeProgramOptimization': 'true', - 'XMLDocumentationFileName': 'a_file_name', - 'ZZXYZ': 'bogus'}, - 'VCLinkerTool': { - 'AdditionalDependencies': 'file1;file2', - 'AdditionalDependencies_excluded': 'file3', - 'AdditionalLibraryDirectories': 'folder1;folder2', - 'AdditionalManifestDependencies': 'file1;file2', - 'AdditionalOptions': 'a string1', - 'AddModuleNamesToAssembly': 'file1;file2', - 'AllowIsolation': 'true', - 'AssemblyDebug': '2', - 'AssemblyLinkResource': 'file1;file2', - 'BaseAddress': 'a string1', - 'CLRImageType': '2', - 'CLRThreadAttribute': '2', - 'CLRUnmanagedCodeCheck': 'true', - 'DataExecutionPrevention': '2', - 'DelayLoadDLLs': 'file1;file2', - 'DelaySign': 'true', - 'Driver': '2', - 'EmbedManagedResourceFile': 'file1;file2', - 'EnableCOMDATFolding': '2', - 'EnableUAC': 'true', - 'EntryPointSymbol': 'a string1', - 'ErrorReporting': '2', - 'FixedBaseAddress': '2', - 'ForceSymbolReferences': 'file1;file2', - 'FunctionOrder': 'a_file_name', - 'GenerateDebugInformation': 'true', - 'GenerateManifest': 'true', - 'GenerateMapFile': 'true', - 'HeapCommitSize': 'a string1', - 'HeapReserveSize': 'a string1', - 'IgnoreAllDefaultLibraries': 'true', - 'IgnoreDefaultLibraryNames': 'file1;file2', - 'IgnoreEmbeddedIDL': 'true', - 'IgnoreImportLibrary': 'true', - 'ImportLibrary': 'a_file_name', - 'KeyContainer': 'a_file_name', - 'KeyFile': 'a_file_name', - 'LargeAddressAware': '2', - 'LinkIncremental': '2', - 'LinkLibraryDependencies': 'true', - 'LinkTimeCodeGeneration': '2', - 'ManifestFile': 'a_file_name', - 'MapExports': 'true', - 'MapFileName': 'a_file_name', - 'MergedIDLBaseFileName': 'a_file_name', - 'MergeSections': 'a string1', - 'MidlCommandFile': 'a_file_name', - 'ModuleDefinitionFile': 'a_file_name', - 'OptimizeForWindows98': '1', - 'OptimizeReferences': '2', - 'OutputFile': 'a_file_name', - 'PerUserRedirection': 'true', - 'Profile': 'true', - 'ProfileGuidedDatabase': 'a_file_name', - 'ProgramDatabaseFile': 'a_file_name', - 'RandomizedBaseAddress': '2', - 'RegisterOutput': 'true', - 'ResourceOnlyDLL': 'true', - 'SetChecksum': 'true', - 'ShowProgress': '2', - 'StackCommitSize': 'a string1', - 'StackReserveSize': 'a string1', - 'StripPrivateSymbols': 'a_file_name', - 'SubSystem': '2', - 'SupportUnloadOfDelayLoadedDLL': 'true', - 'SuppressStartupBanner': 'true', - 'SwapRunFromCD': 'true', - 'SwapRunFromNet': 'true', - 'TargetMachine': '2', - 'TerminalServerAware': '2', - 'TurnOffAssemblyGeneration': 'true', - 'TypeLibraryFile': 'a_file_name', - 'TypeLibraryResourceID': '33', - 'UACExecutionLevel': '2', - 'UACUIAccess': 'true', - 'UseLibraryDependencyInputs': 'true', - 'UseUnicodeResponseFiles': 'true', - 'Version': 'a string1'}, - 'VCMIDLTool': { - 'AdditionalIncludeDirectories': 'folder1;folder2', - 'AdditionalOptions': 'a string1', - 'CPreprocessOptions': 'a string1', - 'DefaultCharType': '1', - 'DLLDataFileName': 'a_file_name', - 'EnableErrorChecks': '1', - 'ErrorCheckAllocations': 'true', - 'ErrorCheckBounds': 'true', - 'ErrorCheckEnumRange': 'true', - 'ErrorCheckRefPointers': 'true', - 'ErrorCheckStubData': 'true', - 'GenerateStublessProxies': 'true', - 'GenerateTypeLibrary': 'true', - 'HeaderFileName': 'a_file_name', - 'IgnoreStandardIncludePath': 'true', - 'InterfaceIdentifierFileName': 'a_file_name', - 'MkTypLibCompatible': 'true', - 'notgood': 'bogus', - 'OutputDirectory': 'a string1', - 'PreprocessorDefinitions': 'string1;string2', - 'ProxyFileName': 'a_file_name', - 'RedirectOutputAndErrors': 'a_file_name', - 'StructMemberAlignment': '1', - 'SuppressStartupBanner': 'true', - 'TargetEnvironment': '1', - 'TypeLibraryName': 'a_file_name', - 'UndefinePreprocessorDefinitions': 'string1;string2', - 'ValidateParameters': 'true', - 'WarnAsError': 'true', - 'WarningLevel': '1'}, - 'VCResourceCompilerTool': { - 'AdditionalOptions': 'a string1', - 'AdditionalIncludeDirectories': 'folder1;folder2', - 'Culture': '1003', - 'IgnoreStandardIncludePath': 'true', - 'notgood2': 'bogus', - 'PreprocessorDefinitions': 'string1;string2', - 'ResourceOutputFileName': 'a string1', - 'ShowProgress': 'true', - 'SuppressStartupBanner': 'true', - 'UndefinePreprocessorDefinitions': 'string1;string2'}, - 'VCLibrarianTool': { - 'AdditionalDependencies': 'file1;file2', - 'AdditionalLibraryDirectories': 'folder1;folder2', - 'AdditionalOptions': 'a string1', - 'ExportNamedFunctions': 'string1;string2', - 'ForceSymbolReferences': 'a string1', - 'IgnoreAllDefaultLibraries': 'true', - 'IgnoreSpecificDefaultLibraries': 'file1;file2', - 'LinkLibraryDependencies': 'true', - 'ModuleDefinitionFile': 'a_file_name', - 'OutputFile': 'a_file_name', - 'SuppressStartupBanner': 'true', - 'UseUnicodeResponseFiles': 'true'}, - 'VCManifestTool': { - 'AdditionalManifestFiles': 'file1;file2', - 'AdditionalOptions': 'a string1', - 'AssemblyIdentity': 'a string1', - 'ComponentFileName': 'a_file_name', - 'DependencyInformationFile': 'a_file_name', - 'GenerateCatalogFiles': 'true', - 'InputResourceManifests': 'a string1', - 'ManifestResourceFile': 'a_file_name', - 'OutputManifestFile': 'a_file_name', - 'RegistrarScriptFile': 'a_file_name', - 'ReplacementsFile': 'a_file_name', - 'SuppressStartupBanner': 'true', - 'TypeLibraryFile': 'a_file_name', - 'UpdateFileHashes': 'truel', - 'UpdateFileHashesSearchPath': 'a_file_name', - 'UseFAT32Workaround': 'true', - 'UseUnicodeResponseFiles': 'true', - 'VerboseOutput': 'true'}}, - self.stderr) - self._ExpectedWarnings([ - 'Warning: for VCCLCompilerTool/BasicRuntimeChecks, ' - 'index value (5) not in expected range [0, 4)', - 'Warning: for VCCLCompilerTool/BrowseInformation, ' - "invalid literal for int() with base 10: 'fdkslj'", - 'Warning: for VCCLCompilerTool/CallingConvention, ' - 'index value (-1) not in expected range [0, 4)', - 'Warning: for VCCLCompilerTool/DebugInformationFormat, ' - 'converted value for 2 not specified.', - 'Warning: unrecognized setting VCCLCompilerTool/Enableprefast', - 'Warning: unrecognized setting VCCLCompilerTool/ZZXYZ', - 'Warning: for VCLinkerTool/TargetMachine, ' - 'converted value for 2 not specified.', - 'Warning: unrecognized setting VCMIDLTool/notgood', - 'Warning: unrecognized setting VCResourceCompilerTool/notgood2', - 'Warning: for VCManifestTool/UpdateFileHashes, ' - "expected bool; got 'truel'" - '']) - - def testValidateMSBuildSettings_settings(self): - """Tests that for invalid MSBuild settings.""" - MSVSSettings.ValidateMSBuildSettings( - {'ClCompile': { - 'AdditionalIncludeDirectories': 'folder1;folder2', - 'AdditionalOptions': ['string1', 'string2'], - 'AdditionalUsingDirectories': 'folder1;folder2', - 'AssemblerListingLocation': 'a_file_name', - 'AssemblerOutput': 'NoListing', - 'BasicRuntimeChecks': 'StackFrameRuntimeCheck', - 'BrowseInformation': 'false', - 'BrowseInformationFile': 'a_file_name', - 'BufferSecurityCheck': 'true', - 'BuildingInIDE': 'true', - 'CallingConvention': 'Cdecl', - 'CompileAs': 'CompileAsC', - 'CompileAsManaged': 'true', - 'CreateHotpatchableImage': 'true', - 'DebugInformationFormat': 'ProgramDatabase', - 'DisableLanguageExtensions': 'true', - 'DisableSpecificWarnings': 'string1;string2', - 'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions', - 'EnableFiberSafeOptimizations': 'true', - 'EnablePREfast': 'true', - 'Enableprefast': 'bogus', - 'ErrorReporting': 'Prompt', - 'ExceptionHandling': 'SyncCThrow', - 'ExpandAttributedSource': 'true', - 'FavorSizeOrSpeed': 'Neither', - 'FloatingPointExceptions': 'true', - 'FloatingPointModel': 'Precise', - 'ForceConformanceInForLoopScope': 'true', - 'ForcedIncludeFiles': 'file1;file2', - 'ForcedUsingFiles': 'file1;file2', - 'FunctionLevelLinking': 'false', - 'GenerateXMLDocumentationFiles': 'true', - 'IgnoreStandardIncludePath': 'true', - 'InlineFunctionExpansion': 'OnlyExplicitInline', - 'IntrinsicFunctions': 'false', - 'MinimalRebuild': 'true', - 'MultiProcessorCompilation': 'true', - 'ObjectFileName': 'a_file_name', - 'OmitDefaultLibName': 'true', - 'OmitFramePointers': 'true', - 'OpenMPSupport': 'true', - 'Optimization': 'Disabled', - 'PrecompiledHeader': 'NotUsing', - 'PrecompiledHeaderFile': 'a_file_name', - 'PrecompiledHeaderOutputFile': 'a_file_name', - 'PreprocessKeepComments': 'true', - 'PreprocessorDefinitions': 'string1;string2', - 'PreprocessOutputPath': 'a string1', - 'PreprocessSuppressLineNumbers': 'false', - 'PreprocessToFile': 'false', - 'ProcessorNumber': '33', - 'ProgramDataBaseFileName': 'a_file_name', - 'RuntimeLibrary': 'MultiThreaded', - 'RuntimeTypeInfo': 'true', - 'ShowIncludes': 'true', - 'SmallerTypeCheck': 'true', - 'StringPooling': 'true', - 'StructMemberAlignment': '1Byte', - 'SuppressStartupBanner': 'true', - 'TrackerLogDirectory': 'a_folder', - 'TreatSpecificWarningsAsErrors': 'string1;string2', - 'TreatWarningAsError': 'true', - 'TreatWChar_tAsBuiltInType': 'true', - 'UndefineAllPreprocessorDefinitions': 'true', - 'UndefinePreprocessorDefinitions': 'string1;string2', - 'UseFullPaths': 'true', - 'UseUnicodeForAssemblerListing': 'true', - 'WarningLevel': 'TurnOffAllWarnings', - 'WholeProgramOptimization': 'true', - 'XMLDocumentationFileName': 'a_file_name', - 'ZZXYZ': 'bogus'}, - 'Link': { - 'AdditionalDependencies': 'file1;file2', - 'AdditionalLibraryDirectories': 'folder1;folder2', - 'AdditionalManifestDependencies': 'file1;file2', - 'AdditionalOptions': 'a string1', - 'AddModuleNamesToAssembly': 'file1;file2', - 'AllowIsolation': 'true', - 'AssemblyDebug': '', - 'AssemblyLinkResource': 'file1;file2', - 'BaseAddress': 'a string1', - 'BuildingInIDE': 'true', - 'CLRImageType': 'ForceIJWImage', - 'CLRSupportLastError': 'Enabled', - 'CLRThreadAttribute': 'MTAThreadingAttribute', - 'CLRUnmanagedCodeCheck': 'true', - 'CreateHotPatchableImage': 'X86Image', - 'DataExecutionPrevention': 'false', - 'DelayLoadDLLs': 'file1;file2', - 'DelaySign': 'true', - 'Driver': 'NotSet', - 'EmbedManagedResourceFile': 'file1;file2', - 'EnableCOMDATFolding': 'false', - 'EnableUAC': 'true', - 'EntryPointSymbol': 'a string1', - 'FixedBaseAddress': 'false', - 'ForceFileOutput': 'Enabled', - 'ForceSymbolReferences': 'file1;file2', - 'FunctionOrder': 'a_file_name', - 'GenerateDebugInformation': 'true', - 'GenerateMapFile': 'true', - 'HeapCommitSize': 'a string1', - 'HeapReserveSize': 'a string1', - 'IgnoreAllDefaultLibraries': 'true', - 'IgnoreEmbeddedIDL': 'true', - 'IgnoreSpecificDefaultLibraries': 'a_file_list', - 'ImageHasSafeExceptionHandlers': 'true', - 'ImportLibrary': 'a_file_name', - 'KeyContainer': 'a_file_name', - 'KeyFile': 'a_file_name', - 'LargeAddressAware': 'false', - 'LinkDLL': 'true', - 'LinkErrorReporting': 'SendErrorReport', - 'LinkStatus': 'true', - 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration', - 'ManifestFile': 'a_file_name', - 'MapExports': 'true', - 'MapFileName': 'a_file_name', - 'MergedIDLBaseFileName': 'a_file_name', - 'MergeSections': 'a string1', - 'MidlCommandFile': 'a_file_name', - 'MinimumRequiredVersion': 'a string1', - 'ModuleDefinitionFile': 'a_file_name', - 'MSDOSStubFileName': 'a_file_name', - 'NoEntryPoint': 'true', - 'OptimizeReferences': 'false', - 'OutputFile': 'a_file_name', - 'PerUserRedirection': 'true', - 'PreventDllBinding': 'true', - 'Profile': 'true', - 'ProfileGuidedDatabase': 'a_file_name', - 'ProgramDatabaseFile': 'a_file_name', - 'RandomizedBaseAddress': 'false', - 'RegisterOutput': 'true', - 'SectionAlignment': '33', - 'SetChecksum': 'true', - 'ShowProgress': 'LinkVerboseREF', - 'SpecifySectionAttributes': 'a string1', - 'StackCommitSize': 'a string1', - 'StackReserveSize': 'a string1', - 'StripPrivateSymbols': 'a_file_name', - 'SubSystem': 'Console', - 'SupportNobindOfDelayLoadedDLL': 'true', - 'SupportUnloadOfDelayLoadedDLL': 'true', - 'SuppressStartupBanner': 'true', - 'SwapRunFromCD': 'true', - 'SwapRunFromNET': 'true', - 'TargetMachine': 'MachineX86', - 'TerminalServerAware': 'false', - 'TrackerLogDirectory': 'a_folder', - 'TreatLinkerWarningAsErrors': 'true', - 'TurnOffAssemblyGeneration': 'true', - 'TypeLibraryFile': 'a_file_name', - 'TypeLibraryResourceID': '33', - 'UACExecutionLevel': 'AsInvoker', - 'UACUIAccess': 'true', - 'Version': 'a string1'}, - 'ResourceCompile': { - 'AdditionalIncludeDirectories': 'folder1;folder2', - 'AdditionalOptions': 'a string1', - 'Culture': '0x236', - 'IgnoreStandardIncludePath': 'true', - 'NullTerminateStrings': 'true', - 'PreprocessorDefinitions': 'string1;string2', - 'ResourceOutputFileName': 'a string1', - 'ShowProgress': 'true', - 'SuppressStartupBanner': 'true', - 'TrackerLogDirectory': 'a_folder', - 'UndefinePreprocessorDefinitions': 'string1;string2'}, - 'Midl': { - 'AdditionalIncludeDirectories': 'folder1;folder2', - 'AdditionalOptions': 'a string1', - 'ApplicationConfigurationMode': 'true', - 'ClientStubFile': 'a_file_name', - 'CPreprocessOptions': 'a string1', - 'DefaultCharType': 'Signed', - 'DllDataFileName': 'a_file_name', - 'EnableErrorChecks': 'EnableCustom', - 'ErrorCheckAllocations': 'true', - 'ErrorCheckBounds': 'true', - 'ErrorCheckEnumRange': 'true', - 'ErrorCheckRefPointers': 'true', - 'ErrorCheckStubData': 'true', - 'GenerateClientFiles': 'Stub', - 'GenerateServerFiles': 'None', - 'GenerateStublessProxies': 'true', - 'GenerateTypeLibrary': 'true', - 'HeaderFileName': 'a_file_name', - 'IgnoreStandardIncludePath': 'true', - 'InterfaceIdentifierFileName': 'a_file_name', - 'LocaleID': '33', - 'MkTypLibCompatible': 'true', - 'OutputDirectory': 'a string1', - 'PreprocessorDefinitions': 'string1;string2', - 'ProxyFileName': 'a_file_name', - 'RedirectOutputAndErrors': 'a_file_name', - 'ServerStubFile': 'a_file_name', - 'StructMemberAlignment': 'NotSet', - 'SuppressCompilerWarnings': 'true', - 'SuppressStartupBanner': 'true', - 'TargetEnvironment': 'Itanium', - 'TrackerLogDirectory': 'a_folder', - 'TypeLibFormat': 'NewFormat', - 'TypeLibraryName': 'a_file_name', - 'UndefinePreprocessorDefinitions': 'string1;string2', - 'ValidateAllParameters': 'true', - 'WarnAsError': 'true', - 'WarningLevel': '1'}, - 'Lib': { - 'AdditionalDependencies': 'file1;file2', - 'AdditionalLibraryDirectories': 'folder1;folder2', - 'AdditionalOptions': 'a string1', - 'DisplayLibrary': 'a string1', - 'ErrorReporting': 'PromptImmediately', - 'ExportNamedFunctions': 'string1;string2', - 'ForceSymbolReferences': 'a string1', - 'IgnoreAllDefaultLibraries': 'true', - 'IgnoreSpecificDefaultLibraries': 'file1;file2', - 'LinkTimeCodeGeneration': 'true', - 'MinimumRequiredVersion': 'a string1', - 'ModuleDefinitionFile': 'a_file_name', - 'Name': 'a_file_name', - 'OutputFile': 'a_file_name', - 'RemoveObjects': 'file1;file2', - 'SubSystem': 'Console', - 'SuppressStartupBanner': 'true', - 'TargetMachine': 'MachineX86i', - 'TrackerLogDirectory': 'a_folder', - 'TreatLibWarningAsErrors': 'true', - 'UseUnicodeResponseFiles': 'true', - 'Verbose': 'true'}, - 'Manifest': { - 'AdditionalManifestFiles': 'file1;file2', - 'AdditionalOptions': 'a string1', - 'AssemblyIdentity': 'a string1', - 'ComponentFileName': 'a_file_name', - 'EnableDPIAwareness': 'fal', - 'GenerateCatalogFiles': 'truel', - 'GenerateCategoryTags': 'true', - 'InputResourceManifests': 'a string1', - 'ManifestFromManagedAssembly': 'a_file_name', - 'notgood3': 'bogus', - 'OutputManifestFile': 'a_file_name', - 'OutputResourceManifests': 'a string1', - 'RegistrarScriptFile': 'a_file_name', - 'ReplacementsFile': 'a_file_name', - 'SuppressDependencyElement': 'true', - 'SuppressStartupBanner': 'true', - 'TrackerLogDirectory': 'a_folder', - 'TypeLibraryFile': 'a_file_name', - 'UpdateFileHashes': 'true', - 'UpdateFileHashesSearchPath': 'a_file_name', - 'VerboseOutput': 'true'}, - 'ProjectReference': { - 'LinkLibraryDependencies': 'true', - 'UseLibraryDependencyInputs': 'true'}, - 'ManifestResourceCompile': { - 'ResourceOutputFileName': 'a_file_name'}, - '': { - 'EmbedManifest': 'true', - 'GenerateManifest': 'true', - 'IgnoreImportLibrary': 'true', - 'LinkIncremental': 'false'}}, - self.stderr) - self._ExpectedWarnings([ - 'Warning: unrecognized setting ClCompile/Enableprefast', - 'Warning: unrecognized setting ClCompile/ZZXYZ', - 'Warning: unrecognized setting Manifest/notgood3', - 'Warning: for Manifest/GenerateCatalogFiles, ' - "expected bool; got 'truel'", - 'Warning: for Lib/TargetMachine, unrecognized enumerated value ' - 'MachineX86i', - "Warning: for Manifest/EnableDPIAwareness, expected bool; got 'fal'"]) - - def testConvertToMSBuildSettings_empty(self): - """Tests an empty conversion.""" - msvs_settings = {} - expected_msbuild_settings = {} - actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( - msvs_settings, - self.stderr) - self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) - self._ExpectedWarnings([]) - - def testConvertToMSBuildSettings_minimal(self): - """Tests a minimal conversion.""" - msvs_settings = { - 'VCCLCompilerTool': { - 'AdditionalIncludeDirectories': 'dir1', - 'AdditionalOptions': '/foo', - 'BasicRuntimeChecks': '0', - }, - 'VCLinkerTool': { - 'LinkTimeCodeGeneration': '1', - 'ErrorReporting': '1', - 'DataExecutionPrevention': '2', - }, - } - expected_msbuild_settings = { - 'ClCompile': { - 'AdditionalIncludeDirectories': 'dir1', - 'AdditionalOptions': '/foo', - 'BasicRuntimeChecks': 'Default', - }, - 'Link': { - 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration', - 'LinkErrorReporting': 'PromptImmediately', - 'DataExecutionPrevention': 'true', - }, - } - actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( - msvs_settings, - self.stderr) - self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) - self._ExpectedWarnings([]) - - def testConvertToMSBuildSettings_warnings(self): - """Tests conversion that generates warnings.""" - msvs_settings = { - 'VCCLCompilerTool': { - 'AdditionalIncludeDirectories': '1', - 'AdditionalOptions': '2', - # These are incorrect values: - 'BasicRuntimeChecks': '12', - 'BrowseInformation': '21', - 'UsePrecompiledHeader': '13', - 'GeneratePreprocessedFile': '14'}, - 'VCLinkerTool': { - # These are incorrect values: - 'Driver': '10', - 'LinkTimeCodeGeneration': '31', - 'ErrorReporting': '21', - 'FixedBaseAddress': '6'}, - 'VCResourceCompilerTool': { - # Custom - 'Culture': '1003'}} - expected_msbuild_settings = { - 'ClCompile': { - 'AdditionalIncludeDirectories': '1', - 'AdditionalOptions': '2'}, - 'Link': {}, - 'ResourceCompile': { - # Custom - 'Culture': '0x03eb'}} - actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( - msvs_settings, - self.stderr) - self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) - self._ExpectedWarnings([ - 'Warning: while converting VCCLCompilerTool/BasicRuntimeChecks to ' - 'MSBuild, index value (12) not in expected range [0, 4)', - 'Warning: while converting VCCLCompilerTool/BrowseInformation to ' - 'MSBuild, index value (21) not in expected range [0, 3)', - 'Warning: while converting VCCLCompilerTool/UsePrecompiledHeader to ' - 'MSBuild, index value (13) not in expected range [0, 3)', - 'Warning: while converting VCCLCompilerTool/GeneratePreprocessedFile to ' - 'MSBuild, value must be one of [0, 1, 2]; got 14', - - 'Warning: while converting VCLinkerTool/Driver to ' - 'MSBuild, index value (10) not in expected range [0, 4)', - 'Warning: while converting VCLinkerTool/LinkTimeCodeGeneration to ' - 'MSBuild, index value (31) not in expected range [0, 5)', - 'Warning: while converting VCLinkerTool/ErrorReporting to ' - 'MSBuild, index value (21) not in expected range [0, 3)', - 'Warning: while converting VCLinkerTool/FixedBaseAddress to ' - 'MSBuild, index value (6) not in expected range [0, 3)', - ]) - - def testConvertToMSBuildSettings_full_synthetic(self): - """Tests conversion of all the MSBuild settings.""" - msvs_settings = { - 'VCCLCompilerTool': { - 'AdditionalIncludeDirectories': 'folder1;folder2;folder3', - 'AdditionalOptions': 'a_string', - 'AdditionalUsingDirectories': 'folder1;folder2;folder3', - 'AssemblerListingLocation': 'a_file_name', - 'AssemblerOutput': '0', - 'BasicRuntimeChecks': '1', - 'BrowseInformation': '2', - 'BrowseInformationFile': 'a_file_name', - 'BufferSecurityCheck': 'true', - 'CallingConvention': '0', - 'CompileAs': '1', - 'DebugInformationFormat': '4', - 'DefaultCharIsUnsigned': 'true', - 'Detect64BitPortabilityProblems': 'true', - 'DisableLanguageExtensions': 'true', - 'DisableSpecificWarnings': 'd1;d2;d3', - 'EnableEnhancedInstructionSet': '0', - 'EnableFiberSafeOptimizations': 'true', - 'EnableFunctionLevelLinking': 'true', - 'EnableIntrinsicFunctions': 'true', - 'EnablePREfast': 'true', - 'ErrorReporting': '1', - 'ExceptionHandling': '2', - 'ExpandAttributedSource': 'true', - 'FavorSizeOrSpeed': '0', - 'FloatingPointExceptions': 'true', - 'FloatingPointModel': '1', - 'ForceConformanceInForLoopScope': 'true', - 'ForcedIncludeFiles': 'file1;file2;file3', - 'ForcedUsingFiles': 'file1;file2;file3', - 'GeneratePreprocessedFile': '1', - 'GenerateXMLDocumentationFiles': 'true', - 'IgnoreStandardIncludePath': 'true', - 'InlineFunctionExpansion': '2', - 'KeepComments': 'true', - 'MinimalRebuild': 'true', - 'ObjectFile': 'a_file_name', - 'OmitDefaultLibName': 'true', - 'OmitFramePointers': 'true', - 'OpenMP': 'true', - 'Optimization': '3', - 'PrecompiledHeaderFile': 'a_file_name', - 'PrecompiledHeaderThrough': 'a_file_name', - 'PreprocessorDefinitions': 'd1;d2;d3', - 'ProgramDataBaseFileName': 'a_file_name', - 'RuntimeLibrary': '0', - 'RuntimeTypeInfo': 'true', - 'ShowIncludes': 'true', - 'SmallerTypeCheck': 'true', - 'StringPooling': 'true', - 'StructMemberAlignment': '1', - 'SuppressStartupBanner': 'true', - 'TreatWChar_tAsBuiltInType': 'true', - 'UndefineAllPreprocessorDefinitions': 'true', - 'UndefinePreprocessorDefinitions': 'd1;d2;d3', - 'UseFullPaths': 'true', - 'UsePrecompiledHeader': '1', - 'UseUnicodeResponseFiles': 'true', - 'WarnAsError': 'true', - 'WarningLevel': '2', - 'WholeProgramOptimization': 'true', - 'XMLDocumentationFileName': 'a_file_name'}, - 'VCLinkerTool': { - 'AdditionalDependencies': 'file1;file2;file3', - 'AdditionalLibraryDirectories': 'folder1;folder2;folder3', - 'AdditionalLibraryDirectories_excluded': 'folder1;folder2;folder3', - 'AdditionalManifestDependencies': 'file1;file2;file3', - 'AdditionalOptions': 'a_string', - 'AddModuleNamesToAssembly': 'file1;file2;file3', - 'AllowIsolation': 'true', - 'AssemblyDebug': '0', - 'AssemblyLinkResource': 'file1;file2;file3', - 'BaseAddress': 'a_string', - 'CLRImageType': '1', - 'CLRThreadAttribute': '2', - 'CLRUnmanagedCodeCheck': 'true', - 'DataExecutionPrevention': '0', - 'DelayLoadDLLs': 'file1;file2;file3', - 'DelaySign': 'true', - 'Driver': '1', - 'EmbedManagedResourceFile': 'file1;file2;file3', - 'EnableCOMDATFolding': '0', - 'EnableUAC': 'true', - 'EntryPointSymbol': 'a_string', - 'ErrorReporting': '0', - 'FixedBaseAddress': '1', - 'ForceSymbolReferences': 'file1;file2;file3', - 'FunctionOrder': 'a_file_name', - 'GenerateDebugInformation': 'true', - 'GenerateManifest': 'true', - 'GenerateMapFile': 'true', - 'HeapCommitSize': 'a_string', - 'HeapReserveSize': 'a_string', - 'IgnoreAllDefaultLibraries': 'true', - 'IgnoreDefaultLibraryNames': 'file1;file2;file3', - 'IgnoreEmbeddedIDL': 'true', - 'IgnoreImportLibrary': 'true', - 'ImportLibrary': 'a_file_name', - 'KeyContainer': 'a_file_name', - 'KeyFile': 'a_file_name', - 'LargeAddressAware': '2', - 'LinkIncremental': '1', - 'LinkLibraryDependencies': 'true', - 'LinkTimeCodeGeneration': '2', - 'ManifestFile': 'a_file_name', - 'MapExports': 'true', - 'MapFileName': 'a_file_name', - 'MergedIDLBaseFileName': 'a_file_name', - 'MergeSections': 'a_string', - 'MidlCommandFile': 'a_file_name', - 'ModuleDefinitionFile': 'a_file_name', - 'OptimizeForWindows98': '1', - 'OptimizeReferences': '0', - 'OutputFile': 'a_file_name', - 'PerUserRedirection': 'true', - 'Profile': 'true', - 'ProfileGuidedDatabase': 'a_file_name', - 'ProgramDatabaseFile': 'a_file_name', - 'RandomizedBaseAddress': '1', - 'RegisterOutput': 'true', - 'ResourceOnlyDLL': 'true', - 'SetChecksum': 'true', - 'ShowProgress': '0', - 'StackCommitSize': 'a_string', - 'StackReserveSize': 'a_string', - 'StripPrivateSymbols': 'a_file_name', - 'SubSystem': '2', - 'SupportUnloadOfDelayLoadedDLL': 'true', - 'SuppressStartupBanner': 'true', - 'SwapRunFromCD': 'true', - 'SwapRunFromNet': 'true', - 'TargetMachine': '3', - 'TerminalServerAware': '2', - 'TurnOffAssemblyGeneration': 'true', - 'TypeLibraryFile': 'a_file_name', - 'TypeLibraryResourceID': '33', - 'UACExecutionLevel': '1', - 'UACUIAccess': 'true', - 'UseLibraryDependencyInputs': 'false', - 'UseUnicodeResponseFiles': 'true', - 'Version': 'a_string'}, - 'VCResourceCompilerTool': { - 'AdditionalIncludeDirectories': 'folder1;folder2;folder3', - 'AdditionalOptions': 'a_string', - 'Culture': '1003', - 'IgnoreStandardIncludePath': 'true', - 'PreprocessorDefinitions': 'd1;d2;d3', - 'ResourceOutputFileName': 'a_string', - 'ShowProgress': 'true', - 'SuppressStartupBanner': 'true', - 'UndefinePreprocessorDefinitions': 'd1;d2;d3'}, - 'VCMIDLTool': { - 'AdditionalIncludeDirectories': 'folder1;folder2;folder3', - 'AdditionalOptions': 'a_string', - 'CPreprocessOptions': 'a_string', - 'DefaultCharType': '0', - 'DLLDataFileName': 'a_file_name', - 'EnableErrorChecks': '2', - 'ErrorCheckAllocations': 'true', - 'ErrorCheckBounds': 'true', - 'ErrorCheckEnumRange': 'true', - 'ErrorCheckRefPointers': 'true', - 'ErrorCheckStubData': 'true', - 'GenerateStublessProxies': 'true', - 'GenerateTypeLibrary': 'true', - 'HeaderFileName': 'a_file_name', - 'IgnoreStandardIncludePath': 'true', - 'InterfaceIdentifierFileName': 'a_file_name', - 'MkTypLibCompatible': 'true', - 'OutputDirectory': 'a_string', - 'PreprocessorDefinitions': 'd1;d2;d3', - 'ProxyFileName': 'a_file_name', - 'RedirectOutputAndErrors': 'a_file_name', - 'StructMemberAlignment': '3', - 'SuppressStartupBanner': 'true', - 'TargetEnvironment': '1', - 'TypeLibraryName': 'a_file_name', - 'UndefinePreprocessorDefinitions': 'd1;d2;d3', - 'ValidateParameters': 'true', - 'WarnAsError': 'true', - 'WarningLevel': '4'}, - 'VCLibrarianTool': { - 'AdditionalDependencies': 'file1;file2;file3', - 'AdditionalLibraryDirectories': 'folder1;folder2;folder3', - 'AdditionalLibraryDirectories_excluded': 'folder1;folder2;folder3', - 'AdditionalOptions': 'a_string', - 'ExportNamedFunctions': 'd1;d2;d3', - 'ForceSymbolReferences': 'a_string', - 'IgnoreAllDefaultLibraries': 'true', - 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3', - 'LinkLibraryDependencies': 'true', - 'ModuleDefinitionFile': 'a_file_name', - 'OutputFile': 'a_file_name', - 'SuppressStartupBanner': 'true', - 'UseUnicodeResponseFiles': 'true'}, - 'VCManifestTool': { - 'AdditionalManifestFiles': 'file1;file2;file3', - 'AdditionalOptions': 'a_string', - 'AssemblyIdentity': 'a_string', - 'ComponentFileName': 'a_file_name', - 'DependencyInformationFile': 'a_file_name', - 'EmbedManifest': 'true', - 'GenerateCatalogFiles': 'true', - 'InputResourceManifests': 'a_string', - 'ManifestResourceFile': 'my_name', - 'OutputManifestFile': 'a_file_name', - 'RegistrarScriptFile': 'a_file_name', - 'ReplacementsFile': 'a_file_name', - 'SuppressStartupBanner': 'true', - 'TypeLibraryFile': 'a_file_name', - 'UpdateFileHashes': 'true', - 'UpdateFileHashesSearchPath': 'a_file_name', - 'UseFAT32Workaround': 'true', - 'UseUnicodeResponseFiles': 'true', - 'VerboseOutput': 'true'}} - expected_msbuild_settings = { - 'ClCompile': { - 'AdditionalIncludeDirectories': 'folder1;folder2;folder3', - 'AdditionalOptions': 'a_string /J', - 'AdditionalUsingDirectories': 'folder1;folder2;folder3', - 'AssemblerListingLocation': 'a_file_name', - 'AssemblerOutput': 'NoListing', - 'BasicRuntimeChecks': 'StackFrameRuntimeCheck', - 'BrowseInformation': 'true', - 'BrowseInformationFile': 'a_file_name', - 'BufferSecurityCheck': 'true', - 'CallingConvention': 'Cdecl', - 'CompileAs': 'CompileAsC', - 'DebugInformationFormat': 'EditAndContinue', - 'DisableLanguageExtensions': 'true', - 'DisableSpecificWarnings': 'd1;d2;d3', - 'EnableEnhancedInstructionSet': 'NotSet', - 'EnableFiberSafeOptimizations': 'true', - 'EnablePREfast': 'true', - 'ErrorReporting': 'Prompt', - 'ExceptionHandling': 'Async', - 'ExpandAttributedSource': 'true', - 'FavorSizeOrSpeed': 'Neither', - 'FloatingPointExceptions': 'true', - 'FloatingPointModel': 'Strict', - 'ForceConformanceInForLoopScope': 'true', - 'ForcedIncludeFiles': 'file1;file2;file3', - 'ForcedUsingFiles': 'file1;file2;file3', - 'FunctionLevelLinking': 'true', - 'GenerateXMLDocumentationFiles': 'true', - 'IgnoreStandardIncludePath': 'true', - 'InlineFunctionExpansion': 'AnySuitable', - 'IntrinsicFunctions': 'true', - 'MinimalRebuild': 'true', - 'ObjectFileName': 'a_file_name', - 'OmitDefaultLibName': 'true', - 'OmitFramePointers': 'true', - 'OpenMPSupport': 'true', - 'Optimization': 'Full', - 'PrecompiledHeader': 'Create', - 'PrecompiledHeaderFile': 'a_file_name', - 'PrecompiledHeaderOutputFile': 'a_file_name', - 'PreprocessKeepComments': 'true', - 'PreprocessorDefinitions': 'd1;d2;d3', - 'PreprocessSuppressLineNumbers': 'false', - 'PreprocessToFile': 'true', - 'ProgramDataBaseFileName': 'a_file_name', - 'RuntimeLibrary': 'MultiThreaded', - 'RuntimeTypeInfo': 'true', - 'ShowIncludes': 'true', - 'SmallerTypeCheck': 'true', - 'StringPooling': 'true', - 'StructMemberAlignment': '1Byte', - 'SuppressStartupBanner': 'true', - 'TreatWarningAsError': 'true', - 'TreatWChar_tAsBuiltInType': 'true', - 'UndefineAllPreprocessorDefinitions': 'true', - 'UndefinePreprocessorDefinitions': 'd1;d2;d3', - 'UseFullPaths': 'true', - 'WarningLevel': 'Level2', - 'WholeProgramOptimization': 'true', - 'XMLDocumentationFileName': 'a_file_name'}, - 'Link': { - 'AdditionalDependencies': 'file1;file2;file3', - 'AdditionalLibraryDirectories': 'folder1;folder2;folder3', - 'AdditionalManifestDependencies': 'file1;file2;file3', - 'AdditionalOptions': 'a_string', - 'AddModuleNamesToAssembly': 'file1;file2;file3', - 'AllowIsolation': 'true', - 'AssemblyDebug': '', - 'AssemblyLinkResource': 'file1;file2;file3', - 'BaseAddress': 'a_string', - 'CLRImageType': 'ForceIJWImage', - 'CLRThreadAttribute': 'STAThreadingAttribute', - 'CLRUnmanagedCodeCheck': 'true', - 'DataExecutionPrevention': '', - 'DelayLoadDLLs': 'file1;file2;file3', - 'DelaySign': 'true', - 'Driver': 'Driver', - 'EmbedManagedResourceFile': 'file1;file2;file3', - 'EnableCOMDATFolding': '', - 'EnableUAC': 'true', - 'EntryPointSymbol': 'a_string', - 'FixedBaseAddress': 'false', - 'ForceSymbolReferences': 'file1;file2;file3', - 'FunctionOrder': 'a_file_name', - 'GenerateDebugInformation': 'true', - 'GenerateMapFile': 'true', - 'HeapCommitSize': 'a_string', - 'HeapReserveSize': 'a_string', - 'IgnoreAllDefaultLibraries': 'true', - 'IgnoreEmbeddedIDL': 'true', - 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3', - 'ImportLibrary': 'a_file_name', - 'KeyContainer': 'a_file_name', - 'KeyFile': 'a_file_name', - 'LargeAddressAware': 'true', - 'LinkErrorReporting': 'NoErrorReport', - 'LinkTimeCodeGeneration': 'PGInstrument', - 'ManifestFile': 'a_file_name', - 'MapExports': 'true', - 'MapFileName': 'a_file_name', - 'MergedIDLBaseFileName': 'a_file_name', - 'MergeSections': 'a_string', - 'MidlCommandFile': 'a_file_name', - 'ModuleDefinitionFile': 'a_file_name', - 'NoEntryPoint': 'true', - 'OptimizeReferences': '', - 'OutputFile': 'a_file_name', - 'PerUserRedirection': 'true', - 'Profile': 'true', - 'ProfileGuidedDatabase': 'a_file_name', - 'ProgramDatabaseFile': 'a_file_name', - 'RandomizedBaseAddress': 'false', - 'RegisterOutput': 'true', - 'SetChecksum': 'true', - 'ShowProgress': 'NotSet', - 'StackCommitSize': 'a_string', - 'StackReserveSize': 'a_string', - 'StripPrivateSymbols': 'a_file_name', - 'SubSystem': 'Windows', - 'SupportUnloadOfDelayLoadedDLL': 'true', - 'SuppressStartupBanner': 'true', - 'SwapRunFromCD': 'true', - 'SwapRunFromNET': 'true', - 'TargetMachine': 'MachineARM', - 'TerminalServerAware': 'true', - 'TurnOffAssemblyGeneration': 'true', - 'TypeLibraryFile': 'a_file_name', - 'TypeLibraryResourceID': '33', - 'UACExecutionLevel': 'HighestAvailable', - 'UACUIAccess': 'true', - 'Version': 'a_string'}, - 'ResourceCompile': { - 'AdditionalIncludeDirectories': 'folder1;folder2;folder3', - 'AdditionalOptions': 'a_string', - 'Culture': '0x03eb', - 'IgnoreStandardIncludePath': 'true', - 'PreprocessorDefinitions': 'd1;d2;d3', - 'ResourceOutputFileName': 'a_string', - 'ShowProgress': 'true', - 'SuppressStartupBanner': 'true', - 'UndefinePreprocessorDefinitions': 'd1;d2;d3'}, - 'Midl': { - 'AdditionalIncludeDirectories': 'folder1;folder2;folder3', - 'AdditionalOptions': 'a_string', - 'CPreprocessOptions': 'a_string', - 'DefaultCharType': 'Unsigned', - 'DllDataFileName': 'a_file_name', - 'EnableErrorChecks': 'All', - 'ErrorCheckAllocations': 'true', - 'ErrorCheckBounds': 'true', - 'ErrorCheckEnumRange': 'true', - 'ErrorCheckRefPointers': 'true', - 'ErrorCheckStubData': 'true', - 'GenerateStublessProxies': 'true', - 'GenerateTypeLibrary': 'true', - 'HeaderFileName': 'a_file_name', - 'IgnoreStandardIncludePath': 'true', - 'InterfaceIdentifierFileName': 'a_file_name', - 'MkTypLibCompatible': 'true', - 'OutputDirectory': 'a_string', - 'PreprocessorDefinitions': 'd1;d2;d3', - 'ProxyFileName': 'a_file_name', - 'RedirectOutputAndErrors': 'a_file_name', - 'StructMemberAlignment': '4', - 'SuppressStartupBanner': 'true', - 'TargetEnvironment': 'Win32', - 'TypeLibraryName': 'a_file_name', - 'UndefinePreprocessorDefinitions': 'd1;d2;d3', - 'ValidateAllParameters': 'true', - 'WarnAsError': 'true', - 'WarningLevel': '4'}, - 'Lib': { - 'AdditionalDependencies': 'file1;file2;file3', - 'AdditionalLibraryDirectories': 'folder1;folder2;folder3', - 'AdditionalOptions': 'a_string', - 'ExportNamedFunctions': 'd1;d2;d3', - 'ForceSymbolReferences': 'a_string', - 'IgnoreAllDefaultLibraries': 'true', - 'IgnoreSpecificDefaultLibraries': 'file1;file2;file3', - 'ModuleDefinitionFile': 'a_file_name', - 'OutputFile': 'a_file_name', - 'SuppressStartupBanner': 'true', - 'UseUnicodeResponseFiles': 'true'}, - 'Manifest': { - 'AdditionalManifestFiles': 'file1;file2;file3', - 'AdditionalOptions': 'a_string', - 'AssemblyIdentity': 'a_string', - 'ComponentFileName': 'a_file_name', - 'GenerateCatalogFiles': 'true', - 'InputResourceManifests': 'a_string', - 'OutputManifestFile': 'a_file_name', - 'RegistrarScriptFile': 'a_file_name', - 'ReplacementsFile': 'a_file_name', - 'SuppressStartupBanner': 'true', - 'TypeLibraryFile': 'a_file_name', - 'UpdateFileHashes': 'true', - 'UpdateFileHashesSearchPath': 'a_file_name', - 'VerboseOutput': 'true'}, - 'ManifestResourceCompile': { - 'ResourceOutputFileName': 'my_name'}, - 'ProjectReference': { - 'LinkLibraryDependencies': 'true', - 'UseLibraryDependencyInputs': 'false'}, - '': { - 'EmbedManifest': 'true', - 'GenerateManifest': 'true', - 'IgnoreImportLibrary': 'true', - 'LinkIncremental': 'false'}} - actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( - msvs_settings, - self.stderr) - self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) - self._ExpectedWarnings([]) - - def testConvertToMSBuildSettings_actual(self): - """Tests the conversion of an actual project. - - A VS2008 project with most of the options defined was created through the - VS2008 IDE. It was then converted to VS2010. The tool settings found in - the .vcproj and .vcxproj files were converted to the two dictionaries - msvs_settings and expected_msbuild_settings. - - Note that for many settings, the VS2010 converter adds macros like - %(AdditionalIncludeDirectories) to make sure than inherited values are - included. Since the Gyp projects we generate do not use inheritance, - we removed these macros. They were: - ClCompile: - AdditionalIncludeDirectories: ';%(AdditionalIncludeDirectories)' - AdditionalOptions: ' %(AdditionalOptions)' - AdditionalUsingDirectories: ';%(AdditionalUsingDirectories)' - DisableSpecificWarnings: ';%(DisableSpecificWarnings)', - ForcedIncludeFiles: ';%(ForcedIncludeFiles)', - ForcedUsingFiles: ';%(ForcedUsingFiles)', - PreprocessorDefinitions: ';%(PreprocessorDefinitions)', - UndefinePreprocessorDefinitions: - ';%(UndefinePreprocessorDefinitions)', - Link: - AdditionalDependencies: ';%(AdditionalDependencies)', - AdditionalLibraryDirectories: ';%(AdditionalLibraryDirectories)', - AdditionalManifestDependencies: - ';%(AdditionalManifestDependencies)', - AdditionalOptions: ' %(AdditionalOptions)', - AddModuleNamesToAssembly: ';%(AddModuleNamesToAssembly)', - AssemblyLinkResource: ';%(AssemblyLinkResource)', - DelayLoadDLLs: ';%(DelayLoadDLLs)', - EmbedManagedResourceFile: ';%(EmbedManagedResourceFile)', - ForceSymbolReferences: ';%(ForceSymbolReferences)', - IgnoreSpecificDefaultLibraries: - ';%(IgnoreSpecificDefaultLibraries)', - ResourceCompile: - AdditionalIncludeDirectories: ';%(AdditionalIncludeDirectories)', - AdditionalOptions: ' %(AdditionalOptions)', - PreprocessorDefinitions: ';%(PreprocessorDefinitions)', - Manifest: - AdditionalManifestFiles: ';%(AdditionalManifestFiles)', - AdditionalOptions: ' %(AdditionalOptions)', - InputResourceManifests: ';%(InputResourceManifests)', - """ - msvs_settings = { - 'VCCLCompilerTool': { - 'AdditionalIncludeDirectories': 'dir1', - 'AdditionalOptions': '/more', - 'AdditionalUsingDirectories': 'test', - 'AssemblerListingLocation': '$(IntDir)\\a', - 'AssemblerOutput': '1', - 'BasicRuntimeChecks': '3', - 'BrowseInformation': '1', - 'BrowseInformationFile': '$(IntDir)\\e', - 'BufferSecurityCheck': 'false', - 'CallingConvention': '1', - 'CompileAs': '1', - 'DebugInformationFormat': '4', - 'DefaultCharIsUnsigned': 'true', - 'Detect64BitPortabilityProblems': 'true', - 'DisableLanguageExtensions': 'true', - 'DisableSpecificWarnings': 'abc', - 'EnableEnhancedInstructionSet': '1', - 'EnableFiberSafeOptimizations': 'true', - 'EnableFunctionLevelLinking': 'true', - 'EnableIntrinsicFunctions': 'true', - 'EnablePREfast': 'true', - 'ErrorReporting': '2', - 'ExceptionHandling': '2', - 'ExpandAttributedSource': 'true', - 'FavorSizeOrSpeed': '2', - 'FloatingPointExceptions': 'true', - 'FloatingPointModel': '1', - 'ForceConformanceInForLoopScope': 'false', - 'ForcedIncludeFiles': 'def', - 'ForcedUsingFiles': 'ge', - 'GeneratePreprocessedFile': '2', - 'GenerateXMLDocumentationFiles': 'true', - 'IgnoreStandardIncludePath': 'true', - 'InlineFunctionExpansion': '1', - 'KeepComments': 'true', - 'MinimalRebuild': 'true', - 'ObjectFile': '$(IntDir)\\b', - 'OmitDefaultLibName': 'true', - 'OmitFramePointers': 'true', - 'OpenMP': 'true', - 'Optimization': '3', - 'PrecompiledHeaderFile': '$(IntDir)\\$(TargetName).pche', - 'PrecompiledHeaderThrough': 'StdAfx.hd', - 'PreprocessorDefinitions': 'WIN32;_DEBUG;_CONSOLE', - 'ProgramDataBaseFileName': '$(IntDir)\\vc90b.pdb', - 'RuntimeLibrary': '3', - 'RuntimeTypeInfo': 'false', - 'ShowIncludes': 'true', - 'SmallerTypeCheck': 'true', - 'StringPooling': 'true', - 'StructMemberAlignment': '3', - 'SuppressStartupBanner': 'false', - 'TreatWChar_tAsBuiltInType': 'false', - 'UndefineAllPreprocessorDefinitions': 'true', - 'UndefinePreprocessorDefinitions': 'wer', - 'UseFullPaths': 'true', - 'UsePrecompiledHeader': '0', - 'UseUnicodeResponseFiles': 'false', - 'WarnAsError': 'true', - 'WarningLevel': '3', - 'WholeProgramOptimization': 'true', - 'XMLDocumentationFileName': '$(IntDir)\\c'}, - 'VCLinkerTool': { - 'AdditionalDependencies': 'zx', - 'AdditionalLibraryDirectories': 'asd', - 'AdditionalManifestDependencies': 's2', - 'AdditionalOptions': '/mor2', - 'AddModuleNamesToAssembly': 'd1', - 'AllowIsolation': 'false', - 'AssemblyDebug': '1', - 'AssemblyLinkResource': 'd5', - 'BaseAddress': '23423', - 'CLRImageType': '3', - 'CLRThreadAttribute': '1', - 'CLRUnmanagedCodeCheck': 'true', - 'DataExecutionPrevention': '0', - 'DelayLoadDLLs': 'd4', - 'DelaySign': 'true', - 'Driver': '2', - 'EmbedManagedResourceFile': 'd2', - 'EnableCOMDATFolding': '1', - 'EnableUAC': 'false', - 'EntryPointSymbol': 'f5', - 'ErrorReporting': '2', - 'FixedBaseAddress': '1', - 'ForceSymbolReferences': 'd3', - 'FunctionOrder': 'fssdfsd', - 'GenerateDebugInformation': 'true', - 'GenerateManifest': 'false', - 'GenerateMapFile': 'true', - 'HeapCommitSize': '13', - 'HeapReserveSize': '12', - 'IgnoreAllDefaultLibraries': 'true', - 'IgnoreDefaultLibraryNames': 'flob;flok', - 'IgnoreEmbeddedIDL': 'true', - 'IgnoreImportLibrary': 'true', - 'ImportLibrary': 'f4', - 'KeyContainer': 'f7', - 'KeyFile': 'f6', - 'LargeAddressAware': '2', - 'LinkIncremental': '0', - 'LinkLibraryDependencies': 'false', - 'LinkTimeCodeGeneration': '1', - 'ManifestFile': - '$(IntDir)\\$(TargetFileName).2intermediate.manifest', - 'MapExports': 'true', - 'MapFileName': 'd5', - 'MergedIDLBaseFileName': 'f2', - 'MergeSections': 'f5', - 'MidlCommandFile': 'f1', - 'ModuleDefinitionFile': 'sdsd', - 'OptimizeForWindows98': '2', - 'OptimizeReferences': '2', - 'OutputFile': '$(OutDir)\\$(ProjectName)2.exe', - 'PerUserRedirection': 'true', - 'Profile': 'true', - 'ProfileGuidedDatabase': '$(TargetDir)$(TargetName).pgdd', - 'ProgramDatabaseFile': 'Flob.pdb', - 'RandomizedBaseAddress': '1', - 'RegisterOutput': 'true', - 'ResourceOnlyDLL': 'true', - 'SetChecksum': 'false', - 'ShowProgress': '1', - 'StackCommitSize': '15', - 'StackReserveSize': '14', - 'StripPrivateSymbols': 'd3', - 'SubSystem': '1', - 'SupportUnloadOfDelayLoadedDLL': 'true', - 'SuppressStartupBanner': 'false', - 'SwapRunFromCD': 'true', - 'SwapRunFromNet': 'true', - 'TargetMachine': '1', - 'TerminalServerAware': '1', - 'TurnOffAssemblyGeneration': 'true', - 'TypeLibraryFile': 'f3', - 'TypeLibraryResourceID': '12', - 'UACExecutionLevel': '2', - 'UACUIAccess': 'true', - 'UseLibraryDependencyInputs': 'true', - 'UseUnicodeResponseFiles': 'false', - 'Version': '333'}, - 'VCResourceCompilerTool': { - 'AdditionalIncludeDirectories': 'f3', - 'AdditionalOptions': '/more3', - 'Culture': '3084', - 'IgnoreStandardIncludePath': 'true', - 'PreprocessorDefinitions': '_UNICODE;UNICODE2', - 'ResourceOutputFileName': '$(IntDir)/$(InputName)3.res', - 'ShowProgress': 'true'}, - 'VCManifestTool': { - 'AdditionalManifestFiles': 'sfsdfsd', - 'AdditionalOptions': 'afdsdafsd', - 'AssemblyIdentity': 'sddfdsadfsa', - 'ComponentFileName': 'fsdfds', - 'DependencyInformationFile': '$(IntDir)\\mt.depdfd', - 'EmbedManifest': 'false', - 'GenerateCatalogFiles': 'true', - 'InputResourceManifests': 'asfsfdafs', - 'ManifestResourceFile': - '$(IntDir)\\$(TargetFileName).embed.manifest.resfdsf', - 'OutputManifestFile': '$(TargetPath).manifestdfs', - 'RegistrarScriptFile': 'sdfsfd', - 'ReplacementsFile': 'sdffsd', - 'SuppressStartupBanner': 'false', - 'TypeLibraryFile': 'sfsd', - 'UpdateFileHashes': 'true', - 'UpdateFileHashesSearchPath': 'sfsd', - 'UseFAT32Workaround': 'true', - 'UseUnicodeResponseFiles': 'false', - 'VerboseOutput': 'true'}} - expected_msbuild_settings = { - 'ClCompile': { - 'AdditionalIncludeDirectories': 'dir1', - 'AdditionalOptions': '/more /J', - 'AdditionalUsingDirectories': 'test', - 'AssemblerListingLocation': '$(IntDir)a', - 'AssemblerOutput': 'AssemblyCode', - 'BasicRuntimeChecks': 'EnableFastChecks', - 'BrowseInformation': 'true', - 'BrowseInformationFile': '$(IntDir)e', - 'BufferSecurityCheck': 'false', - 'CallingConvention': 'FastCall', - 'CompileAs': 'CompileAsC', - 'DebugInformationFormat': 'EditAndContinue', - 'DisableLanguageExtensions': 'true', - 'DisableSpecificWarnings': 'abc', - 'EnableEnhancedInstructionSet': 'StreamingSIMDExtensions', - 'EnableFiberSafeOptimizations': 'true', - 'EnablePREfast': 'true', - 'ErrorReporting': 'Queue', - 'ExceptionHandling': 'Async', - 'ExpandAttributedSource': 'true', - 'FavorSizeOrSpeed': 'Size', - 'FloatingPointExceptions': 'true', - 'FloatingPointModel': 'Strict', - 'ForceConformanceInForLoopScope': 'false', - 'ForcedIncludeFiles': 'def', - 'ForcedUsingFiles': 'ge', - 'FunctionLevelLinking': 'true', - 'GenerateXMLDocumentationFiles': 'true', - 'IgnoreStandardIncludePath': 'true', - 'InlineFunctionExpansion': 'OnlyExplicitInline', - 'IntrinsicFunctions': 'true', - 'MinimalRebuild': 'true', - 'ObjectFileName': '$(IntDir)b', - 'OmitDefaultLibName': 'true', - 'OmitFramePointers': 'true', - 'OpenMPSupport': 'true', - 'Optimization': 'Full', - 'PrecompiledHeader': 'NotUsing', # Actual conversion gives '' - 'PrecompiledHeaderFile': 'StdAfx.hd', - 'PrecompiledHeaderOutputFile': '$(IntDir)$(TargetName).pche', - 'PreprocessKeepComments': 'true', - 'PreprocessorDefinitions': 'WIN32;_DEBUG;_CONSOLE', - 'PreprocessSuppressLineNumbers': 'true', - 'PreprocessToFile': 'true', - 'ProgramDataBaseFileName': '$(IntDir)vc90b.pdb', - 'RuntimeLibrary': 'MultiThreadedDebugDLL', - 'RuntimeTypeInfo': 'false', - 'ShowIncludes': 'true', - 'SmallerTypeCheck': 'true', - 'StringPooling': 'true', - 'StructMemberAlignment': '4Bytes', - 'SuppressStartupBanner': 'false', - 'TreatWarningAsError': 'true', - 'TreatWChar_tAsBuiltInType': 'false', - 'UndefineAllPreprocessorDefinitions': 'true', - 'UndefinePreprocessorDefinitions': 'wer', - 'UseFullPaths': 'true', - 'WarningLevel': 'Level3', - 'WholeProgramOptimization': 'true', - 'XMLDocumentationFileName': '$(IntDir)c'}, - 'Link': { - 'AdditionalDependencies': 'zx', - 'AdditionalLibraryDirectories': 'asd', - 'AdditionalManifestDependencies': 's2', - 'AdditionalOptions': '/mor2', - 'AddModuleNamesToAssembly': 'd1', - 'AllowIsolation': 'false', - 'AssemblyDebug': 'true', - 'AssemblyLinkResource': 'd5', - 'BaseAddress': '23423', - 'CLRImageType': 'ForceSafeILImage', - 'CLRThreadAttribute': 'MTAThreadingAttribute', - 'CLRUnmanagedCodeCheck': 'true', - 'DataExecutionPrevention': '', - 'DelayLoadDLLs': 'd4', - 'DelaySign': 'true', - 'Driver': 'UpOnly', - 'EmbedManagedResourceFile': 'd2', - 'EnableCOMDATFolding': 'false', - 'EnableUAC': 'false', - 'EntryPointSymbol': 'f5', - 'FixedBaseAddress': 'false', - 'ForceSymbolReferences': 'd3', - 'FunctionOrder': 'fssdfsd', - 'GenerateDebugInformation': 'true', - 'GenerateMapFile': 'true', - 'HeapCommitSize': '13', - 'HeapReserveSize': '12', - 'IgnoreAllDefaultLibraries': 'true', - 'IgnoreEmbeddedIDL': 'true', - 'IgnoreSpecificDefaultLibraries': 'flob;flok', - 'ImportLibrary': 'f4', - 'KeyContainer': 'f7', - 'KeyFile': 'f6', - 'LargeAddressAware': 'true', - 'LinkErrorReporting': 'QueueForNextLogin', - 'LinkTimeCodeGeneration': 'UseLinkTimeCodeGeneration', - 'ManifestFile': '$(IntDir)$(TargetFileName).2intermediate.manifest', - 'MapExports': 'true', - 'MapFileName': 'd5', - 'MergedIDLBaseFileName': 'f2', - 'MergeSections': 'f5', - 'MidlCommandFile': 'f1', - 'ModuleDefinitionFile': 'sdsd', - 'NoEntryPoint': 'true', - 'OptimizeReferences': 'true', - 'OutputFile': '$(OutDir)$(ProjectName)2.exe', - 'PerUserRedirection': 'true', - 'Profile': 'true', - 'ProfileGuidedDatabase': '$(TargetDir)$(TargetName).pgdd', - 'ProgramDatabaseFile': 'Flob.pdb', - 'RandomizedBaseAddress': 'false', - 'RegisterOutput': 'true', - 'SetChecksum': 'false', - 'ShowProgress': 'LinkVerbose', - 'StackCommitSize': '15', - 'StackReserveSize': '14', - 'StripPrivateSymbols': 'd3', - 'SubSystem': 'Console', - 'SupportUnloadOfDelayLoadedDLL': 'true', - 'SuppressStartupBanner': 'false', - 'SwapRunFromCD': 'true', - 'SwapRunFromNET': 'true', - 'TargetMachine': 'MachineX86', - 'TerminalServerAware': 'false', - 'TurnOffAssemblyGeneration': 'true', - 'TypeLibraryFile': 'f3', - 'TypeLibraryResourceID': '12', - 'UACExecutionLevel': 'RequireAdministrator', - 'UACUIAccess': 'true', - 'Version': '333'}, - 'ResourceCompile': { - 'AdditionalIncludeDirectories': 'f3', - 'AdditionalOptions': '/more3', - 'Culture': '0x0c0c', - 'IgnoreStandardIncludePath': 'true', - 'PreprocessorDefinitions': '_UNICODE;UNICODE2', - 'ResourceOutputFileName': '$(IntDir)%(Filename)3.res', - 'ShowProgress': 'true'}, - 'Manifest': { - 'AdditionalManifestFiles': 'sfsdfsd', - 'AdditionalOptions': 'afdsdafsd', - 'AssemblyIdentity': 'sddfdsadfsa', - 'ComponentFileName': 'fsdfds', - 'GenerateCatalogFiles': 'true', - 'InputResourceManifests': 'asfsfdafs', - 'OutputManifestFile': '$(TargetPath).manifestdfs', - 'RegistrarScriptFile': 'sdfsfd', - 'ReplacementsFile': 'sdffsd', - 'SuppressStartupBanner': 'false', - 'TypeLibraryFile': 'sfsd', - 'UpdateFileHashes': 'true', - 'UpdateFileHashesSearchPath': 'sfsd', - 'VerboseOutput': 'true'}, - 'ProjectReference': { - 'LinkLibraryDependencies': 'false', - 'UseLibraryDependencyInputs': 'true'}, - '': { - 'EmbedManifest': 'false', - 'GenerateManifest': 'false', - 'IgnoreImportLibrary': 'true', - 'LinkIncremental': '' - }, - 'ManifestResourceCompile': { - 'ResourceOutputFileName': - '$(IntDir)$(TargetFileName).embed.manifest.resfdsf'} - } - actual_msbuild_settings = MSVSSettings.ConvertToMSBuildSettings( - msvs_settings, - self.stderr) - self.assertEqual(expected_msbuild_settings, actual_msbuild_settings) - self._ExpectedWarnings([]) - - -if __name__ == '__main__': - unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py deleted file mode 100644 index 74e529a17f1dc..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSToolFile.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2012 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. - -"""Visual Studio project reader/writer.""" - -import gyp.common -import gyp.easy_xml as easy_xml - - -class Writer(object): - """Visual Studio XML tool file writer.""" - - def __init__(self, tool_file_path, name): - """Initializes the tool file. - - Args: - tool_file_path: Path to the tool file. - name: Name of the tool file. - """ - self.tool_file_path = tool_file_path - self.name = name - self.rules_section = ['Rules'] - - def AddCustomBuildRule(self, name, cmd, description, - additional_dependencies, - outputs, extensions): - """Adds a rule to the tool file. - - Args: - name: Name of the rule. - description: Description of the rule. - cmd: Command line of the rule. - additional_dependencies: other files which may trigger the rule. - outputs: outputs of the rule. - extensions: extensions handled by the rule. - """ - rule = ['CustomBuildRule', - {'Name': name, - 'ExecutionDescription': description, - 'CommandLine': cmd, - 'Outputs': ';'.join(outputs), - 'FileExtensions': ';'.join(extensions), - 'AdditionalDependencies': - ';'.join(additional_dependencies) - }] - self.rules_section.append(rule) - - def WriteIfChanged(self): - """Writes the tool file.""" - content = ['VisualStudioToolFile', - {'Version': '8.00', - 'Name': self.name - }, - self.rules_section - ] - easy_xml.WriteXmlIfChanged(content, self.tool_file_path, - encoding="Windows-1252") diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py deleted file mode 100644 index 6c07e9a893bac..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUserFile.py +++ /dev/null @@ -1,147 +0,0 @@ -# Copyright (c) 2012 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. - -"""Visual Studio user preferences file writer.""" - -import os -import re -import socket # for gethostname - -import gyp.common -import gyp.easy_xml as easy_xml - - -#------------------------------------------------------------------------------ - -def _FindCommandInPath(command): - """If there are no slashes in the command given, this function - searches the PATH env to find the given command, and converts it - to an absolute path. We have to do this because MSVS is looking - for an actual file to launch a debugger on, not just a command - line. Note that this happens at GYP time, so anything needing to - be built needs to have a full path.""" - if '/' in command or '\\' in command: - # If the command already has path elements (either relative or - # absolute), then assume it is constructed properly. - return command - else: - # Search through the path list and find an existing file that - # we can access. - paths = os.environ.get('PATH','').split(os.pathsep) - for path in paths: - item = os.path.join(path, command) - if os.path.isfile(item) and os.access(item, os.X_OK): - return item - return command - -def _QuoteWin32CommandLineArgs(args): - new_args = [] - for arg in args: - # Replace all double-quotes with double-double-quotes to escape - # them for cmd shell, and then quote the whole thing if there - # are any. - if arg.find('"') != -1: - arg = '""'.join(arg.split('"')) - arg = '"%s"' % arg - - # Otherwise, if there are any spaces, quote the whole arg. - elif re.search(r'[ \t\n]', arg): - arg = '"%s"' % arg - new_args.append(arg) - return new_args - -class Writer(object): - """Visual Studio XML user user file writer.""" - - def __init__(self, user_file_path, version, name): - """Initializes the user file. - - Args: - user_file_path: Path to the user file. - version: Version info. - name: Name of the user file. - """ - self.user_file_path = user_file_path - self.version = version - self.name = name - self.configurations = {} - - def AddConfig(self, name): - """Adds a configuration to the project. - - Args: - name: Configuration name. - """ - self.configurations[name] = ['Configuration', {'Name': name}] - - def AddDebugSettings(self, config_name, command, environment = {}, - working_directory=""): - """Adds a DebugSettings node to the user file for a particular config. - - Args: - command: command line to run. First element in the list is the - executable. All elements of the command will be quoted if - necessary. - working_directory: other files which may trigger the rule. (optional) - """ - command = _QuoteWin32CommandLineArgs(command) - - abs_command = _FindCommandInPath(command[0]) - - if environment and isinstance(environment, dict): - env_list = ['%s="%s"' % (key, val) - for (key,val) in environment.iteritems()] - environment = ' '.join(env_list) - else: - environment = '' - - n_cmd = ['DebugSettings', - {'Command': abs_command, - 'WorkingDirectory': working_directory, - 'CommandArguments': " ".join(command[1:]), - 'RemoteMachine': socket.gethostname(), - 'Environment': environment, - 'EnvironmentMerge': 'true', - # Currently these are all "dummy" values that we're just setting - # in the default manner that MSVS does it. We could use some of - # these to add additional capabilities, I suppose, but they might - # not have parity with other platforms then. - 'Attach': 'false', - 'DebuggerType': '3', # 'auto' debugger - 'Remote': '1', - 'RemoteCommand': '', - 'HttpUrl': '', - 'PDBPath': '', - 'SQLDebugging': '', - 'DebuggerFlavor': '0', - 'MPIRunCommand': '', - 'MPIRunArguments': '', - 'MPIRunWorkingDirectory': '', - 'ApplicationCommand': '', - 'ApplicationArguments': '', - 'ShimCommand': '', - 'MPIAcceptMode': '', - 'MPIAcceptFilter': '' - }] - - # Find the config, and add it if it doesn't exist. - if config_name not in self.configurations: - self.AddConfig(config_name) - - # Add the DebugSettings onto the appropriate config. - self.configurations[config_name].append(n_cmd) - - def WriteIfChanged(self): - """Writes the user file.""" - configs = ['Configurations'] - for config, spec in sorted(self.configurations.iteritems()): - configs.append(spec) - - content = ['VisualStudioUserFile', - {'Version': self.version.ProjectVersion(), - 'Name': self.name - }, - configs] - easy_xml.WriteXmlIfChanged(content, self.user_file_path, - encoding="Windows-1252") diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py deleted file mode 100644 index 0b32e91180784..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSUtil.py +++ /dev/null @@ -1,270 +0,0 @@ -# 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. - -"""Utility functions shared amongst the Windows generators.""" - -import copy -import os - - -# A dictionary mapping supported target types to extensions. -TARGET_TYPE_EXT = { - 'executable': 'exe', - 'loadable_module': 'dll', - 'shared_library': 'dll', - 'static_library': 'lib', -} - - -def _GetLargePdbShimCcPath(): - """Returns the path of the large_pdb_shim.cc file.""" - this_dir = os.path.abspath(os.path.dirname(__file__)) - src_dir = os.path.abspath(os.path.join(this_dir, '..', '..')) - win_data_dir = os.path.join(src_dir, 'data', 'win') - large_pdb_shim_cc = os.path.join(win_data_dir, 'large-pdb-shim.cc') - return large_pdb_shim_cc - - -def _DeepCopySomeKeys(in_dict, keys): - """Performs a partial deep-copy on |in_dict|, only copying the keys in |keys|. - - Arguments: - in_dict: The dictionary to copy. - keys: The keys to be copied. If a key is in this list and doesn't exist in - |in_dict| this is not an error. - Returns: - The partially deep-copied dictionary. - """ - d = {} - for key in keys: - if key not in in_dict: - continue - d[key] = copy.deepcopy(in_dict[key]) - return d - - -def _SuffixName(name, suffix): - """Add a suffix to the end of a target. - - Arguments: - name: name of the target (foo#target) - suffix: the suffix to be added - Returns: - Target name with suffix added (foo_suffix#target) - """ - parts = name.rsplit('#', 1) - parts[0] = '%s_%s' % (parts[0], suffix) - return '#'.join(parts) - - -def _ShardName(name, number): - """Add a shard number to the end of a target. - - Arguments: - name: name of the target (foo#target) - number: shard number - Returns: - Target name with shard added (foo_1#target) - """ - return _SuffixName(name, str(number)) - - -def ShardTargets(target_list, target_dicts): - """Shard some targets apart to work around the linkers limits. - - Arguments: - target_list: List of target pairs: 'base/base.gyp:base'. - target_dicts: Dict of target properties keyed on target pair. - Returns: - Tuple of the new sharded versions of the inputs. - """ - # Gather the targets to shard, and how many pieces. - targets_to_shard = {} - for t in target_dicts: - shards = int(target_dicts[t].get('msvs_shard', 0)) - if shards: - targets_to_shard[t] = shards - # Shard target_list. - new_target_list = [] - for t in target_list: - if t in targets_to_shard: - for i in range(targets_to_shard[t]): - new_target_list.append(_ShardName(t, i)) - else: - new_target_list.append(t) - # Shard target_dict. - new_target_dicts = {} - for t in target_dicts: - if t in targets_to_shard: - for i in range(targets_to_shard[t]): - name = _ShardName(t, i) - new_target_dicts[name] = copy.copy(target_dicts[t]) - new_target_dicts[name]['target_name'] = _ShardName( - new_target_dicts[name]['target_name'], i) - sources = new_target_dicts[name].get('sources', []) - new_sources = [] - for pos in range(i, len(sources), targets_to_shard[t]): - new_sources.append(sources[pos]) - new_target_dicts[name]['sources'] = new_sources - else: - new_target_dicts[t] = target_dicts[t] - # Shard dependencies. - for t in new_target_dicts: - for deptype in ('dependencies', 'dependencies_original'): - dependencies = copy.copy(new_target_dicts[t].get(deptype, [])) - new_dependencies = [] - for d in dependencies: - if d in targets_to_shard: - for i in range(targets_to_shard[d]): - new_dependencies.append(_ShardName(d, i)) - else: - new_dependencies.append(d) - new_target_dicts[t][deptype] = new_dependencies - - return (new_target_list, new_target_dicts) - - -def _GetPdbPath(target_dict, config_name, vars): - """Returns the path to the PDB file that will be generated by a given - configuration. - - The lookup proceeds as follows: - - Look for an explicit path in the VCLinkerTool configuration block. - - Look for an 'msvs_large_pdb_path' variable. - - Use '<(PRODUCT_DIR)/<(product_name).(exe|dll).pdb' if 'product_name' is - specified. - - Use '<(PRODUCT_DIR)/<(target_name).(exe|dll).pdb'. - - Arguments: - target_dict: The target dictionary to be searched. - config_name: The name of the configuration of interest. - vars: A dictionary of common GYP variables with generator-specific values. - Returns: - The path of the corresponding PDB file. - """ - config = target_dict['configurations'][config_name] - msvs = config.setdefault('msvs_settings', {}) - - linker = msvs.get('VCLinkerTool', {}) - - pdb_path = linker.get('ProgramDatabaseFile') - if pdb_path: - return pdb_path - - variables = target_dict.get('variables', {}) - pdb_path = variables.get('msvs_large_pdb_path', None) - if pdb_path: - return pdb_path - - - pdb_base = target_dict.get('product_name', target_dict['target_name']) - pdb_base = '%s.%s.pdb' % (pdb_base, TARGET_TYPE_EXT[target_dict['type']]) - pdb_path = vars['PRODUCT_DIR'] + '/' + pdb_base - - return pdb_path - - -def InsertLargePdbShims(target_list, target_dicts, vars): - """Insert a shim target that forces the linker to use 4KB pagesize PDBs. - - This is a workaround for targets with PDBs greater than 1GB in size, the - limit for the 1KB pagesize PDBs created by the linker by default. - - Arguments: - target_list: List of target pairs: 'base/base.gyp:base'. - target_dicts: Dict of target properties keyed on target pair. - vars: A dictionary of common GYP variables with generator-specific values. - Returns: - Tuple of the shimmed version of the inputs. - """ - # Determine which targets need shimming. - targets_to_shim = [] - for t in target_dicts: - target_dict = target_dicts[t] - - # We only want to shim targets that have msvs_large_pdb enabled. - if not int(target_dict.get('msvs_large_pdb', 0)): - continue - # This is intended for executable, shared_library and loadable_module - # targets where every configuration is set up to produce a PDB output. - # If any of these conditions is not true then the shim logic will fail - # below. - targets_to_shim.append(t) - - large_pdb_shim_cc = _GetLargePdbShimCcPath() - - for t in targets_to_shim: - target_dict = target_dicts[t] - target_name = target_dict.get('target_name') - - base_dict = _DeepCopySomeKeys(target_dict, - ['configurations', 'default_configuration', 'toolset']) - - # This is the dict for copying the source file (part of the GYP tree) - # to the intermediate directory of the project. This is necessary because - # we can't always build a relative path to the shim source file (on Windows - # GYP and the project may be on different drives), and Ninja hates absolute - # paths (it ends up generating the .obj and .obj.d alongside the source - # file, polluting GYPs tree). - copy_suffix = 'large_pdb_copy' - copy_target_name = target_name + '_' + copy_suffix - full_copy_target_name = _SuffixName(t, copy_suffix) - shim_cc_basename = os.path.basename(large_pdb_shim_cc) - shim_cc_dir = vars['SHARED_INTERMEDIATE_DIR'] + '/' + copy_target_name - shim_cc_path = shim_cc_dir + '/' + shim_cc_basename - copy_dict = copy.deepcopy(base_dict) - copy_dict['target_name'] = copy_target_name - copy_dict['type'] = 'none' - copy_dict['sources'] = [ large_pdb_shim_cc ] - copy_dict['copies'] = [{ - 'destination': shim_cc_dir, - 'files': [ large_pdb_shim_cc ] - }] - - # This is the dict for the PDB generating shim target. It depends on the - # copy target. - shim_suffix = 'large_pdb_shim' - shim_target_name = target_name + '_' + shim_suffix - full_shim_target_name = _SuffixName(t, shim_suffix) - shim_dict = copy.deepcopy(base_dict) - shim_dict['target_name'] = shim_target_name - shim_dict['type'] = 'static_library' - shim_dict['sources'] = [ shim_cc_path ] - shim_dict['dependencies'] = [ full_copy_target_name ] - - # Set up the shim to output its PDB to the same location as the final linker - # target. - for config_name, config in shim_dict.get('configurations').iteritems(): - pdb_path = _GetPdbPath(target_dict, config_name, vars) - - # A few keys that we don't want to propagate. - for key in ['msvs_precompiled_header', 'msvs_precompiled_source', 'test']: - config.pop(key, None) - - msvs = config.setdefault('msvs_settings', {}) - - # Update the compiler directives in the shim target. - compiler = msvs.setdefault('VCCLCompilerTool', {}) - compiler['DebugInformationFormat'] = '3' - compiler['ProgramDataBaseFileName'] = pdb_path - - # Set the explicit PDB path in the appropriate configuration of the - # original target. - config = target_dict['configurations'][config_name] - msvs = config.setdefault('msvs_settings', {}) - linker = msvs.setdefault('VCLinkerTool', {}) - linker['GenerateDebugInformation'] = 'true' - linker['ProgramDatabaseFile'] = pdb_path - - # Add the new targets. They must go to the beginning of the list so that - # the dependency generation works as expected in ninja. - target_list.insert(0, full_copy_target_name) - target_list.insert(0, full_shim_target_name) - target_dicts[full_copy_target_name] = copy_dict - target_dicts[full_shim_target_name] = shim_dict - - # Update the original target to depend on the shim target. - target_dict.setdefault('dependencies', []).append(full_shim_target_name) - - return (target_list, target_dicts) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py deleted file mode 100644 index d9bfa684fa30c..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/MSVSVersion.py +++ /dev/null @@ -1,443 +0,0 @@ -# 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. - -"""Handle version information related to Visual Stuio.""" - -import errno -import os -import re -import subprocess -import sys -import gyp -import glob - - -class VisualStudioVersion(object): - """Information regarding a version of Visual Studio.""" - - def __init__(self, short_name, description, - solution_version, project_version, flat_sln, uses_vcxproj, - path, sdk_based, default_toolset=None): - self.short_name = short_name - self.description = description - self.solution_version = solution_version - self.project_version = project_version - self.flat_sln = flat_sln - self.uses_vcxproj = uses_vcxproj - self.path = path - self.sdk_based = sdk_based - self.default_toolset = default_toolset - - def ShortName(self): - return self.short_name - - def Description(self): - """Get the full description of the version.""" - return self.description - - def SolutionVersion(self): - """Get the version number of the sln files.""" - return self.solution_version - - def ProjectVersion(self): - """Get the version number of the vcproj or vcxproj files.""" - return self.project_version - - def FlatSolution(self): - return self.flat_sln - - def UsesVcxproj(self): - """Returns true if this version uses a vcxproj file.""" - return self.uses_vcxproj - - def ProjectExtension(self): - """Returns the file extension for the project.""" - return self.uses_vcxproj and '.vcxproj' or '.vcproj' - - def Path(self): - """Returns the path to Visual Studio installation.""" - return self.path - - def ToolPath(self, tool): - """Returns the path to a given compiler tool. """ - return os.path.normpath(os.path.join(self.path, "VC/bin", tool)) - - def DefaultToolset(self): - """Returns the msbuild toolset version that will be used in the absence - of a user override.""" - return self.default_toolset - - def SetupScript(self, target_arch): - """Returns a command (with arguments) to be used to set up the - environment.""" - # Check if we are running in the SDK command line environment and use - # the setup script from the SDK if so. |target_arch| should be either - # 'x86' or 'x64'. - assert target_arch in ('x86', 'x64') - sdk_dir = os.environ.get('WindowsSDKDir') - if self.sdk_based and sdk_dir: - return [os.path.normpath(os.path.join(sdk_dir, 'Bin/SetEnv.Cmd')), - '/' + target_arch] - else: - # We don't use VC/vcvarsall.bat for x86 because vcvarsall calls - # vcvars32, which it can only find if VS??COMNTOOLS is set, which it - # isn't always. - if target_arch == 'x86': - if self.short_name >= '2013' and self.short_name[-1] != 'e' and ( - os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or - os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64'): - # VS2013 and later, non-Express have a x64-x86 cross that we want - # to prefer. - return [os.path.normpath( - os.path.join(self.path, 'VC/vcvarsall.bat')), 'amd64_x86'] - # Otherwise, the standard x86 compiler. - return [os.path.normpath( - os.path.join(self.path, 'Common7/Tools/vsvars32.bat'))] - else: - assert target_arch == 'x64' - arg = 'x86_amd64' - # 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'): - arg = 'amd64' - return [os.path.normpath( - os.path.join(self.path, 'VC/vcvarsall.bat')), arg] - - -def _RegistryQueryBase(sysdir, key, value): - """Use reg.exe to read a particular key. - - While ideally we might use the win32 module, we would like gyp to be - python neutral, so for instance cygwin python lacks this module. - - Arguments: - sysdir: The system subdirectory to attempt to launch reg.exe from. - key: The registry key to read from. - value: The particular value to read. - Return: - stdout from reg.exe, or None for failure. - """ - # Skip if not on Windows or Python Win32 setup issue - if sys.platform not in ('win32', 'cygwin'): - return None - # Setup params to pass to and attempt to launch reg.exe - cmd = [os.path.join(os.environ.get('WINDIR', ''), sysdir, 'reg.exe'), - 'query', key] - if value: - cmd.extend(['/v', value]) - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - # Obtain the stdout from reg.exe, reading to the end so p.returncode is valid - # Note that the error text may be in [1] in some cases - text = p.communicate()[0] - # Check return code from reg.exe; officially 0==success and 1==error - if p.returncode: - return None - return text - - -def _RegistryQuery(key, value=None): - r"""Use reg.exe to read a particular key through _RegistryQueryBase. - - First tries to launch from %WinDir%\Sysnative to avoid WoW64 redirection. If - that fails, it falls back to System32. Sysnative is available on Vista and - up and available on Windows Server 2003 and XP through KB patch 942589. Note - that Sysnative will always fail if using 64-bit python due to it being a - virtual directory and System32 will work correctly in the first place. - - KB 942589 - http://support.microsoft.com/kb/942589/en-us. - - Arguments: - key: The registry key. - value: The particular registry value to read (optional). - Return: - stdout from reg.exe, or None for failure. - """ - text = None - try: - text = _RegistryQueryBase('Sysnative', key, value) - except OSError, e: - if e.errno == errno.ENOENT: - text = _RegistryQueryBase('System32', key, value) - else: - raise - return text - - -def _RegistryGetValueUsingWinReg(key, value): - """Use the _winreg module to obtain the value of a registry key. - - Args: - key: The registry key. - value: The particular registry value to read. - Return: - contents of the registry key's value, or None on failure. Throws - ImportError if _winreg is unavailable. - """ - import _winreg - try: - root, subkey = key.split('\\', 1) - assert root == 'HKLM' # Only need HKLM for now. - with _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, subkey) as hkey: - return _winreg.QueryValueEx(hkey, value)[0] - except WindowsError: - return None - - -def _RegistryGetValue(key, value): - """Use _winreg or reg.exe to obtain the value of a registry key. - - Using _winreg is preferable because it solves an issue on some corporate - environments where access to reg.exe is locked down. However, we still need - to fallback to reg.exe for the case where the _winreg module is not available - (for example in cygwin python). - - Args: - key: The registry key. - value: The particular registry value to read. - Return: - contents of the registry key's value, or None on failure. - """ - try: - return _RegistryGetValueUsingWinReg(key, value) - except ImportError: - pass - - # Fallback to reg.exe if we fail to import _winreg. - text = _RegistryQuery(key, value) - if not text: - return None - # Extract value. - match = re.search(r'REG_\w+\s+([^\r]+)\r\n', text) - if not match: - return None - return match.group(1) - - -def _CreateVersion(name, path, sdk_based=False): - """Sets up MSVS project generation. - - Setup is based off the GYP_MSVS_VERSION environment variable or whatever is - autodetected if GYP_MSVS_VERSION is not explicitly specified. If a version is - passed in that doesn't match a value in versions python will throw a error. - """ - if path: - path = os.path.normpath(path) - versions = { - '2015': VisualStudioVersion('2015', - 'Visual Studio 2015', - solution_version='12.00', - project_version='14.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v140'), - '2013': VisualStudioVersion('2013', - 'Visual Studio 2013', - solution_version='13.00', - project_version='12.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v120'), - '2013e': VisualStudioVersion('2013e', - 'Visual Studio 2013', - solution_version='13.00', - project_version='12.0', - flat_sln=True, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v120'), - '2012': VisualStudioVersion('2012', - 'Visual Studio 2012', - solution_version='12.00', - project_version='4.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v110'), - '2012e': VisualStudioVersion('2012e', - 'Visual Studio 2012', - solution_version='12.00', - project_version='4.0', - flat_sln=True, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based, - default_toolset='v110'), - '2010': VisualStudioVersion('2010', - 'Visual Studio 2010', - solution_version='11.00', - project_version='4.0', - flat_sln=False, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based), - '2010e': VisualStudioVersion('2010e', - 'Visual C++ Express 2010', - solution_version='11.00', - project_version='4.0', - flat_sln=True, - uses_vcxproj=True, - path=path, - sdk_based=sdk_based), - '2008': VisualStudioVersion('2008', - 'Visual Studio 2008', - solution_version='10.00', - project_version='9.00', - flat_sln=False, - uses_vcxproj=False, - path=path, - sdk_based=sdk_based), - '2008e': VisualStudioVersion('2008e', - 'Visual Studio 2008', - solution_version='10.00', - project_version='9.00', - flat_sln=True, - uses_vcxproj=False, - path=path, - sdk_based=sdk_based), - '2005': VisualStudioVersion('2005', - 'Visual Studio 2005', - solution_version='9.00', - project_version='8.00', - flat_sln=False, - uses_vcxproj=False, - path=path, - sdk_based=sdk_based), - '2005e': VisualStudioVersion('2005e', - 'Visual Studio 2005', - solution_version='9.00', - project_version='8.00', - flat_sln=True, - uses_vcxproj=False, - path=path, - sdk_based=sdk_based), - } - return versions[str(name)] - - -def _ConvertToCygpath(path): - """Convert to cygwin path if we are using cygwin.""" - if sys.platform == 'cygwin': - p = subprocess.Popen(['cygpath', path], stdout=subprocess.PIPE) - path = p.communicate()[0].strip() - return path - - -def _DetectVisualStudioVersions(versions_to_check, force_express): - """Collect the list of installed visual studio versions. - - Returns: - A list of visual studio versions installed in descending order of - usage preference. - Base this on the registry and a quick check if devenv.exe exists. - Only versions 8-10 are considered. - Possibilities are: - 2005(e) - Visual Studio 2005 (8) - 2008(e) - Visual Studio 2008 (9) - 2010(e) - Visual Studio 2010 (10) - 2012(e) - Visual Studio 2012 (11) - 2013(e) - Visual Studio 2013 (12) - 2015 - Visual Studio 2015 (14) - Where (e) is e for express editions of MSVS and blank otherwise. - """ - version_to_year = { - '8.0': '2005', - '9.0': '2008', - '10.0': '2010', - '11.0': '2012', - '12.0': '2013', - '14.0': '2015', - } - versions = [] - for version in versions_to_check: - # Old method of searching for which VS version is installed - # We don't use the 2010-encouraged-way because we also want to get the - # path to the binaries, which it doesn't offer. - keys = [r'HKLM\Software\Microsoft\VisualStudio\%s' % version, - r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\%s' % version, - r'HKLM\Software\Microsoft\VCExpress\%s' % version, - r'HKLM\Software\Wow6432Node\Microsoft\VCExpress\%s' % version] - for index in range(len(keys)): - path = _RegistryGetValue(keys[index], 'InstallDir') - if not path: - continue - path = _ConvertToCygpath(path) - # Check for full. - full_path = os.path.join(path, 'devenv.exe') - express_path = os.path.join(path, '*express.exe') - if not force_express and os.path.exists(full_path): - # Add this one. - versions.append(_CreateVersion(version_to_year[version], - os.path.join(path, '..', '..'))) - # Check for express. - elif glob.glob(express_path): - # Add this one. - versions.append(_CreateVersion(version_to_year[version] + 'e', - os.path.join(path, '..', '..'))) - - # The old method above does not work when only SDK is installed. - keys = [r'HKLM\Software\Microsoft\VisualStudio\SxS\VC7', - r'HKLM\Software\Wow6432Node\Microsoft\VisualStudio\SxS\VC7'] - for index in range(len(keys)): - path = _RegistryGetValue(keys[index], version) - if not path: - continue - path = _ConvertToCygpath(path) - if version != '14.0': # There is no Express edition for 2015. - versions.append(_CreateVersion(version_to_year[version] + 'e', - os.path.join(path, '..'), sdk_based=True)) - - return versions - - -def SelectVisualStudioVersion(version='auto', allow_fallback=True): - """Select which version of Visual Studio projects to generate. - - Arguments: - version: Hook to allow caller to force a particular version (vs auto). - Returns: - An object representing a visual studio project format version. - """ - # In auto mode, check environment variable for override. - if version == 'auto': - version = os.environ.get('GYP_MSVS_VERSION', 'auto') - version_map = { - 'auto': ('14.0', '12.0', '10.0', '9.0', '8.0', '11.0'), - '2005': ('8.0',), - '2005e': ('8.0',), - '2008': ('9.0',), - '2008e': ('9.0',), - '2010': ('10.0',), - '2010e': ('10.0',), - '2012': ('11.0',), - '2012e': ('11.0',), - '2013': ('12.0',), - '2013e': ('12.0',), - '2015': ('14.0',), - } - override_path = os.environ.get('GYP_MSVS_OVERRIDE_PATH') - if override_path: - msvs_version = os.environ.get('GYP_MSVS_VERSION') - if not msvs_version: - raise ValueError('GYP_MSVS_OVERRIDE_PATH requires GYP_MSVS_VERSION to be ' - 'set to a particular version (e.g. 2010e).') - return _CreateVersion(msvs_version, override_path, sdk_based=True) - version = str(version) - versions = _DetectVisualStudioVersions(version_map[version], 'e' in version) - if not versions: - if not allow_fallback: - raise ValueError('Could not locate Visual Studio installation.') - if version == 'auto': - # Default to 2005 if we couldn't find anything - return _CreateVersion('2005', None) - else: - return _CreateVersion(version, None) - return versions[0] diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/__init__.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/__init__.py deleted file mode 100755 index 668f38b60d009..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/__init__.py +++ /dev/null @@ -1,548 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2012 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. - -import copy -import gyp.input -import optparse -import os.path -import re -import shlex -import sys -import traceback -from gyp.common import GypError - -# Default debug modes for GYP -debug = {} - -# List of "official" debug modes, but you can use anything you like. -DEBUG_GENERAL = 'general' -DEBUG_VARIABLES = 'variables' -DEBUG_INCLUDES = 'includes' - - -def DebugOutput(mode, message, *args): - if 'all' in gyp.debug or mode in gyp.debug: - ctx = ('unknown', 0, 'unknown') - try: - f = traceback.extract_stack(limit=2) - if f: - ctx = f[0][:3] - except: - pass - if args: - message %= args - print '%s:%s:%d:%s %s' % (mode.upper(), os.path.basename(ctx[0]), - ctx[1], ctx[2], message) - -def FindBuildFiles(): - extension = '.gyp' - files = os.listdir(os.getcwd()) - build_files = [] - for file in files: - if file.endswith(extension): - build_files.append(file) - return build_files - - -def Load(build_files, format, default_variables={}, - includes=[], depth='.', params=None, check=False, - circular_check=True, duplicate_basename_check=True): - """ - Loads one or more specified build files. - default_variables and includes will be copied before use. - Returns the generator for the specified format and the - data returned by loading the specified build files. - """ - if params is None: - params = {} - - if '-' in format: - format, params['flavor'] = format.split('-', 1) - - default_variables = copy.copy(default_variables) - - # Default variables provided by this program and its modules should be - # named WITH_CAPITAL_LETTERS to provide a distinct "best practice" namespace, - # avoiding collisions with user and automatic variables. - default_variables['GENERATOR'] = format - default_variables['GENERATOR_FLAVOR'] = params.get('flavor', '') - - # Format can be a custom python file, or by default the name of a module - # within gyp.generator. - if format.endswith('.py'): - generator_name = os.path.splitext(format)[0] - path, generator_name = os.path.split(generator_name) - - # Make sure the path to the custom generator is in sys.path - # Don't worry about removing it once we are done. Keeping the path - # to each generator that is used in sys.path is likely harmless and - # arguably a good idea. - path = os.path.abspath(path) - if path not in sys.path: - sys.path.insert(0, path) - else: - generator_name = 'gyp.generator.' + format - - # These parameters are passed in order (as opposed to by key) - # because ActivePython cannot handle key parameters to __import__. - generator = __import__(generator_name, globals(), locals(), generator_name) - for (key, val) in generator.generator_default_variables.items(): - default_variables.setdefault(key, val) - - # Give the generator the opportunity to set additional variables based on - # the params it will receive in the output phase. - if getattr(generator, 'CalculateVariables', None): - generator.CalculateVariables(default_variables, params) - - # Give the generator the opportunity to set generator_input_info based on - # the params it will receive in the output phase. - if getattr(generator, 'CalculateGeneratorInputInfo', None): - generator.CalculateGeneratorInputInfo(params) - - # Fetch the generator specific info that gets fed to input, we use getattr - # so we can default things and the generators only have to provide what - # they need. - generator_input_info = { - 'non_configuration_keys': - getattr(generator, 'generator_additional_non_configuration_keys', []), - 'path_sections': - getattr(generator, 'generator_additional_path_sections', []), - 'extra_sources_for_rules': - getattr(generator, 'generator_extra_sources_for_rules', []), - 'generator_supports_multiple_toolsets': - getattr(generator, 'generator_supports_multiple_toolsets', False), - 'generator_wants_static_library_dependencies_adjusted': - getattr(generator, - 'generator_wants_static_library_dependencies_adjusted', True), - 'generator_wants_sorted_dependencies': - getattr(generator, 'generator_wants_sorted_dependencies', False), - 'generator_filelist_paths': - getattr(generator, 'generator_filelist_paths', None), - } - - # Process the input specific to this generator. - result = gyp.input.Load(build_files, default_variables, includes[:], - depth, generator_input_info, check, circular_check, - duplicate_basename_check, - params['parallel'], params['root_targets']) - return [generator] + result - -def NameValueListToDict(name_value_list): - """ - Takes an array of strings of the form 'NAME=VALUE' and creates a dictionary - of the pairs. If a string is simply NAME, then the value in the dictionary - is set to True. If VALUE can be converted to an integer, it is. - """ - result = { } - for item in name_value_list: - tokens = item.split('=', 1) - if len(tokens) == 2: - # If we can make it an int, use that, otherwise, use the string. - try: - token_value = int(tokens[1]) - except ValueError: - token_value = tokens[1] - # Set the variable to the supplied value. - result[tokens[0]] = token_value - else: - # No value supplied, treat it as a boolean and set it. - result[tokens[0]] = True - return result - -def ShlexEnv(env_name): - flags = os.environ.get(env_name, []) - if flags: - flags = shlex.split(flags) - return flags - -def FormatOpt(opt, value): - if opt.startswith('--'): - return '%s=%s' % (opt, value) - return opt + value - -def RegenerateAppendFlag(flag, values, predicate, env_name, options): - """Regenerate a list of command line flags, for an option of action='append'. - - The |env_name|, if given, is checked in the environment and used to generate - an initial list of options, then the options that were specified on the - command line (given in |values|) are appended. This matches the handling of - environment variables and command line flags where command line flags override - the environment, while not requiring the environment to be set when the flags - are used again. - """ - flags = [] - if options.use_environment and env_name: - for flag_value in ShlexEnv(env_name): - value = FormatOpt(flag, predicate(flag_value)) - if value in flags: - flags.remove(value) - flags.append(value) - if values: - for flag_value in values: - flags.append(FormatOpt(flag, predicate(flag_value))) - return flags - -def RegenerateFlags(options): - """Given a parsed options object, and taking the environment variables into - account, returns a list of flags that should regenerate an equivalent options - object (even in the absence of the environment variables.) - - Any path options will be normalized relative to depth. - - The format flag is not included, as it is assumed the calling generator will - set that as appropriate. - """ - def FixPath(path): - path = gyp.common.FixIfRelativePath(path, options.depth) - if not path: - return os.path.curdir - return path - - def Noop(value): - return value - - # We always want to ignore the environment when regenerating, to avoid - # duplicate or changed flags in the environment at the time of regeneration. - flags = ['--ignore-environment'] - for name, metadata in options._regeneration_metadata.iteritems(): - opt = metadata['opt'] - value = getattr(options, name) - value_predicate = metadata['type'] == 'path' and FixPath or Noop - action = metadata['action'] - env_name = metadata['env_name'] - if action == 'append': - flags.extend(RegenerateAppendFlag(opt, value, value_predicate, - env_name, options)) - elif action in ('store', None): # None is a synonym for 'store'. - if value: - flags.append(FormatOpt(opt, value_predicate(value))) - elif options.use_environment and env_name and os.environ.get(env_name): - flags.append(FormatOpt(opt, value_predicate(os.environ.get(env_name)))) - elif action in ('store_true', 'store_false'): - if ((action == 'store_true' and value) or - (action == 'store_false' and not value)): - flags.append(opt) - elif options.use_environment and env_name: - print >>sys.stderr, ('Warning: environment regeneration unimplemented ' - 'for %s flag %r env_name %r' % (action, opt, - env_name)) - else: - print >>sys.stderr, ('Warning: regeneration unimplemented for action %r ' - 'flag %r' % (action, opt)) - - return flags - -class RegeneratableOptionParser(optparse.OptionParser): - def __init__(self): - self.__regeneratable_options = {} - optparse.OptionParser.__init__(self) - - def add_option(self, *args, **kw): - """Add an option to the parser. - - This accepts the same arguments as OptionParser.add_option, plus the - following: - regenerate: can be set to False to prevent this option from being included - in regeneration. - env_name: name of environment variable that additional values for this - option come from. - type: adds type='path', to tell the regenerator that the values of - this option need to be made relative to options.depth - """ - env_name = kw.pop('env_name', None) - if 'dest' in kw and kw.pop('regenerate', True): - dest = kw['dest'] - - # The path type is needed for regenerating, for optparse we can just treat - # it as a string. - type = kw.get('type') - if type == 'path': - kw['type'] = 'string' - - self.__regeneratable_options[dest] = { - 'action': kw.get('action'), - 'type': type, - 'env_name': env_name, - 'opt': args[0], - } - - optparse.OptionParser.add_option(self, *args, **kw) - - def parse_args(self, *args): - values, args = optparse.OptionParser.parse_args(self, *args) - values._regeneration_metadata = self.__regeneratable_options - return values, args - -def gyp_main(args): - my_name = os.path.basename(sys.argv[0]) - - parser = RegeneratableOptionParser() - usage = 'usage: %s [options ...] [build_file ...]' - parser.set_usage(usage.replace('%s', '%prog')) - parser.add_option('--build', dest='configs', action='append', - help='configuration for build after project generation') - parser.add_option('--check', dest='check', action='store_true', - help='check format of gyp files') - parser.add_option('--config-dir', dest='config_dir', action='store', - env_name='GYP_CONFIG_DIR', default=None, - help='The location for configuration files like ' - 'include.gypi.') - parser.add_option('-d', '--debug', dest='debug', metavar='DEBUGMODE', - action='append', default=[], help='turn on a debugging ' - 'mode for debugging GYP. Supported modes are "variables", ' - '"includes" and "general" or "all" for all of them.') - parser.add_option('-D', dest='defines', action='append', metavar='VAR=VAL', - env_name='GYP_DEFINES', - help='sets variable VAR to value VAL') - parser.add_option('--depth', dest='depth', metavar='PATH', type='path', - help='set DEPTH gyp variable to a relative path to PATH') - parser.add_option('-f', '--format', dest='formats', action='append', - env_name='GYP_GENERATORS', regenerate=False, - help='output formats to generate') - parser.add_option('-G', dest='generator_flags', action='append', default=[], - metavar='FLAG=VAL', env_name='GYP_GENERATOR_FLAGS', - help='sets generator flag FLAG to VAL') - parser.add_option('--generator-output', dest='generator_output', - action='store', default=None, metavar='DIR', type='path', - env_name='GYP_GENERATOR_OUTPUT', - help='puts generated build files under DIR') - parser.add_option('--ignore-environment', dest='use_environment', - action='store_false', default=True, regenerate=False, - help='do not read options from environment variables') - parser.add_option('-I', '--include', dest='includes', action='append', - metavar='INCLUDE', type='path', - help='files to include in all loaded .gyp files') - # --no-circular-check disables the check for circular relationships between - # .gyp files. These relationships should not exist, but they've only been - # observed to be harmful with the Xcode generator. Chromium's .gyp files - # currently have some circular relationships on non-Mac platforms, so this - # option allows the strict behavior to be used on Macs and the lenient - # behavior to be used elsewhere. - # TODO(mark): Remove this option when http://crbug.com/35878 is fixed. - parser.add_option('--no-circular-check', dest='circular_check', - action='store_false', default=True, regenerate=False, - help="don't check for circular relationships between files") - # --no-duplicate-basename-check disables the check for duplicate basenames - # in a static_library/shared_library project. Visual C++ 2008 generator - # doesn't support this configuration. Libtool on Mac also generates warnings - # when duplicate basenames are passed into Make generator on Mac. - # TODO(yukawa): Remove this option when these legacy generators are - # deprecated. - parser.add_option('--no-duplicate-basename-check', - dest='duplicate_basename_check', action='store_false', - default=True, regenerate=False, - help="don't check for duplicate basenames") - parser.add_option('--no-parallel', action='store_true', default=False, - help='Disable multiprocessing') - parser.add_option('-S', '--suffix', dest='suffix', default='', - help='suffix to add to generated files') - parser.add_option('--toplevel-dir', dest='toplevel_dir', action='store', - default=None, metavar='DIR', type='path', - help='directory to use as the root of the source tree') - parser.add_option('-R', '--root-target', dest='root_targets', - action='append', metavar='TARGET', - help='include only TARGET and its deep dependencies') - - options, build_files_arg = parser.parse_args(args) - build_files = build_files_arg - - # Set up the configuration directory (defaults to ~/.gyp) - if not options.config_dir: - home = None - home_dot_gyp = None - if options.use_environment: - home_dot_gyp = os.environ.get('GYP_CONFIG_DIR', None) - if home_dot_gyp: - home_dot_gyp = os.path.expanduser(home_dot_gyp) - - if not home_dot_gyp: - home_vars = ['HOME'] - if sys.platform in ('cygwin', 'win32'): - home_vars.append('USERPROFILE') - for home_var in home_vars: - home = os.getenv(home_var) - if home != None: - home_dot_gyp = os.path.join(home, '.gyp') - if not os.path.exists(home_dot_gyp): - home_dot_gyp = None - else: - break - else: - home_dot_gyp = os.path.expanduser(options.config_dir) - - if home_dot_gyp and not os.path.exists(home_dot_gyp): - home_dot_gyp = None - - if not options.formats: - # If no format was given on the command line, then check the env variable. - generate_formats = [] - if options.use_environment: - generate_formats = os.environ.get('GYP_GENERATORS', []) - if generate_formats: - generate_formats = re.split(r'[\s,]', generate_formats) - if generate_formats: - options.formats = generate_formats - else: - # Nothing in the variable, default based on platform. - if sys.platform == 'darwin': - options.formats = ['xcode'] - elif sys.platform in ('win32', 'cygwin'): - options.formats = ['msvs'] - else: - options.formats = ['make'] - - if not options.generator_output and options.use_environment: - g_o = os.environ.get('GYP_GENERATOR_OUTPUT') - if g_o: - options.generator_output = g_o - - options.parallel = not options.no_parallel - - for mode in options.debug: - gyp.debug[mode] = 1 - - # Do an extra check to avoid work when we're not debugging. - if DEBUG_GENERAL in gyp.debug: - DebugOutput(DEBUG_GENERAL, 'running with these options:') - for option, value in sorted(options.__dict__.items()): - if option[0] == '_': - continue - if isinstance(value, basestring): - DebugOutput(DEBUG_GENERAL, " %s: '%s'", option, value) - else: - DebugOutput(DEBUG_GENERAL, " %s: %s", option, value) - - if not build_files: - build_files = FindBuildFiles() - if not build_files: - raise GypError((usage + '\n\n%s: error: no build_file') % - (my_name, my_name)) - - # TODO(mark): Chromium-specific hack! - # For Chromium, the gyp "depth" variable should always be a relative path - # to Chromium's top-level "src" directory. If no depth variable was set - # on the command line, try to find a "src" directory by looking at the - # absolute path to each build file's directory. The first "src" component - # found will be treated as though it were the path used for --depth. - if not options.depth: - for build_file in build_files: - build_file_dir = os.path.abspath(os.path.dirname(build_file)) - build_file_dir_components = build_file_dir.split(os.path.sep) - components_len = len(build_file_dir_components) - for index in xrange(components_len - 1, -1, -1): - if build_file_dir_components[index] == 'src': - options.depth = os.path.sep.join(build_file_dir_components) - break - del build_file_dir_components[index] - - # If the inner loop found something, break without advancing to another - # build file. - if options.depth: - break - - if not options.depth: - raise GypError('Could not automatically locate src directory. This is' - 'a temporary Chromium feature that will be removed. Use' - '--depth as a workaround.') - - # If toplevel-dir is not set, we assume that depth is the root of our source - # tree. - if not options.toplevel_dir: - options.toplevel_dir = options.depth - - # -D on the command line sets variable defaults - D isn't just for define, - # it's for default. Perhaps there should be a way to force (-F?) a - # variable's value so that it can't be overridden by anything else. - cmdline_default_variables = {} - defines = [] - if options.use_environment: - defines += ShlexEnv('GYP_DEFINES') - if options.defines: - defines += options.defines - cmdline_default_variables = NameValueListToDict(defines) - if DEBUG_GENERAL in gyp.debug: - DebugOutput(DEBUG_GENERAL, - "cmdline_default_variables: %s", cmdline_default_variables) - - # Set up includes. - includes = [] - - # If ~/.gyp/include.gypi exists, it'll be forcibly included into every - # .gyp file that's loaded, before anything else is included. - if home_dot_gyp != None: - default_include = os.path.join(home_dot_gyp, 'include.gypi') - if os.path.exists(default_include): - print 'Using overrides found in ' + default_include - includes.append(default_include) - - # Command-line --include files come after the default include. - if options.includes: - includes.extend(options.includes) - - # Generator flags should be prefixed with the target generator since they - # are global across all generator runs. - gen_flags = [] - if options.use_environment: - gen_flags += ShlexEnv('GYP_GENERATOR_FLAGS') - if options.generator_flags: - gen_flags += options.generator_flags - generator_flags = NameValueListToDict(gen_flags) - if DEBUG_GENERAL in gyp.debug.keys(): - DebugOutput(DEBUG_GENERAL, "generator_flags: %s", generator_flags) - - # Generate all requested formats (use a set in case we got one format request - # twice) - for format in set(options.formats): - params = {'options': options, - 'build_files': build_files, - 'generator_flags': generator_flags, - 'cwd': os.getcwd(), - 'build_files_arg': build_files_arg, - 'gyp_binary': sys.argv[0], - 'home_dot_gyp': home_dot_gyp, - 'parallel': options.parallel, - 'root_targets': options.root_targets, - 'target_arch': cmdline_default_variables.get('target_arch', '')} - - # Start with the default variables from the command line. - [generator, flat_list, targets, data] = Load( - build_files, format, cmdline_default_variables, includes, options.depth, - params, options.check, options.circular_check, - options.duplicate_basename_check) - - # TODO(mark): Pass |data| for now because the generator needs a list of - # build files that came in. In the future, maybe it should just accept - # a list, and not the whole data dict. - # NOTE: flat_list is the flattened dependency graph specifying the order - # that targets may be built. Build systems that operate serially or that - # need to have dependencies defined before dependents reference them should - # generate targets in the order specified in flat_list. - generator.GenerateOutput(flat_list, targets, data, params) - - if options.configs: - valid_configs = targets[flat_list[0]]['configurations'].keys() - for conf in options.configs: - if conf not in valid_configs: - raise GypError('Invalid config specified via --build: %s' % conf) - generator.PerformBuild(data, options.configs, params) - - # Done - return 0 - - -def main(args): - try: - return gyp_main(args) - except GypError, e: - sys.stderr.write("gyp: %s\n" % e) - return 1 - -# NOTE: setuptools generated console_scripts calls function with no arguments -def script_main(): - return main(sys.argv[1:]) - -if __name__ == '__main__': - sys.exit(script_main()) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common.py deleted file mode 100644 index 501118796f00d..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common.py +++ /dev/null @@ -1,612 +0,0 @@ -# Copyright (c) 2012 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. - -from __future__ import with_statement - -import collections -import errno -import filecmp -import os.path -import re -import tempfile -import sys - - -# A minimal memoizing decorator. It'll blow up if the args aren't immutable, -# among other "problems". -class memoize(object): - def __init__(self, func): - self.func = func - self.cache = {} - def __call__(self, *args): - try: - return self.cache[args] - except KeyError: - result = self.func(*args) - self.cache[args] = result - return result - - -class GypError(Exception): - """Error class representing an error, which is to be presented - to the user. The main entry point will catch and display this. - """ - pass - - -def ExceptionAppend(e, msg): - """Append a message to the given exception's message.""" - if not e.args: - e.args = (msg,) - elif len(e.args) == 1: - e.args = (str(e.args[0]) + ' ' + msg,) - else: - e.args = (str(e.args[0]) + ' ' + msg,) + e.args[1:] - - -def FindQualifiedTargets(target, qualified_list): - """ - Given a list of qualified targets, return the qualified targets for the - specified |target|. - """ - return [t for t in qualified_list if ParseQualifiedTarget(t)[1] == target] - - -def ParseQualifiedTarget(target): - # Splits a qualified target into a build file, target name and toolset. - - # NOTE: rsplit is used to disambiguate the Windows drive letter separator. - target_split = target.rsplit(':', 1) - if len(target_split) == 2: - [build_file, target] = target_split - else: - build_file = None - - target_split = target.rsplit('#', 1) - if len(target_split) == 2: - [target, toolset] = target_split - else: - toolset = None - - return [build_file, target, toolset] - - -def ResolveTarget(build_file, target, toolset): - # This function resolves a target into a canonical form: - # - a fully defined build file, either absolute or relative to the current - # directory - # - a target name - # - a toolset - # - # build_file is the file relative to which 'target' is defined. - # target is the qualified target. - # toolset is the default toolset for that target. - [parsed_build_file, target, parsed_toolset] = ParseQualifiedTarget(target) - - if parsed_build_file: - if build_file: - # If a relative path, parsed_build_file is relative to the directory - # containing build_file. If build_file is not in the current directory, - # parsed_build_file is not a usable path as-is. Resolve it by - # interpreting it as relative to build_file. If parsed_build_file is - # absolute, it is usable as a path regardless of the current directory, - # and os.path.join will return it as-is. - build_file = os.path.normpath(os.path.join(os.path.dirname(build_file), - parsed_build_file)) - # Further (to handle cases like ../cwd), make it relative to cwd) - if not os.path.isabs(build_file): - build_file = RelativePath(build_file, '.') - else: - build_file = parsed_build_file - - if parsed_toolset: - toolset = parsed_toolset - - return [build_file, target, toolset] - - -def BuildFile(fully_qualified_target): - # Extracts the build file from the fully qualified target. - return ParseQualifiedTarget(fully_qualified_target)[0] - - -def GetEnvironFallback(var_list, default): - """Look up a key in the environment, with fallback to secondary keys - and finally falling back to a default value.""" - for var in var_list: - if var in os.environ: - return os.environ[var] - return default - - -def QualifiedTarget(build_file, target, toolset): - # "Qualified" means the file that a target was defined in and the target - # name, separated by a colon, suffixed by a # and the toolset name: - # /path/to/file.gyp:target_name#toolset - fully_qualified = build_file + ':' + target - if toolset: - fully_qualified = fully_qualified + '#' + toolset - return fully_qualified - - -@memoize -def RelativePath(path, relative_to, follow_path_symlink=True): - # Assuming both |path| and |relative_to| are relative to the current - # directory, returns a relative path that identifies path relative to - # relative_to. - # If |follow_symlink_path| is true (default) and |path| is a symlink, then - # this method returns a path to the real file represented by |path|. If it is - # false, this method returns a path to the symlink. If |path| is not a - # symlink, this option has no effect. - - # Convert to normalized (and therefore absolute paths). - if follow_path_symlink: - path = os.path.realpath(path) - else: - path = os.path.abspath(path) - relative_to = os.path.realpath(relative_to) - - # On Windows, we can't create a relative path to a different drive, so just - # use the absolute path. - if sys.platform == 'win32': - if (os.path.splitdrive(path)[0].lower() != - os.path.splitdrive(relative_to)[0].lower()): - return path - - # Split the paths into components. - path_split = path.split(os.path.sep) - relative_to_split = relative_to.split(os.path.sep) - - # Determine how much of the prefix the two paths share. - prefix_len = len(os.path.commonprefix([path_split, relative_to_split])) - - # Put enough ".." components to back up out of relative_to to the common - # prefix, and then append the part of path_split after the common prefix. - relative_split = [os.path.pardir] * (len(relative_to_split) - prefix_len) + \ - path_split[prefix_len:] - - if len(relative_split) == 0: - # The paths were the same. - return '' - - # Turn it back into a string and we're done. - return os.path.join(*relative_split) - - -@memoize -def InvertRelativePath(path, toplevel_dir=None): - """Given a path like foo/bar that is relative to toplevel_dir, return - the inverse relative path back to the toplevel_dir. - - E.g. os.path.normpath(os.path.join(path, InvertRelativePath(path))) - should always produce the empty string, unless the path contains symlinks. - """ - if not path: - return path - toplevel_dir = '.' if toplevel_dir is None else toplevel_dir - return RelativePath(toplevel_dir, os.path.join(toplevel_dir, path)) - - -def FixIfRelativePath(path, relative_to): - # Like RelativePath but returns |path| unchanged if it is absolute. - if os.path.isabs(path): - return path - return RelativePath(path, relative_to) - - -def UnrelativePath(path, relative_to): - # Assuming that |relative_to| is relative to the current directory, and |path| - # is a path relative to the dirname of |relative_to|, returns a path that - # identifies |path| relative to the current directory. - rel_dir = os.path.dirname(relative_to) - return os.path.normpath(os.path.join(rel_dir, path)) - - -# re objects used by EncodePOSIXShellArgument. See IEEE 1003.1 XCU.2.2 at -# http://www.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html#tag_02_02 -# and the documentation for various shells. - -# _quote is a pattern that should match any argument that needs to be quoted -# with double-quotes by EncodePOSIXShellArgument. It matches the following -# characters appearing anywhere in an argument: -# \t, \n, space parameter separators -# # comments -# $ expansions (quoted to always expand within one argument) -# % called out by IEEE 1003.1 XCU.2.2 -# & job control -# ' quoting -# (, ) subshell execution -# *, ?, [ pathname expansion -# ; command delimiter -# <, >, | redirection -# = assignment -# {, } brace expansion (bash) -# ~ tilde expansion -# It also matches the empty string, because "" (or '') is the only way to -# represent an empty string literal argument to a POSIX shell. -# -# This does not match the characters in _escape, because those need to be -# backslash-escaped regardless of whether they appear in a double-quoted -# string. -_quote = re.compile('[\t\n #$%&\'()*;<=>?[{|}~]|^$') - -# _escape is a pattern that should match any character that needs to be -# escaped with a backslash, whether or not the argument matched the _quote -# pattern. _escape is used with re.sub to backslash anything in _escape's -# first match group, hence the (parentheses) in the regular expression. -# -# _escape matches the following characters appearing anywhere in an argument: -# " to prevent POSIX shells from interpreting this character for quoting -# \ to prevent POSIX shells from interpreting this character for escaping -# ` to prevent POSIX shells from interpreting this character for command -# substitution -# Missing from this list is $, because the desired behavior of -# EncodePOSIXShellArgument is to permit parameter (variable) expansion. -# -# Also missing from this list is !, which bash will interpret as the history -# expansion character when history is enabled. bash does not enable history -# by default in non-interactive shells, so this is not thought to be a problem. -# ! was omitted from this list because bash interprets "\!" as a literal string -# including the backslash character (avoiding history expansion but retaining -# the backslash), which would not be correct for argument encoding. Handling -# this case properly would also be problematic because bash allows the history -# character to be changed with the histchars shell variable. Fortunately, -# as history is not enabled in non-interactive shells and -# EncodePOSIXShellArgument is only expected to encode for non-interactive -# shells, there is no room for error here by ignoring !. -_escape = re.compile(r'(["\\`])') - -def EncodePOSIXShellArgument(argument): - """Encodes |argument| suitably for consumption by POSIX shells. - - argument may be quoted and escaped as necessary to ensure that POSIX shells - treat the returned value as a literal representing the argument passed to - this function. Parameter (variable) expansions beginning with $ are allowed - to remain intact without escaping the $, to allow the argument to contain - references to variables to be expanded by the shell. - """ - - if not isinstance(argument, str): - argument = str(argument) - - if _quote.search(argument): - quote = '"' - else: - quote = '' - - encoded = quote + re.sub(_escape, r'\\\1', argument) + quote - - return encoded - - -def EncodePOSIXShellList(list): - """Encodes |list| suitably for consumption by POSIX shells. - - Returns EncodePOSIXShellArgument for each item in list, and joins them - together using the space character as an argument separator. - """ - - encoded_arguments = [] - for argument in list: - encoded_arguments.append(EncodePOSIXShellArgument(argument)) - return ' '.join(encoded_arguments) - - -def DeepDependencyTargets(target_dicts, roots): - """Returns the recursive list of target dependencies.""" - dependencies = set() - pending = set(roots) - while pending: - # Pluck out one. - r = pending.pop() - # Skip if visited already. - if r in dependencies: - continue - # Add it. - dependencies.add(r) - # Add its children. - spec = target_dicts[r] - pending.update(set(spec.get('dependencies', []))) - pending.update(set(spec.get('dependencies_original', []))) - return list(dependencies - set(roots)) - - -def BuildFileTargets(target_list, build_file): - """From a target_list, returns the subset from the specified build_file. - """ - return [p for p in target_list if BuildFile(p) == build_file] - - -def AllTargets(target_list, target_dicts, build_file): - """Returns all targets (direct and dependencies) for the specified build_file. - """ - bftargets = BuildFileTargets(target_list, build_file) - deptargets = DeepDependencyTargets(target_dicts, bftargets) - return bftargets + deptargets - - -def WriteOnDiff(filename): - """Write to a file only if the new contents differ. - - Arguments: - filename: name of the file to potentially write to. - Returns: - A file like object which will write to temporary file and only overwrite - the target if it differs (on close). - """ - - class Writer(object): - """Wrapper around file which only covers the target if it differs.""" - def __init__(self): - # Pick temporary file. - tmp_fd, self.tmp_path = tempfile.mkstemp( - suffix='.tmp', - prefix=os.path.split(filename)[1] + '.gyp.', - dir=os.path.split(filename)[0]) - try: - self.tmp_file = os.fdopen(tmp_fd, 'wb') - except Exception: - # Don't leave turds behind. - os.unlink(self.tmp_path) - raise - - def __getattr__(self, attrname): - # Delegate everything else to self.tmp_file - return getattr(self.tmp_file, attrname) - - def close(self): - try: - # Close tmp file. - self.tmp_file.close() - # Determine if different. - same = False - try: - same = filecmp.cmp(self.tmp_path, filename, False) - except OSError, e: - if e.errno != errno.ENOENT: - raise - - if same: - # The new file is identical to the old one, just get rid of the new - # one. - os.unlink(self.tmp_path) - else: - # The new file is different from the old one, or there is no old one. - # Rename the new file to the permanent name. - # - # tempfile.mkstemp uses an overly restrictive mode, resulting in a - # file that can only be read by the owner, regardless of the umask. - # There's no reason to not respect the umask here, which means that - # an extra hoop is required to fetch it and reset the new file's mode. - # - # No way to get the umask without setting a new one? Set a safe one - # and then set it back to the old value. - umask = os.umask(077) - os.umask(umask) - os.chmod(self.tmp_path, 0666 & ~umask) - if sys.platform == 'win32' and os.path.exists(filename): - # NOTE: on windows (but not cygwin) rename will not replace an - # existing file, so it must be preceded with a remove. Sadly there - # is no way to make the switch atomic. - os.remove(filename) - os.rename(self.tmp_path, filename) - except Exception: - # Don't leave turds behind. - os.unlink(self.tmp_path) - raise - - 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 = { - 'cygwin': 'win', - 'win32': 'win', - 'darwin': 'mac', - } - - if 'flavor' in params: - return params['flavor'] - if sys.platform in flavors: - return flavors[sys.platform] - if sys.platform.startswith('sunos'): - return 'solaris' - if sys.platform.startswith('freebsd'): - return 'freebsd' - if sys.platform.startswith('openbsd'): - return 'openbsd' - if sys.platform.startswith('netbsd'): - return 'netbsd' - if sys.platform.startswith('aix'): - return 'aix' - if sys.platform.startswith('zos'): - return 'zos' - if sys.platform.startswith('os390'): - return 'zos' - - return 'linux' - - -def CopyTool(flavor, out_path): - """Finds (flock|mac|win)_tool.gyp in the gyp directory and copies it - to |out_path|.""" - # aix and solaris just need flock emulation. mac and win use more complicated - # support scripts. - prefix = { - 'aix': 'flock', - 'solaris': 'flock', - 'mac': 'mac', - 'win': 'win' - }.get(flavor, None) - if not prefix: - return - - # Slurp input file. - source_path = os.path.join( - os.path.dirname(os.path.abspath(__file__)), '%s_tool.py' % prefix) - with open(source_path) as source_file: - source = source_file.readlines() - - # Add header and write it out. - tool_path = os.path.join(out_path, 'gyp-%s-tool' % prefix) - with open(tool_path, 'w') as tool_file: - tool_file.write( - ''.join([source[0], '# Generated by gyp. Do not edit.\n'] + source[1:])) - - # Make file executable. - os.chmod(tool_path, 0755) - - -# From Alex Martelli, -# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/52560 -# ASPN: Python Cookbook: Remove duplicates from a sequence -# First comment, dated 2001/10/13. -# (Also in the printed Python Cookbook.) - -def uniquer(seq, idfun=None): - if idfun is None: - idfun = lambda x: x - seen = {} - result = [] - for item in seq: - marker = idfun(item) - if marker in seen: continue - seen[marker] = 1 - result.append(item) - return result - - -# 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 __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 discard(self, key): - if key in self.map: - key, prev_item, next_item = self.map.pop(key) - prev_item[2] = next_item - next_item[1] = prev_item - - def __iter__(self): - end = self.end - curr = end[2] - while curr is not end: - yield curr[0] - curr = curr[2] - - def __reversed__(self): - end = self.end - curr = end[1] - while curr is not end: - yield curr[0] - curr = curr[1] - - # The second argument is an addition that causes a pylint warning. - def pop(self, last=True): # pylint: disable=W0221 - if not self: - raise KeyError('set is empty') - key = self.end[1][0] if last else self.end[2][0] - self.discard(key) - return key - - def __repr__(self): - if not self: - return '%s()' % (self.__class__.__name__,) - return '%s(%r)' % (self.__class__.__name__, list(self)) - - def __eq__(self, other): - if isinstance(other, OrderedSet): - return len(self) == len(other) and list(self) == list(other) - return set(self) == set(other) - - # Extensions to the recipe. - def update(self, iterable): - for i in iterable: - if i not in self: - self.add(i) - - -class CycleError(Exception): - """An exception raised when an unexpected cycle is detected.""" - def __init__(self, nodes): - self.nodes = nodes - def __str__(self): - return 'CycleError: cycle involving: ' + str(self.nodes) - - -def TopologicallySorted(graph, get_edges): - r"""Topologically sort based on a user provided edge definition. - - Args: - graph: A list of node names. - get_edges: A function mapping from node name to a hashable collection - of node names which this node has outgoing edges to. - Returns: - A list containing all of the node in graph in topological order. - It is assumed that calling get_edges once for each node and caching is - cheaper than repeatedly calling get_edges. - Raises: - CycleError in the event of a cycle. - Example: - graph = {'a': '$(b) $(c)', 'b': 'hi', 'c': '$(b)'} - def GetEdges(node): - return re.findall(r'\$\(([^))]\)', graph[node]) - print TopologicallySorted(graph.keys(), GetEdges) - ==> - ['a', 'c', b'] - """ - get_edges = memoize(get_edges) - visited = set() - visiting = set() - ordered_nodes = [] - def Visit(node): - if node in visiting: - raise CycleError(visiting) - if node in visited: - return - visited.add(node) - visiting.add(node) - for neighbor in get_edges(node): - Visit(neighbor) - visiting.remove(node) - ordered_nodes.insert(0, node) - for node in sorted(graph): - Visit(node) - return ordered_nodes - -def CrossCompileRequested(): - # TODO: figure out how to not build extra host objects in the - # non-cross-compile case when this is enabled, and enable unconditionally. - return (os.environ.get('GYP_CROSSCOMPILE') or - os.environ.get('AR_host') or - os.environ.get('CC_host') or - os.environ.get('CXX_host') or - os.environ.get('AR_target') or - os.environ.get('CC_target') or - os.environ.get('CXX_target')) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common_test.py deleted file mode 100755 index ad6f9a1438f30..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/common_test.py +++ /dev/null @@ -1,72 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2012 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. - -"""Unit tests for the common.py file.""" - -import gyp.common -import unittest -import sys - - -class TestTopologicallySorted(unittest.TestCase): - def test_Valid(self): - """Test that sorting works on a valid graph with one possible order.""" - graph = { - 'a': ['b', 'c'], - 'b': [], - 'c': ['d'], - 'd': ['b'], - } - def GetEdge(node): - return tuple(graph[node]) - self.assertEqual( - gyp.common.TopologicallySorted(graph.keys(), GetEdge), - ['a', 'c', 'd', 'b']) - - def test_Cycle(self): - """Test that an exception is thrown on a cyclic graph.""" - graph = { - 'a': ['b'], - 'b': ['c'], - 'c': ['d'], - 'd': ['a'], - } - def GetEdge(node): - return tuple(graph[node]) - self.assertRaises( - gyp.common.CycleError, gyp.common.TopologicallySorted, - graph.keys(), GetEdge) - - -class TestGetFlavor(unittest.TestCase): - """Test that gyp.common.GetFlavor works as intended""" - original_platform = '' - - def setUp(self): - self.original_platform = sys.platform - - def tearDown(self): - sys.platform = self.original_platform - - def assertFlavor(self, expected, argument, param): - sys.platform = argument - self.assertEqual(expected, gyp.common.GetFlavor(param)) - - def test_platform_default(self): - self.assertFlavor('freebsd', 'freebsd9' , {}) - self.assertFlavor('freebsd', 'freebsd10', {}) - self.assertFlavor('openbsd', 'openbsd5' , {}) - self.assertFlavor('solaris', 'sunos5' , {}); - self.assertFlavor('solaris', 'sunos' , {}); - self.assertFlavor('linux' , 'linux2' , {}); - self.assertFlavor('linux' , 'linux3' , {}); - - def test_param(self): - self.assertFlavor('foobar', 'linux2' , {'flavor': 'foobar'}) - - -if __name__ == '__main__': - unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py deleted file mode 100644 index 841f31f925b05..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml.py +++ /dev/null @@ -1,162 +0,0 @@ -# Copyright (c) 2011 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. - -import re -import os -import locale - - -def XmlToString(content, encoding='utf-8', pretty=False): - """ Writes the XML content to disk, touching the file only if it has changed. - - Visual Studio files have a lot of pre-defined structures. This function makes - it easy to represent these structures as Python data structures, instead of - having to create a lot of function calls. - - Each XML element of the content is represented as a list composed of: - 1. The name of the element, a string, - 2. The attributes of the element, a dictionary (optional), and - 3+. The content of the element, if any. Strings are simple text nodes and - lists are child elements. - - Example 1: - - becomes - ['test'] - - Example 2: - - This is - it! - - - becomes - ['myelement', {'a':'value1', 'b':'value2'}, - ['childtype', 'This is'], - ['childtype', 'it!'], - ] - - Args: - content: The structured content to be converted. - encoding: The encoding to report on the first XML line. - pretty: True if we want pretty printing with indents and new lines. - - Returns: - The XML content as a string. - """ - # We create a huge list of all the elements of the file. - xml_parts = ['' % encoding] - if pretty: - xml_parts.append('\n') - _ConstructContentList(xml_parts, content, pretty) - - # Convert it to a string - return ''.join(xml_parts) - - -def _ConstructContentList(xml_parts, specification, pretty, level=0): - """ Appends the XML parts corresponding to the specification. - - Args: - xml_parts: A list of XML parts to be appended to. - specification: The specification of the element. See EasyXml docs. - pretty: True if we want pretty printing with indents and new lines. - level: Indentation level. - """ - # The first item in a specification is the name of the element. - if pretty: - indentation = ' ' * level - new_line = '\n' - else: - indentation = '' - new_line = '' - name = specification[0] - if not isinstance(name, str): - raise Exception('The first item of an EasyXml specification should be ' - 'a string. Specification was ' + str(specification)) - xml_parts.append(indentation + '<' + name) - - # Optionally in second position is a dictionary of the attributes. - rest = specification[1:] - if rest and isinstance(rest[0], dict): - for at, val in sorted(rest[0].iteritems()): - xml_parts.append(' %s="%s"' % (at, _XmlEscape(val, attr=True))) - rest = rest[1:] - if rest: - xml_parts.append('>') - all_strings = reduce(lambda x, y: x and isinstance(y, str), rest, True) - multi_line = not all_strings - if multi_line and new_line: - xml_parts.append(new_line) - for child_spec in rest: - # If it's a string, append a text node. - # Otherwise recurse over that child definition - if isinstance(child_spec, str): - xml_parts.append(_XmlEscape(child_spec)) - else: - _ConstructContentList(xml_parts, child_spec, pretty, level + 1) - if multi_line and indentation: - xml_parts.append(indentation) - xml_parts.append('%s' % (name, new_line)) - else: - xml_parts.append('/>%s' % new_line) - - -def WriteXmlIfChanged(content, path, encoding='utf-8', pretty=False, - win32=False): - """ Writes the XML content to disk, touching the file only if it has changed. - - Args: - content: The structured content to be written. - path: Location of the file. - encoding: The encoding to report on the first line of the XML file. - pretty: True if we want pretty printing with indents and new lines. - """ - xml_string = XmlToString(content, encoding, pretty) - if win32 and os.linesep != '\r\n': - xml_string = xml_string.replace('\n', '\r\n') - - default_encoding = locale.getdefaultlocale()[1] - if default_encoding.upper() != encoding.upper(): - xml_string = xml_string.decode(default_encoding).encode(encoding) - - # Get the old content - try: - f = open(path, 'r') - existing = f.read() - f.close() - except: - existing = None - - # It has changed, write it - if existing != xml_string: - f = open(path, 'w') - f.write(xml_string) - f.close() - - -_xml_escape_map = { - '"': '"', - "'": ''', - '<': '<', - '>': '>', - '&': '&', - '\n': ' ', - '\r': ' ', -} - - -_xml_escape_re = re.compile( - "(%s)" % "|".join(map(re.escape, _xml_escape_map.keys()))) - - -def _XmlEscape(value, attr=False): - """ Escape a string for inclusion in XML.""" - def replace(match): - m = match.string[match.start() : match.end()] - # don't replace single quotes in attrs - if attr and m == "'": - return m - return _xml_escape_map[m] - return _xml_escape_re.sub(replace, value) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py deleted file mode 100755 index df64354982c01..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/easy_xml_test.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2011 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. - -""" Unit tests for the easy_xml.py file. """ - -import gyp.easy_xml as easy_xml -import unittest -import StringIO - - -class TestSequenceFunctions(unittest.TestCase): - - def setUp(self): - self.stderr = StringIO.StringIO() - - def test_EasyXml_simple(self): - self.assertEqual( - easy_xml.XmlToString(['test']), - '') - - self.assertEqual( - easy_xml.XmlToString(['test'], encoding='Windows-1252'), - '') - - def test_EasyXml_simple_with_attributes(self): - self.assertEqual( - easy_xml.XmlToString(['test2', {'a': 'value1', 'b': 'value2'}]), - '') - - def test_EasyXml_escaping(self): - original = '\'"\r&\nfoo' - converted = '<test>\'" & foo' - converted_apos = converted.replace("'", ''') - self.assertEqual( - easy_xml.XmlToString(['test3', {'a': original}, original]), - '%s' % - (converted, converted_apos)) - - def test_EasyXml_pretty(self): - self.assertEqual( - easy_xml.XmlToString( - ['test3', - ['GrandParent', - ['Parent1', - ['Child'] - ], - ['Parent2'] - ] - ], - pretty=True), - '\n' - '\n' - ' \n' - ' \n' - ' \n' - ' \n' - ' \n' - ' \n' - '\n') - - - def test_EasyXml_complex(self): - # We want to create: - target = ( - '' - '' - '' - '{D2250C20-3A94-4FB9-AF73-11BC5B73884B}' - 'Win32Proj' - 'automated_ui_tests' - '' - '' - '' - 'Application' - 'Unicode' - '' - '') - - xml = easy_xml.XmlToString( - ['Project', - ['PropertyGroup', {'Label': 'Globals'}, - ['ProjectGuid', '{D2250C20-3A94-4FB9-AF73-11BC5B73884B}'], - ['Keyword', 'Win32Proj'], - ['RootNamespace', 'automated_ui_tests'] - ], - ['Import', {'Project': '$(VCTargetsPath)\\Microsoft.Cpp.props'}], - ['PropertyGroup', - {'Condition': "'$(Configuration)|$(Platform)'=='Debug|Win32'", - 'Label': 'Configuration'}, - ['ConfigurationType', 'Application'], - ['CharacterSet', 'Unicode'] - ] - ]) - self.assertEqual(xml, target) - - -if __name__ == '__main__': - unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py deleted file mode 100755 index b38d8660f7285..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/flock_tool.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2011 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. - -"""These functions are executed via gyp-flock-tool when using the Makefile -generator. Used on systems that don't have a built-in flock.""" - -import fcntl -import os -import struct -import subprocess -import sys - - -def main(args): - executor = FlockTool() - executor.Dispatch(args) - - -class FlockTool(object): - """This class emulates the 'flock' command.""" - def Dispatch(self, args): - """Dispatches a string command to a method.""" - if len(args) < 1: - raise Exception("Not enough arguments") - - method = "Exec%s" % self._CommandifyName(args[0]) - getattr(self, method)(*args[1:]) - - def _CommandifyName(self, name_string): - """Transforms a tool name like copy-info-plist to CopyInfoPlist""" - return name_string.title().replace('-', '') - - def ExecFlock(self, lockfile, *cmd_list): - """Emulates the most basic behavior of Linux's flock(1).""" - # Rely on exception handling to report errors. - # Note that the stock python on SunOS has a bug - # where fcntl.flock(fd, LOCK_EX) always fails - # with EBADF, that's why we use this F_SETLK - # hack instead. - fd = os.open(lockfile, os.O_WRONLY|os.O_NOCTTY|os.O_CREAT, 0666) - if sys.platform.startswith('aix'): - # Python on AIX is compiled with LARGEFILE support, which changes the - # struct size. - op = struct.pack('hhIllqq', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0) - else: - op = struct.pack('hhllhhl', fcntl.F_WRLCK, 0, 0, 0, 0, 0, 0) - fcntl.fcntl(fd, fcntl.F_SETLK, op) - return subprocess.call(cmd_list) - - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/__init__.py deleted file mode 100644 index e69de29bb2d1d..0000000000000 diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py deleted file mode 100644 index 921c1a6b71432..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/analyzer.py +++ /dev/null @@ -1,741 +0,0 @@ -# Copyright (c) 2014 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. - -""" -This script is intended for use as a GYP_GENERATOR. It takes as input (by way of -the generator flag config_path) the path of a json file that dictates the files -and targets to search for. The following keys are supported: -files: list of paths (relative) of the files to search for. -test_targets: unqualified target names to search for. Any target in this list -that depends upon a file in |files| is output regardless of the type of target -or chain of dependencies. -additional_compile_targets: Unqualified targets to search for in addition to -test_targets. Targets in the combined list that depend upon a file in |files| -are not necessarily output. For example, if the target is of type none then the -target is not output (but one of the descendants of the target will be). - -The following is output: -error: only supplied if there is an error. -compile_targets: minimal set of targets that directly or indirectly (for - targets of type none) depend on the files in |files| and is one of the - supplied targets or a target that one of the supplied targets depends on. - The expectation is this set of targets is passed into a build step. This list - always contains the output of test_targets as well. -test_targets: set of targets from the supplied |test_targets| that either - directly or indirectly depend upon a file in |files|. This list if useful - if additional processing needs to be done for certain targets after the - build, such as running tests. -status: outputs one of three values: none of the supplied files were found, - one of the include files changed so that it should be assumed everything - changed (in this case test_targets and compile_targets are not output) or at - least one file was found. -invalid_targets: list of supplied targets that were not found. - -Example: -Consider a graph like the following: - A D - / \ -B C -A depends upon both B and C, A is of type none and B and C are executables. -D is an executable, has no dependencies and nothing depends on it. -If |additional_compile_targets| = ["A"], |test_targets| = ["B", "C"] and -files = ["b.cc", "d.cc"] (B depends upon b.cc and D depends upon d.cc), then -the following is output: -|compile_targets| = ["B"] B must built as it depends upon the changed file b.cc -and the supplied target A depends upon it. A is not output as a build_target -as it is of type none with no rules and actions. -|test_targets| = ["B"] B directly depends upon the change file b.cc. - -Even though the file d.cc, which D depends upon, has changed D is not output -as it was not supplied by way of |additional_compile_targets| or |test_targets|. - -If the generator flag analyzer_output_path is specified, output is written -there. Otherwise output is written to stdout. - -In Gyp the "all" target is shorthand for the root targets in the files passed -to gyp. For example, if file "a.gyp" contains targets "a1" and -"a2", and file "b.gyp" contains targets "b1" and "b2" and "a2" has a dependency -on "b2" and gyp is supplied "a.gyp" then "all" consists of "a1" and "a2". -Notice that "b1" and "b2" are not in the "all" target as "b.gyp" was not -directly supplied to gyp. OTOH if both "a.gyp" and "b.gyp" are supplied to gyp -then the "all" target includes "b1" and "b2". -""" - -import gyp.common -import gyp.ninja_syntax as ninja_syntax -import json -import os -import posixpath -import sys - -debug = False - -found_dependency_string = 'Found dependency' -no_dependency_string = 'No dependencies' -# Status when it should be assumed that everything has changed. -all_changed_string = 'Found dependency (all)' - -# MatchStatus is used indicate if and how a target depends upon the supplied -# sources. -# The target's sources contain one of the supplied paths. -MATCH_STATUS_MATCHES = 1 -# The target has a dependency on another target that contains one of the -# supplied paths. -MATCH_STATUS_MATCHES_BY_DEPENDENCY = 2 -# The target's sources weren't in the supplied paths and none of the target's -# dependencies depend upon a target that matched. -MATCH_STATUS_DOESNT_MATCH = 3 -# The target doesn't contain the source, but the dependent targets have not yet -# been visited to determine a more specific status yet. -MATCH_STATUS_TBD = 4 - -generator_supports_multiple_toolsets = gyp.common.CrossCompileRequested() - -generator_wants_static_library_dependencies_adjusted = False - -generator_default_variables = { -} -for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR', - 'LIB_DIR', 'SHARED_LIB_DIR']: - generator_default_variables[dirname] = '!!!' - -for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', - 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', - 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX', - 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX', - 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX', - 'CONFIGURATION_NAME']: - generator_default_variables[unused] = '' - - -def _ToGypPath(path): - """Converts a path to the format used by gyp.""" - if os.sep == '\\' and os.altsep == '/': - return path.replace('\\', '/') - return path - - -def _ResolveParent(path, base_path_components): - """Resolves |path|, which starts with at least one '../'. Returns an empty - string if the path shouldn't be considered. See _AddSources() for a - description of |base_path_components|.""" - depth = 0 - while path.startswith('../'): - depth += 1 - path = path[3:] - # Relative includes may go outside the source tree. For example, an action may - # have inputs in /usr/include, which are not in the source tree. - if depth > len(base_path_components): - return '' - if depth == len(base_path_components): - return path - return '/'.join(base_path_components[0:len(base_path_components) - depth]) + \ - '/' + path - - -def _AddSources(sources, base_path, base_path_components, result): - """Extracts valid sources from |sources| and adds them to |result|. Each - source file is relative to |base_path|, but may contain '..'. To make - resolving '..' easier |base_path_components| contains each of the - directories in |base_path|. Additionally each source may contain variables. - Such sources are ignored as it is assumed dependencies on them are expressed - and tracked in some other means.""" - # NOTE: gyp paths are always posix style. - for source in sources: - if not len(source) or source.startswith('!!!') or source.startswith('$'): - continue - # variable expansion may lead to //. - org_source = source - source = source[0] + source[1:].replace('//', '/') - if source.startswith('../'): - source = _ResolveParent(source, base_path_components) - if len(source): - result.append(source) - continue - result.append(base_path + source) - if debug: - print 'AddSource', org_source, result[len(result) - 1] - - -def _ExtractSourcesFromAction(action, base_path, base_path_components, - results): - if 'inputs' in action: - _AddSources(action['inputs'], base_path, base_path_components, results) - - -def _ToLocalPath(toplevel_dir, path): - """Converts |path| to a path relative to |toplevel_dir|.""" - if path == toplevel_dir: - return '' - if path.startswith(toplevel_dir + '/'): - return path[len(toplevel_dir) + len('/'):] - return path - - -def _ExtractSources(target, target_dict, toplevel_dir): - # |target| is either absolute or relative and in the format of the OS. Gyp - # source paths are always posix. Convert |target| to a posix path relative to - # |toplevel_dir_|. This is done to make it easy to build source paths. - base_path = posixpath.dirname(_ToLocalPath(toplevel_dir, _ToGypPath(target))) - base_path_components = base_path.split('/') - - # Add a trailing '/' so that _AddSources() can easily build paths. - if len(base_path): - base_path += '/' - - if debug: - print 'ExtractSources', target, base_path - - results = [] - if 'sources' in target_dict: - _AddSources(target_dict['sources'], base_path, base_path_components, - results) - # Include the inputs from any actions. Any changes to these affect the - # resulting output. - if 'actions' in target_dict: - for action in target_dict['actions']: - _ExtractSourcesFromAction(action, base_path, base_path_components, - results) - if 'rules' in target_dict: - for rule in target_dict['rules']: - _ExtractSourcesFromAction(rule, base_path, base_path_components, results) - - return results - - -class Target(object): - """Holds information about a particular target: - deps: set of Targets this Target depends upon. This is not recursive, only the - direct dependent Targets. - match_status: one of the MatchStatus values. - back_deps: set of Targets that have a dependency on this Target. - visited: used during iteration to indicate whether we've visited this target. - This is used for two iterations, once in building the set of Targets and - again in _GetBuildTargets(). - name: fully qualified name of the target. - requires_build: True if the target type is such that it needs to be built. - See _DoesTargetTypeRequireBuild for details. - added_to_compile_targets: used when determining if the target was added to the - set of targets that needs to be built. - in_roots: true if this target is a descendant of one of the root nodes. - is_executable: true if the type of target is executable. - is_static_library: true if the type of target is static_library. - is_or_has_linked_ancestor: true if the target does a link (eg executable), or - if there is a target in back_deps that does a link.""" - def __init__(self, name): - self.deps = set() - self.match_status = MATCH_STATUS_TBD - self.back_deps = set() - self.name = name - # TODO(sky): I don't like hanging this off Target. This state is specific - # to certain functions and should be isolated there. - self.visited = False - self.requires_build = False - self.added_to_compile_targets = False - self.in_roots = False - self.is_executable = False - self.is_static_library = False - self.is_or_has_linked_ancestor = False - - -class Config(object): - """Details what we're looking for - files: set of files to search for - targets: see file description for details.""" - def __init__(self): - self.files = [] - self.targets = set() - self.additional_compile_target_names = set() - self.test_target_names = set() - - def Init(self, params): - """Initializes Config. This is a separate method as it raises an exception - if there is a parse error.""" - generator_flags = params.get('generator_flags', {}) - config_path = generator_flags.get('config_path', None) - if not config_path: - return - try: - f = open(config_path, 'r') - config = json.load(f) - f.close() - except IOError: - raise Exception('Unable to open file ' + config_path) - except ValueError as e: - raise Exception('Unable to parse config file ' + config_path + str(e)) - if not isinstance(config, dict): - raise Exception('config_path must be a JSON file containing a dictionary') - self.files = config.get('files', []) - self.additional_compile_target_names = set( - config.get('additional_compile_targets', [])) - self.test_target_names = set(config.get('test_targets', [])) - - -def _WasBuildFileModified(build_file, data, files, toplevel_dir): - """Returns true if the build file |build_file| is either in |files| or - one of the files included by |build_file| is in |files|. |toplevel_dir| is - the root of the source tree.""" - if _ToLocalPath(toplevel_dir, _ToGypPath(build_file)) in files: - if debug: - print 'gyp file modified', build_file - return True - - # First element of included_files is the file itself. - if len(data[build_file]['included_files']) <= 1: - return False - - for include_file in data[build_file]['included_files'][1:]: - # |included_files| are relative to the directory of the |build_file|. - rel_include_file = \ - _ToGypPath(gyp.common.UnrelativePath(include_file, build_file)) - if _ToLocalPath(toplevel_dir, rel_include_file) in files: - if debug: - print 'included gyp file modified, gyp_file=', build_file, \ - 'included file=', rel_include_file - return True - return False - - -def _GetOrCreateTargetByName(targets, target_name): - """Creates or returns the Target at targets[target_name]. If there is no - Target for |target_name| one is created. Returns a tuple of whether a new - Target was created and the Target.""" - if target_name in targets: - return False, targets[target_name] - target = Target(target_name) - targets[target_name] = target - return True, target - - -def _DoesTargetTypeRequireBuild(target_dict): - """Returns true if the target type is such that it needs to be built.""" - # If a 'none' target has rules or actions we assume it requires a build. - return bool(target_dict['type'] != 'none' or - target_dict.get('actions') or target_dict.get('rules')) - - -def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files, - build_files): - """Returns a tuple of the following: - . A dictionary mapping from fully qualified name to Target. - . A list of the targets that have a source file in |files|. - . Targets that constitute the 'all' target. See description at top of file - for details on the 'all' target. - This sets the |match_status| of the targets that contain any of the source - files in |files| to MATCH_STATUS_MATCHES. - |toplevel_dir| is the root of the source tree.""" - # Maps from target name to Target. - name_to_target = {} - - # Targets that matched. - matching_targets = [] - - # Queue of targets to visit. - targets_to_visit = target_list[:] - - # Maps from build file to a boolean indicating whether the build file is in - # |files|. - build_file_in_files = {} - - # Root targets across all files. - roots = set() - - # Set of Targets in |build_files|. - build_file_targets = set() - - while len(targets_to_visit) > 0: - target_name = targets_to_visit.pop() - created_target, target = _GetOrCreateTargetByName(name_to_target, - target_name) - if created_target: - roots.add(target) - elif target.visited: - continue - - target.visited = True - target.requires_build = _DoesTargetTypeRequireBuild( - target_dicts[target_name]) - target_type = target_dicts[target_name]['type'] - target.is_executable = target_type == 'executable' - target.is_static_library = target_type == 'static_library' - target.is_or_has_linked_ancestor = (target_type == 'executable' or - target_type == 'shared_library') - - build_file = gyp.common.ParseQualifiedTarget(target_name)[0] - if not build_file in build_file_in_files: - build_file_in_files[build_file] = \ - _WasBuildFileModified(build_file, data, files, toplevel_dir) - - if build_file in build_files: - build_file_targets.add(target) - - # If a build file (or any of its included files) is modified we assume all - # targets in the file are modified. - if build_file_in_files[build_file]: - print 'matching target from modified build file', target_name - target.match_status = MATCH_STATUS_MATCHES - matching_targets.append(target) - else: - sources = _ExtractSources(target_name, target_dicts[target_name], - toplevel_dir) - for source in sources: - if _ToGypPath(os.path.normpath(source)) in files: - print 'target', target_name, 'matches', source - target.match_status = MATCH_STATUS_MATCHES - matching_targets.append(target) - break - - # Add dependencies to visit as well as updating back pointers for deps. - for dep in target_dicts[target_name].get('dependencies', []): - targets_to_visit.append(dep) - - created_dep_target, dep_target = _GetOrCreateTargetByName(name_to_target, - dep) - if not created_dep_target: - roots.discard(dep_target) - - target.deps.add(dep_target) - dep_target.back_deps.add(target) - - return name_to_target, matching_targets, roots & build_file_targets - - -def _GetUnqualifiedToTargetMapping(all_targets, to_find): - """Returns a tuple of the following: - . mapping (dictionary) from unqualified name to Target for all the - Targets in |to_find|. - . any target names not found. If this is empty all targets were found.""" - result = {} - if not to_find: - return {}, [] - to_find = set(to_find) - for target_name in all_targets.keys(): - extracted = gyp.common.ParseQualifiedTarget(target_name) - if len(extracted) > 1 and extracted[1] in to_find: - to_find.remove(extracted[1]) - result[extracted[1]] = all_targets[target_name] - if not to_find: - return result, [] - return result, [x for x in to_find] - - -def _DoesTargetDependOnMatchingTargets(target): - """Returns true if |target| or any of its dependencies is one of the - targets containing the files supplied as input to analyzer. This updates - |matches| of the Targets as it recurses. - target: the Target to look for.""" - if target.match_status == MATCH_STATUS_DOESNT_MATCH: - return False - if target.match_status == MATCH_STATUS_MATCHES or \ - target.match_status == MATCH_STATUS_MATCHES_BY_DEPENDENCY: - return True - for dep in target.deps: - if _DoesTargetDependOnMatchingTargets(dep): - target.match_status = MATCH_STATUS_MATCHES_BY_DEPENDENCY - print '\t', target.name, 'matches by dep', dep.name - return True - target.match_status = MATCH_STATUS_DOESNT_MATCH - return False - - -def _GetTargetsDependingOnMatchingTargets(possible_targets): - """Returns the list of Targets in |possible_targets| that depend (either - directly on indirectly) on at least one of the targets containing the files - supplied as input to analyzer. - possible_targets: targets to search from.""" - found = [] - print 'Targets that matched by dependency:' - for target in possible_targets: - if _DoesTargetDependOnMatchingTargets(target): - found.append(target) - return found - - -def _AddCompileTargets(target, roots, add_if_no_ancestor, result): - """Recurses through all targets that depend on |target|, adding all targets - that need to be built (and are in |roots|) to |result|. - roots: set of root targets. - add_if_no_ancestor: If true and there are no ancestors of |target| then add - |target| to |result|. |target| must still be in |roots|. - result: targets that need to be built are added here.""" - if target.visited: - return - - target.visited = True - target.in_roots = target in roots - - for back_dep_target in target.back_deps: - _AddCompileTargets(back_dep_target, roots, False, result) - target.added_to_compile_targets |= back_dep_target.added_to_compile_targets - target.in_roots |= back_dep_target.in_roots - target.is_or_has_linked_ancestor |= ( - back_dep_target.is_or_has_linked_ancestor) - - # Always add 'executable' targets. Even though they may be built by other - # targets that depend upon them it makes detection of what is going to be - # built easier. - # And always add static_libraries that have no dependencies on them from - # linkables. This is necessary as the other dependencies on them may be - # static libraries themselves, which are not compile time dependencies. - if target.in_roots and \ - (target.is_executable or - (not target.added_to_compile_targets and - (add_if_no_ancestor or target.requires_build)) or - (target.is_static_library and add_if_no_ancestor and - not target.is_or_has_linked_ancestor)): - print '\t\tadding to compile targets', target.name, 'executable', \ - target.is_executable, 'added_to_compile_targets', \ - target.added_to_compile_targets, 'add_if_no_ancestor', \ - add_if_no_ancestor, 'requires_build', target.requires_build, \ - 'is_static_library', target.is_static_library, \ - 'is_or_has_linked_ancestor', target.is_or_has_linked_ancestor - result.add(target) - target.added_to_compile_targets = True - - -def _GetCompileTargets(matching_targets, supplied_targets): - """Returns the set of Targets that require a build. - matching_targets: targets that changed and need to be built. - supplied_targets: set of targets supplied to analyzer to search from.""" - result = set() - for target in matching_targets: - print 'finding compile targets for match', target.name - _AddCompileTargets(target, supplied_targets, True, result) - return result - - -def _WriteOutput(params, **values): - """Writes the output, either to stdout or a file is specified.""" - if 'error' in values: - print 'Error:', values['error'] - if 'status' in values: - print values['status'] - if 'targets' in values: - values['targets'].sort() - print 'Supplied targets that depend on changed files:' - for target in values['targets']: - print '\t', target - if 'invalid_targets' in values: - values['invalid_targets'].sort() - print 'The following targets were not found:' - for target in values['invalid_targets']: - print '\t', target - if 'build_targets' in values: - values['build_targets'].sort() - print 'Targets that require a build:' - for target in values['build_targets']: - print '\t', target - if 'compile_targets' in values: - values['compile_targets'].sort() - print 'Targets that need to be built:' - for target in values['compile_targets']: - print '\t', target - if 'test_targets' in values: - values['test_targets'].sort() - print 'Test targets:' - for target in values['test_targets']: - print '\t', target - - output_path = params.get('generator_flags', {}).get( - 'analyzer_output_path', None) - if not output_path: - print json.dumps(values) - return - try: - f = open(output_path, 'w') - f.write(json.dumps(values) + '\n') - f.close() - except IOError as e: - print 'Error writing to output file', output_path, str(e) - - -def _WasGypIncludeFileModified(params, files): - """Returns true if one of the files in |files| is in the set of included - files.""" - if params['options'].includes: - for include in params['options'].includes: - if _ToGypPath(os.path.normpath(include)) in files: - print 'Include file modified, assuming all changed', include - return True - return False - - -def _NamesNotIn(names, mapping): - """Returns a list of the values in |names| that are not in |mapping|.""" - return [name for name in names if name not in mapping] - - -def _LookupTargets(names, mapping): - """Returns a list of the mapping[name] for each value in |names| that is in - |mapping|.""" - return [mapping[name] for name in names if name in mapping] - - -def CalculateVariables(default_variables, params): - """Calculate additional variables for use in the build (called by gyp).""" - flavor = gyp.common.GetFlavor(params) - if flavor == 'mac': - default_variables.setdefault('OS', 'mac') - elif flavor == 'win': - default_variables.setdefault('OS', 'win') - # Copy additional generator configuration data from VS, which is shared - # by the Windows Ninja generator. - import gyp.generator.msvs as msvs_generator - generator_additional_non_configuration_keys = getattr(msvs_generator, - 'generator_additional_non_configuration_keys', []) - generator_additional_path_sections = getattr(msvs_generator, - 'generator_additional_path_sections', []) - - gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) - else: - operating_system = flavor - if flavor == 'android': - operating_system = 'linux' # Keep this legacy behavior for now. - default_variables.setdefault('OS', operating_system) - - -class TargetCalculator(object): - """Calculates the matching test_targets and matching compile_targets.""" - def __init__(self, files, additional_compile_target_names, test_target_names, - data, target_list, target_dicts, toplevel_dir, build_files): - self._additional_compile_target_names = set(additional_compile_target_names) - self._test_target_names = set(test_target_names) - self._name_to_target, self._changed_targets, self._root_targets = ( - _GenerateTargets(data, target_list, target_dicts, toplevel_dir, - frozenset(files), build_files)) - self._unqualified_mapping, self.invalid_targets = ( - _GetUnqualifiedToTargetMapping(self._name_to_target, - self._supplied_target_names_no_all())) - - def _supplied_target_names(self): - return self._additional_compile_target_names | self._test_target_names - - def _supplied_target_names_no_all(self): - """Returns the supplied test targets without 'all'.""" - result = self._supplied_target_names(); - result.discard('all') - return result - - def is_build_impacted(self): - """Returns true if the supplied files impact the build at all.""" - return self._changed_targets - - def find_matching_test_target_names(self): - """Returns the set of output test targets.""" - assert self.is_build_impacted() - # Find the test targets first. 'all' is special cased to mean all the - # root targets. To deal with all the supplied |test_targets| are expanded - # to include the root targets during lookup. If any of the root targets - # match, we remove it and replace it with 'all'. - test_target_names_no_all = set(self._test_target_names) - test_target_names_no_all.discard('all') - test_targets_no_all = _LookupTargets(test_target_names_no_all, - self._unqualified_mapping) - test_target_names_contains_all = 'all' in self._test_target_names - if test_target_names_contains_all: - test_targets = [x for x in (set(test_targets_no_all) | - set(self._root_targets))] - else: - test_targets = [x for x in test_targets_no_all] - print 'supplied test_targets' - for target_name in self._test_target_names: - print '\t', target_name - print 'found test_targets' - for target in test_targets: - print '\t', target.name - print 'searching for matching test targets' - matching_test_targets = _GetTargetsDependingOnMatchingTargets(test_targets) - matching_test_targets_contains_all = (test_target_names_contains_all and - set(matching_test_targets) & - set(self._root_targets)) - if matching_test_targets_contains_all: - # Remove any of the targets for all that were not explicitly supplied, - # 'all' is subsequentely added to the matching names below. - matching_test_targets = [x for x in (set(matching_test_targets) & - set(test_targets_no_all))] - print 'matched test_targets' - for target in matching_test_targets: - print '\t', target.name - matching_target_names = [gyp.common.ParseQualifiedTarget(target.name)[1] - for target in matching_test_targets] - if matching_test_targets_contains_all: - matching_target_names.append('all') - print '\tall' - return matching_target_names - - def find_matching_compile_target_names(self): - """Returns the set of output compile targets.""" - assert self.is_build_impacted(); - # Compile targets are found by searching up from changed targets. - # Reset the visited status for _GetBuildTargets. - for target in self._name_to_target.itervalues(): - target.visited = False - - supplied_targets = _LookupTargets(self._supplied_target_names_no_all(), - self._unqualified_mapping) - if 'all' in self._supplied_target_names(): - supplied_targets = [x for x in (set(supplied_targets) | - set(self._root_targets))] - print 'Supplied test_targets & compile_targets' - for target in supplied_targets: - print '\t', target.name - print 'Finding compile targets' - compile_targets = _GetCompileTargets(self._changed_targets, - supplied_targets) - return [gyp.common.ParseQualifiedTarget(target.name)[1] - for target in compile_targets] - - -def GenerateOutput(target_list, target_dicts, data, params): - """Called by gyp as the final stage. Outputs results.""" - config = Config() - try: - config.Init(params) - - if not config.files: - raise Exception('Must specify files to analyze via config_path generator ' - 'flag') - - toplevel_dir = _ToGypPath(os.path.abspath(params['options'].toplevel_dir)) - if debug: - print 'toplevel_dir', toplevel_dir - - if _WasGypIncludeFileModified(params, config.files): - result_dict = { 'status': all_changed_string, - 'test_targets': list(config.test_target_names), - 'compile_targets': list( - config.additional_compile_target_names | - config.test_target_names) } - _WriteOutput(params, **result_dict) - return - - calculator = TargetCalculator(config.files, - config.additional_compile_target_names, - config.test_target_names, data, - target_list, target_dicts, toplevel_dir, - params['build_files']) - if not calculator.is_build_impacted(): - result_dict = { 'status': no_dependency_string, - 'test_targets': [], - 'compile_targets': [] } - if calculator.invalid_targets: - result_dict['invalid_targets'] = calculator.invalid_targets - _WriteOutput(params, **result_dict) - return - - test_target_names = calculator.find_matching_test_target_names() - compile_target_names = calculator.find_matching_compile_target_names() - found_at_least_one_target = compile_target_names or test_target_names - result_dict = { 'test_targets': test_target_names, - 'status': found_dependency_string if - found_at_least_one_target else no_dependency_string, - 'compile_targets': list( - set(compile_target_names) | - set(test_target_names)) } - if calculator.invalid_targets: - result_dict['invalid_targets'] = calculator.invalid_targets - _WriteOutput(params, **result_dict) - - except Exception as e: - _WriteOutput(params, error=str(e)) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py deleted file mode 100644 index 5b26cc785a80e..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/android.py +++ /dev/null @@ -1,1095 +0,0 @@ -# Copyright (c) 2012 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. - -# Notes: -# -# This generates makefiles suitable for inclusion into the Android build system -# via an Android.mk file. It is based on make.py, the standard makefile -# generator. -# -# The code below generates a separate .mk file for each target, but -# all are sourced by the top-level GypAndroid.mk. This means that all -# variables in .mk-files clobber one another, and furthermore that any -# variables set potentially clash with other Android build system variables. -# Try to avoid setting global variables where possible. - -import gyp -import gyp.common -import gyp.generator.make as make # Reuse global functions from make backend. -import os -import re -import subprocess - -generator_default_variables = { - 'OS': 'android', - 'EXECUTABLE_PREFIX': '', - 'EXECUTABLE_SUFFIX': '', - 'STATIC_LIB_PREFIX': 'lib', - 'SHARED_LIB_PREFIX': 'lib', - 'STATIC_LIB_SUFFIX': '.a', - 'SHARED_LIB_SUFFIX': '.so', - 'INTERMEDIATE_DIR': '$(gyp_intermediate_dir)', - 'SHARED_INTERMEDIATE_DIR': '$(gyp_shared_intermediate_dir)', - 'PRODUCT_DIR': '$(gyp_shared_intermediate_dir)', - 'SHARED_LIB_DIR': '$(builddir)/lib.$(TOOLSET)', - 'LIB_DIR': '$(obj).$(TOOLSET)', - 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python. - 'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s', # This gets expanded by Python. - 'RULE_INPUT_PATH': '$(RULE_SOURCES)', - 'RULE_INPUT_EXT': '$(suffix $<)', - 'RULE_INPUT_NAME': '$(notdir $<)', - 'CONFIGURATION_NAME': '$(GYP_CONFIGURATION)', -} - -# Make supports multiple toolsets -generator_supports_multiple_toolsets = True - - -# Generator-specific gyp specs. -generator_additional_non_configuration_keys = [ - # Boolean to declare that this target does not want its name mangled. - 'android_unmangled_name', - # Map of android build system variables to set. - 'aosp_build_settings', -] -generator_additional_path_sections = [] -generator_extra_sources_for_rules = [] - - -ALL_MODULES_FOOTER = """\ -# "gyp_all_modules" is a concatenation of the "gyp_all_modules" targets from -# all the included sub-makefiles. This is just here to clarify. -gyp_all_modules: -""" - -header = """\ -# This file is generated by gyp; do not edit. - -""" - -# Map gyp target types to Android module classes. -MODULE_CLASSES = { - 'static_library': 'STATIC_LIBRARIES', - 'shared_library': 'SHARED_LIBRARIES', - 'executable': 'EXECUTABLES', -} - - -def IsCPPExtension(ext): - return make.COMPILABLE_EXTENSIONS.get(ext) == 'cxx' - - -def Sourceify(path): - """Convert a path to its source directory form. The Android backend does not - support options.generator_output, so this function is a noop.""" - return path - - -# Map from qualified target to path to output. -# For Android, the target of these maps is a tuple ('static', 'modulename'), -# ('dynamic', 'modulename'), or ('path', 'some/path') instead of a string, -# since we link by module. -target_outputs = {} -# Map from qualified target to any linkable output. A subset -# of target_outputs. E.g. when mybinary depends on liba, we want to -# include liba in the linker line; when otherbinary depends on -# mybinary, we just want to build mybinary first. -target_link_deps = {} - - -class AndroidMkWriter(object): - """AndroidMkWriter packages up the writing of one target-specific Android.mk. - - Its only real entry point is Write(), and is mostly used for namespacing. - """ - - def __init__(self, android_top_dir): - self.android_top_dir = android_top_dir - - def Write(self, qualified_target, relative_target, base_path, output_filename, - spec, configs, part_of_all, write_alias_target, sdk_version): - """The main entry point: writes a .mk file for a single target. - - Arguments: - qualified_target: target we're generating - relative_target: qualified target name relative to the root - base_path: path relative to source root we're building in, used to resolve - target-relative paths - output_filename: output .mk file name to write - spec, configs: gyp info - part_of_all: flag indicating this target is part of 'all' - write_alias_target: flag indicating whether to create short aliases for - this target - sdk_version: what to emit for LOCAL_SDK_VERSION in output - """ - gyp.common.EnsureDirExists(output_filename) - - self.fp = open(output_filename, 'w') - - self.fp.write(header) - - self.qualified_target = qualified_target - self.relative_target = relative_target - self.path = base_path - self.target = spec['target_name'] - self.type = spec['type'] - self.toolset = spec['toolset'] - - deps, link_deps = self.ComputeDeps(spec) - - # Some of the generation below can add extra output, sources, or - # link dependencies. All of the out params of the functions that - # follow use names like extra_foo. - extra_outputs = [] - extra_sources = [] - - self.android_class = MODULE_CLASSES.get(self.type, 'GYP') - self.android_module = self.ComputeAndroidModule(spec) - (self.android_stem, self.android_suffix) = self.ComputeOutputParts(spec) - self.output = self.output_binary = self.ComputeOutput(spec) - - # Standard header. - self.WriteLn('include $(CLEAR_VARS)\n') - - # Module class and name. - self.WriteLn('LOCAL_MODULE_CLASS := ' + self.android_class) - self.WriteLn('LOCAL_MODULE := ' + self.android_module) - # Only emit LOCAL_MODULE_STEM if it's different to LOCAL_MODULE. - # The library module classes fail if the stem is set. ComputeOutputParts - # makes sure that stem == modulename in these cases. - if self.android_stem != self.android_module: - self.WriteLn('LOCAL_MODULE_STEM := ' + self.android_stem) - self.WriteLn('LOCAL_MODULE_SUFFIX := ' + self.android_suffix) - if self.toolset == 'host': - self.WriteLn('LOCAL_IS_HOST_MODULE := true') - self.WriteLn('LOCAL_MULTILIB := $(GYP_HOST_MULTILIB)') - elif sdk_version > 0: - self.WriteLn('LOCAL_MODULE_TARGET_ARCH := ' - '$(TARGET_$(GYP_VAR_PREFIX)ARCH)') - self.WriteLn('LOCAL_SDK_VERSION := %s' % sdk_version) - - # Grab output directories; needed for Actions and Rules. - if self.toolset == 'host': - self.WriteLn('gyp_intermediate_dir := ' - '$(call local-intermediates-dir,,$(GYP_HOST_VAR_PREFIX))') - else: - self.WriteLn('gyp_intermediate_dir := ' - '$(call local-intermediates-dir,,$(GYP_VAR_PREFIX))') - self.WriteLn('gyp_shared_intermediate_dir := ' - '$(call intermediates-dir-for,GYP,shared,,,$(GYP_VAR_PREFIX))') - self.WriteLn() - - # List files this target depends on so that actions/rules/copies/sources - # can depend on the list. - # TODO: doesn't pull in things through transitive link deps; needed? - target_dependencies = [x[1] for x in deps if x[0] == 'path'] - self.WriteLn('# Make sure our deps are built first.') - self.WriteList(target_dependencies, 'GYP_TARGET_DEPENDENCIES', - local_pathify=True) - - # Actions must come first, since they can generate more OBJs for use below. - if 'actions' in spec: - self.WriteActions(spec['actions'], extra_sources, extra_outputs) - - # Rules must be early like actions. - if 'rules' in spec: - self.WriteRules(spec['rules'], extra_sources, extra_outputs) - - if 'copies' in spec: - self.WriteCopies(spec['copies'], extra_outputs) - - # GYP generated outputs. - self.WriteList(extra_outputs, 'GYP_GENERATED_OUTPUTS', local_pathify=True) - - # Set LOCAL_ADDITIONAL_DEPENDENCIES so that Android's build rules depend - # on both our dependency targets and our generated files. - self.WriteLn('# Make sure our deps and generated files are built first.') - self.WriteLn('LOCAL_ADDITIONAL_DEPENDENCIES := $(GYP_TARGET_DEPENDENCIES) ' - '$(GYP_GENERATED_OUTPUTS)') - self.WriteLn() - - # Sources. - if spec.get('sources', []) or extra_sources: - self.WriteSources(spec, configs, extra_sources) - - self.WriteTarget(spec, configs, deps, link_deps, part_of_all, - write_alias_target) - - # Update global list of target outputs, used in dependency tracking. - target_outputs[qualified_target] = ('path', self.output_binary) - - # Update global list of link dependencies. - if self.type == 'static_library': - target_link_deps[qualified_target] = ('static', self.android_module) - elif self.type == 'shared_library': - target_link_deps[qualified_target] = ('shared', self.android_module) - - self.fp.close() - return self.android_module - - - def WriteActions(self, actions, extra_sources, extra_outputs): - """Write Makefile code for any 'actions' from the gyp input. - - extra_sources: a list that will be filled in with newly generated source - files, if any - extra_outputs: a list that will be filled in with any outputs of these - actions (used to make other pieces dependent on these - actions) - """ - for action in actions: - name = make.StringToMakefileVariable('%s_%s' % (self.relative_target, - action['action_name'])) - self.WriteLn('### Rules for action "%s":' % action['action_name']) - inputs = action['inputs'] - outputs = action['outputs'] - - # Build up a list of outputs. - # Collect the output dirs we'll need. - dirs = set() - for out in outputs: - if not out.startswith('$'): - print ('WARNING: Action for target "%s" writes output to local path ' - '"%s".' % (self.target, out)) - dir = os.path.split(out)[0] - if dir: - dirs.add(dir) - if int(action.get('process_outputs_as_sources', False)): - extra_sources += outputs - - # Prepare the actual command. - command = gyp.common.EncodePOSIXShellList(action['action']) - if 'message' in action: - quiet_cmd = 'Gyp action: %s ($@)' % action['message'] - else: - quiet_cmd = 'Gyp action: %s ($@)' % name - if len(dirs) > 0: - command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command - - cd_action = 'cd $(gyp_local_path)/%s; ' % self.path - command = cd_action + command - - # The makefile rules are all relative to the top dir, but the gyp actions - # are defined relative to their containing dir. This replaces the gyp_* - # variables for the action rule with an absolute version so that the - # output goes in the right place. - # Only write the gyp_* rules for the "primary" output (:1); - # it's superfluous for the "extra outputs", and this avoids accidentally - # writing duplicate dummy rules for those outputs. - main_output = make.QuoteSpaces(self.LocalPathify(outputs[0])) - self.WriteLn('%s: gyp_local_path := $(LOCAL_PATH)' % main_output) - self.WriteLn('%s: gyp_var_prefix := $(GYP_VAR_PREFIX)' % main_output) - self.WriteLn('%s: gyp_intermediate_dir := ' - '$(abspath $(gyp_intermediate_dir))' % main_output) - self.WriteLn('%s: gyp_shared_intermediate_dir := ' - '$(abspath $(gyp_shared_intermediate_dir))' % main_output) - - # Android's envsetup.sh adds a number of directories to the path including - # the built host binary directory. This causes actions/rules invoked by - # gyp to sometimes use these instead of system versions, e.g. bison. - # The built host binaries may not be suitable, and can cause errors. - # So, we remove them from the PATH using the ANDROID_BUILD_PATHS variable - # set by envsetup. - self.WriteLn('%s: export PATH := $(subst $(ANDROID_BUILD_PATHS),,$(PATH))' - % main_output) - - # Don't allow spaces in input/output filenames, but make an exception for - # filenames which start with '$(' since it's okay for there to be spaces - # inside of make function/macro invocations. - for input in inputs: - if not input.startswith('$(') and ' ' in input: - raise gyp.common.GypError( - 'Action input filename "%s" in target %s contains a space' % - (input, self.target)) - for output in outputs: - if not output.startswith('$(') and ' ' in output: - raise gyp.common.GypError( - 'Action output filename "%s" in target %s contains a space' % - (output, self.target)) - - self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' % - (main_output, ' '.join(map(self.LocalPathify, inputs)))) - self.WriteLn('\t@echo "%s"' % quiet_cmd) - self.WriteLn('\t$(hide)%s\n' % command) - for output in outputs[1:]: - # Make each output depend on the main output, with an empty command - # to force make to notice that the mtime has changed. - self.WriteLn('%s: %s ;' % (self.LocalPathify(output), main_output)) - - extra_outputs += outputs - self.WriteLn() - - self.WriteLn() - - - def WriteRules(self, rules, extra_sources, extra_outputs): - """Write Makefile code for any 'rules' from the gyp input. - - extra_sources: a list that will be filled in with newly generated source - files, if any - extra_outputs: a list that will be filled in with any outputs of these - rules (used to make other pieces dependent on these rules) - """ - if len(rules) == 0: - return - - for rule in rules: - if len(rule.get('rule_sources', [])) == 0: - continue - name = make.StringToMakefileVariable('%s_%s' % (self.relative_target, - rule['rule_name'])) - self.WriteLn('\n### Generated for rule "%s":' % name) - self.WriteLn('# "%s":' % rule) - - inputs = rule.get('inputs') - for rule_source in rule.get('rule_sources', []): - (rule_source_dirname, rule_source_basename) = os.path.split(rule_source) - (rule_source_root, rule_source_ext) = \ - os.path.splitext(rule_source_basename) - - outputs = [self.ExpandInputRoot(out, rule_source_root, - rule_source_dirname) - for out in rule['outputs']] - - dirs = set() - for out in outputs: - if not out.startswith('$'): - print ('WARNING: Rule for target %s writes output to local path %s' - % (self.target, out)) - dir = os.path.dirname(out) - if dir: - dirs.add(dir) - extra_outputs += outputs - if int(rule.get('process_outputs_as_sources', False)): - extra_sources.extend(outputs) - - components = [] - for component in rule['action']: - component = self.ExpandInputRoot(component, rule_source_root, - rule_source_dirname) - if '$(RULE_SOURCES)' in component: - component = component.replace('$(RULE_SOURCES)', - rule_source) - components.append(component) - - command = gyp.common.EncodePOSIXShellList(components) - cd_action = 'cd $(gyp_local_path)/%s; ' % self.path - command = cd_action + command - if dirs: - command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command - - # We set up a rule to build the first output, and then set up - # a rule for each additional output to depend on the first. - outputs = map(self.LocalPathify, outputs) - main_output = outputs[0] - self.WriteLn('%s: gyp_local_path := $(LOCAL_PATH)' % main_output) - self.WriteLn('%s: gyp_var_prefix := $(GYP_VAR_PREFIX)' % main_output) - self.WriteLn('%s: gyp_intermediate_dir := ' - '$(abspath $(gyp_intermediate_dir))' % main_output) - self.WriteLn('%s: gyp_shared_intermediate_dir := ' - '$(abspath $(gyp_shared_intermediate_dir))' % main_output) - - # See explanation in WriteActions. - self.WriteLn('%s: export PATH := ' - '$(subst $(ANDROID_BUILD_PATHS),,$(PATH))' % main_output) - - main_output_deps = self.LocalPathify(rule_source) - if inputs: - main_output_deps += ' ' - main_output_deps += ' '.join([self.LocalPathify(f) for f in inputs]) - - self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES)' % - (main_output, main_output_deps)) - self.WriteLn('\t%s\n' % command) - for output in outputs[1:]: - # Make each output depend on the main output, with an empty command - # to force make to notice that the mtime has changed. - self.WriteLn('%s: %s ;' % (output, main_output)) - self.WriteLn() - - self.WriteLn() - - - def WriteCopies(self, copies, extra_outputs): - """Write Makefile code for any 'copies' from the gyp input. - - extra_outputs: a list that will be filled in with any outputs of this action - (used to make other pieces dependent on this action) - """ - self.WriteLn('### Generated for copy rule.') - - variable = make.StringToMakefileVariable(self.relative_target + '_copies') - outputs = [] - for copy in copies: - for path in copy['files']: - # The Android build system does not allow generation of files into the - # source tree. The destination should start with a variable, which will - # typically be $(gyp_intermediate_dir) or - # $(gyp_shared_intermediate_dir). Note that we can't use an assertion - # because some of the gyp tests depend on this. - if not copy['destination'].startswith('$'): - print ('WARNING: Copy rule for target %s writes output to ' - 'local path %s' % (self.target, copy['destination'])) - - # LocalPathify() calls normpath, stripping trailing slashes. - path = Sourceify(self.LocalPathify(path)) - filename = os.path.split(path)[1] - output = Sourceify(self.LocalPathify(os.path.join(copy['destination'], - filename))) - - self.WriteLn('%s: %s $(GYP_TARGET_DEPENDENCIES) | $(ACP)' % - (output, path)) - self.WriteLn('\t@echo Copying: $@') - self.WriteLn('\t$(hide) mkdir -p $(dir $@)') - self.WriteLn('\t$(hide) $(ACP) -rpf $< $@') - self.WriteLn() - outputs.append(output) - self.WriteLn('%s = %s' % (variable, - ' '.join(map(make.QuoteSpaces, outputs)))) - extra_outputs.append('$(%s)' % variable) - self.WriteLn() - - - def WriteSourceFlags(self, spec, configs): - """Write out the flags and include paths used to compile source files for - the current target. - - Args: - spec, configs: input from gyp. - """ - for configname, config in sorted(configs.iteritems()): - extracted_includes = [] - - self.WriteLn('\n# Flags passed to both C and C++ files.') - cflags, includes_from_cflags = self.ExtractIncludesFromCFlags( - config.get('cflags', []) + config.get('cflags_c', [])) - extracted_includes.extend(includes_from_cflags) - self.WriteList(cflags, 'MY_CFLAGS_%s' % configname) - - self.WriteList(config.get('defines'), 'MY_DEFS_%s' % configname, - prefix='-D', quoter=make.EscapeCppDefine) - - self.WriteLn('\n# Include paths placed before CFLAGS/CPPFLAGS') - includes = list(config.get('include_dirs', [])) - includes.extend(extracted_includes) - includes = map(Sourceify, map(self.LocalPathify, includes)) - includes = self.NormalizeIncludePaths(includes) - self.WriteList(includes, 'LOCAL_C_INCLUDES_%s' % configname) - - self.WriteLn('\n# Flags passed to only C++ (and not C) files.') - self.WriteList(config.get('cflags_cc'), 'LOCAL_CPPFLAGS_%s' % configname) - - self.WriteLn('\nLOCAL_CFLAGS := $(MY_CFLAGS_$(GYP_CONFIGURATION)) ' - '$(MY_DEFS_$(GYP_CONFIGURATION))') - # Undefine ANDROID for host modules - # TODO: the source code should not use macro ANDROID to tell if it's host - # or target module. - if self.toolset == 'host': - self.WriteLn('# Undefine ANDROID for host modules') - self.WriteLn('LOCAL_CFLAGS += -UANDROID') - self.WriteLn('LOCAL_C_INCLUDES := $(GYP_COPIED_SOURCE_ORIGIN_DIRS) ' - '$(LOCAL_C_INCLUDES_$(GYP_CONFIGURATION))') - self.WriteLn('LOCAL_CPPFLAGS := $(LOCAL_CPPFLAGS_$(GYP_CONFIGURATION))') - # Android uses separate flags for assembly file invocations, but gyp expects - # the same CFLAGS to be applied: - self.WriteLn('LOCAL_ASFLAGS := $(LOCAL_CFLAGS)') - - - def WriteSources(self, spec, configs, extra_sources): - """Write Makefile code for any 'sources' from the gyp input. - These are source files necessary to build the current target. - We need to handle shared_intermediate directory source files as - a special case by copying them to the intermediate directory and - treating them as a genereated sources. Otherwise the Android build - rules won't pick them up. - - Args: - spec, configs: input from gyp. - extra_sources: Sources generated from Actions or Rules. - """ - sources = filter(make.Compilable, spec.get('sources', [])) - generated_not_sources = [x for x in extra_sources if not make.Compilable(x)] - extra_sources = filter(make.Compilable, extra_sources) - - # Determine and output the C++ extension used by these sources. - # We simply find the first C++ file and use that extension. - all_sources = sources + extra_sources - local_cpp_extension = '.cpp' - for source in all_sources: - (root, ext) = os.path.splitext(source) - if IsCPPExtension(ext): - local_cpp_extension = ext - break - if local_cpp_extension != '.cpp': - self.WriteLn('LOCAL_CPP_EXTENSION := %s' % local_cpp_extension) - - # We need to move any non-generated sources that are coming from the - # shared intermediate directory out of LOCAL_SRC_FILES and put them - # into LOCAL_GENERATED_SOURCES. We also need to move over any C++ files - # that don't match our local_cpp_extension, since Android will only - # generate Makefile rules for a single LOCAL_CPP_EXTENSION. - local_files = [] - for source in sources: - (root, ext) = os.path.splitext(source) - if '$(gyp_shared_intermediate_dir)' in source: - extra_sources.append(source) - elif '$(gyp_intermediate_dir)' in source: - extra_sources.append(source) - elif IsCPPExtension(ext) and ext != local_cpp_extension: - extra_sources.append(source) - else: - local_files.append(os.path.normpath(os.path.join(self.path, source))) - - # For any generated source, if it is coming from the shared intermediate - # directory then we add a Make rule to copy them to the local intermediate - # directory first. This is because the Android LOCAL_GENERATED_SOURCES - # must be in the local module intermediate directory for the compile rules - # to work properly. If the file has the wrong C++ extension, then we add - # a rule to copy that to intermediates and use the new version. - final_generated_sources = [] - # If a source file gets copied, we still need to add the orginal source - # directory as header search path, for GCC searches headers in the - # directory that contains the source file by default. - origin_src_dirs = [] - for source in extra_sources: - local_file = source - if not '$(gyp_intermediate_dir)/' in local_file: - basename = os.path.basename(local_file) - local_file = '$(gyp_intermediate_dir)/' + basename - (root, ext) = os.path.splitext(local_file) - if IsCPPExtension(ext) and ext != local_cpp_extension: - local_file = root + local_cpp_extension - if local_file != source: - self.WriteLn('%s: %s' % (local_file, self.LocalPathify(source))) - self.WriteLn('\tmkdir -p $(@D); cp $< $@') - origin_src_dirs.append(os.path.dirname(source)) - final_generated_sources.append(local_file) - - # We add back in all of the non-compilable stuff to make sure that the - # make rules have dependencies on them. - final_generated_sources.extend(generated_not_sources) - self.WriteList(final_generated_sources, 'LOCAL_GENERATED_SOURCES') - - origin_src_dirs = gyp.common.uniquer(origin_src_dirs) - origin_src_dirs = map(Sourceify, map(self.LocalPathify, origin_src_dirs)) - self.WriteList(origin_src_dirs, 'GYP_COPIED_SOURCE_ORIGIN_DIRS') - - self.WriteList(local_files, 'LOCAL_SRC_FILES') - - # Write out the flags used to compile the source; this must be done last - # so that GYP_COPIED_SOURCE_ORIGIN_DIRS can be used as an include path. - self.WriteSourceFlags(spec, configs) - - - def ComputeAndroidModule(self, spec): - """Return the Android module name used for a gyp spec. - - We use the complete qualified target name to avoid collisions between - duplicate targets in different directories. We also add a suffix to - distinguish gyp-generated module names. - """ - - if int(spec.get('android_unmangled_name', 0)): - assert self.type != 'shared_library' or self.target.startswith('lib') - return self.target - - if self.type == 'shared_library': - # For reasons of convention, the Android build system requires that all - # shared library modules are named 'libfoo' when generating -l flags. - prefix = 'lib_' - else: - prefix = '' - - if spec['toolset'] == 'host': - suffix = '_$(TARGET_$(GYP_VAR_PREFIX)ARCH)_host_gyp' - else: - suffix = '_gyp' - - if self.path: - middle = make.StringToMakefileVariable('%s_%s' % (self.path, self.target)) - else: - middle = make.StringToMakefileVariable(self.target) - - return ''.join([prefix, middle, suffix]) - - - def ComputeOutputParts(self, spec): - """Return the 'output basename' of a gyp spec, split into filename + ext. - - Android libraries must be named the same thing as their module name, - otherwise the linker can't find them, so product_name and so on must be - ignored if we are building a library, and the "lib" prepending is - not done for Android. - """ - assert self.type != 'loadable_module' # TODO: not supported? - - target = spec['target_name'] - target_prefix = '' - target_ext = '' - if self.type == 'static_library': - target = self.ComputeAndroidModule(spec) - target_ext = '.a' - elif self.type == 'shared_library': - target = self.ComputeAndroidModule(spec) - target_ext = '.so' - elif self.type == 'none': - target_ext = '.stamp' - elif self.type != 'executable': - print ("ERROR: What output file should be generated?", - "type", self.type, "target", target) - - if self.type != 'static_library' and self.type != 'shared_library': - target_prefix = spec.get('product_prefix', target_prefix) - target = spec.get('product_name', target) - product_ext = spec.get('product_extension') - if product_ext: - target_ext = '.' + product_ext - - target_stem = target_prefix + target - return (target_stem, target_ext) - - - def ComputeOutputBasename(self, spec): - """Return the 'output basename' of a gyp spec. - - E.g., the loadable module 'foobar' in directory 'baz' will produce - 'libfoobar.so' - """ - return ''.join(self.ComputeOutputParts(spec)) - - - def ComputeOutput(self, spec): - """Return the 'output' (full output path) of a gyp spec. - - E.g., the loadable module 'foobar' in directory 'baz' will produce - '$(obj)/baz/libfoobar.so' - """ - if self.type == 'executable': - # We install host executables into shared_intermediate_dir so they can be - # run by gyp rules that refer to PRODUCT_DIR. - path = '$(gyp_shared_intermediate_dir)' - elif self.type == 'shared_library': - if self.toolset == 'host': - path = '$($(GYP_HOST_VAR_PREFIX)HOST_OUT_INTERMEDIATE_LIBRARIES)' - else: - path = '$($(GYP_VAR_PREFIX)TARGET_OUT_INTERMEDIATE_LIBRARIES)' - else: - # Other targets just get built into their intermediate dir. - if self.toolset == 'host': - path = ('$(call intermediates-dir-for,%s,%s,true,,' - '$(GYP_HOST_VAR_PREFIX))' % (self.android_class, - self.android_module)) - else: - path = ('$(call intermediates-dir-for,%s,%s,,,$(GYP_VAR_PREFIX))' - % (self.android_class, self.android_module)) - - assert spec.get('product_dir') is None # TODO: not supported? - return os.path.join(path, self.ComputeOutputBasename(spec)) - - def NormalizeIncludePaths(self, include_paths): - """ Normalize include_paths. - Convert absolute paths to relative to the Android top directory. - - Args: - include_paths: A list of unprocessed include paths. - Returns: - A list of normalized include paths. - """ - normalized = [] - for path in include_paths: - if path[0] == '/': - path = gyp.common.RelativePath(path, self.android_top_dir) - normalized.append(path) - return normalized - - def ExtractIncludesFromCFlags(self, cflags): - """Extract includes "-I..." out from cflags - - Args: - cflags: A list of compiler flags, which may be mixed with "-I.." - Returns: - A tuple of lists: (clean_clfags, include_paths). "-I.." is trimmed. - """ - clean_cflags = [] - include_paths = [] - for flag in cflags: - if flag.startswith('-I'): - include_paths.append(flag[2:]) - else: - clean_cflags.append(flag) - - return (clean_cflags, include_paths) - - def FilterLibraries(self, libraries): - """Filter the 'libraries' key to separate things that shouldn't be ldflags. - - Library entries that look like filenames should be converted to android - module names instead of being passed to the linker as flags. - - Args: - libraries: the value of spec.get('libraries') - Returns: - A tuple (static_lib_modules, dynamic_lib_modules, ldflags) - """ - static_lib_modules = [] - dynamic_lib_modules = [] - ldflags = [] - for libs in libraries: - # Libs can have multiple words. - for lib in libs.split(): - # Filter the system libraries, which are added by default by the Android - # build system. - if (lib == '-lc' or lib == '-lstdc++' or lib == '-lm' or - lib.endswith('libgcc.a')): - continue - match = re.search(r'([^/]+)\.a$', lib) - if match: - static_lib_modules.append(match.group(1)) - continue - match = re.search(r'([^/]+)\.so$', lib) - if match: - dynamic_lib_modules.append(match.group(1)) - continue - if lib.startswith('-l'): - ldflags.append(lib) - return (static_lib_modules, dynamic_lib_modules, ldflags) - - - def ComputeDeps(self, spec): - """Compute the dependencies of a gyp spec. - - Returns a tuple (deps, link_deps), where each is a list of - filenames that will need to be put in front of make for either - building (deps) or linking (link_deps). - """ - deps = [] - link_deps = [] - if 'dependencies' in spec: - deps.extend([target_outputs[dep] for dep in spec['dependencies'] - if target_outputs[dep]]) - for dep in spec['dependencies']: - if dep in target_link_deps: - link_deps.append(target_link_deps[dep]) - deps.extend(link_deps) - return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps)) - - - def WriteTargetFlags(self, spec, configs, link_deps): - """Write Makefile code to specify the link flags and library dependencies. - - spec, configs: input from gyp. - link_deps: link dependency list; see ComputeDeps() - """ - # Libraries (i.e. -lfoo) - # These must be included even for static libraries as some of them provide - # implicit include paths through the build system. - libraries = gyp.common.uniquer(spec.get('libraries', [])) - static_libs, dynamic_libs, ldflags_libs = self.FilterLibraries(libraries) - - if self.type != 'static_library': - for configname, config in sorted(configs.iteritems()): - ldflags = list(config.get('ldflags', [])) - self.WriteLn('') - self.WriteList(ldflags, 'LOCAL_LDFLAGS_%s' % configname) - self.WriteList(ldflags_libs, 'LOCAL_GYP_LIBS') - self.WriteLn('LOCAL_LDFLAGS := $(LOCAL_LDFLAGS_$(GYP_CONFIGURATION)) ' - '$(LOCAL_GYP_LIBS)') - - # Link dependencies (i.e. other gyp targets this target depends on) - # These need not be included for static libraries as within the gyp build - # we do not use the implicit include path mechanism. - if self.type != 'static_library': - static_link_deps = [x[1] for x in link_deps if x[0] == 'static'] - shared_link_deps = [x[1] for x in link_deps if x[0] == 'shared'] - else: - static_link_deps = [] - shared_link_deps = [] - - # Only write the lists if they are non-empty. - if static_libs or static_link_deps: - self.WriteLn('') - self.WriteList(static_libs + static_link_deps, - 'LOCAL_STATIC_LIBRARIES') - self.WriteLn('# Enable grouping to fix circular references') - self.WriteLn('LOCAL_GROUP_STATIC_LIBRARIES := true') - if dynamic_libs or shared_link_deps: - self.WriteLn('') - self.WriteList(dynamic_libs + shared_link_deps, - 'LOCAL_SHARED_LIBRARIES') - - - def WriteTarget(self, spec, configs, deps, link_deps, part_of_all, - write_alias_target): - """Write Makefile code to produce the final target of the gyp spec. - - spec, configs: input from gyp. - deps, link_deps: dependency lists; see ComputeDeps() - part_of_all: flag indicating this target is part of 'all' - write_alias_target: flag indicating whether to create short aliases for this - target - """ - self.WriteLn('### Rules for final target.') - - if self.type != 'none': - self.WriteTargetFlags(spec, configs, link_deps) - - settings = spec.get('aosp_build_settings', {}) - if settings: - self.WriteLn('### Set directly by aosp_build_settings.') - for k, v in settings.iteritems(): - if isinstance(v, list): - self.WriteList(v, k) - else: - self.WriteLn('%s := %s' % (k, make.QuoteIfNecessary(v))) - self.WriteLn('') - - # Add to the set of targets which represent the gyp 'all' target. We use the - # name 'gyp_all_modules' as the Android build system doesn't allow the use - # of the Make target 'all' and because 'all_modules' is the equivalent of - # the Make target 'all' on Android. - if part_of_all and write_alias_target: - self.WriteLn('# Add target alias to "gyp_all_modules" target.') - self.WriteLn('.PHONY: gyp_all_modules') - self.WriteLn('gyp_all_modules: %s' % self.android_module) - self.WriteLn('') - - # Add an alias from the gyp target name to the Android module name. This - # simplifies manual builds of the target, and is required by the test - # framework. - if self.target != self.android_module and write_alias_target: - self.WriteLn('# Alias gyp target name.') - self.WriteLn('.PHONY: %s' % self.target) - self.WriteLn('%s: %s' % (self.target, self.android_module)) - self.WriteLn('') - - # Add the command to trigger build of the target type depending - # on the toolset. Ex: BUILD_STATIC_LIBRARY vs. BUILD_HOST_STATIC_LIBRARY - # NOTE: This has to come last! - modifier = '' - if self.toolset == 'host': - modifier = 'HOST_' - if self.type == 'static_library': - self.WriteLn('include $(BUILD_%sSTATIC_LIBRARY)' % modifier) - elif self.type == 'shared_library': - self.WriteLn('LOCAL_PRELINK_MODULE := false') - self.WriteLn('include $(BUILD_%sSHARED_LIBRARY)' % modifier) - elif self.type == 'executable': - self.WriteLn('LOCAL_CXX_STL := libc++_static') - # Executables are for build and test purposes only, so they're installed - # to a directory that doesn't get included in the system image. - self.WriteLn('LOCAL_MODULE_PATH := $(gyp_shared_intermediate_dir)') - self.WriteLn('include $(BUILD_%sEXECUTABLE)' % modifier) - else: - self.WriteLn('LOCAL_MODULE_PATH := $(PRODUCT_OUT)/gyp_stamp') - self.WriteLn('LOCAL_UNINSTALLABLE_MODULE := true') - if self.toolset == 'target': - self.WriteLn('LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_VAR_PREFIX)') - else: - self.WriteLn('LOCAL_2ND_ARCH_VAR_PREFIX := $(GYP_HOST_VAR_PREFIX)') - self.WriteLn() - self.WriteLn('include $(BUILD_SYSTEM)/base_rules.mk') - self.WriteLn() - self.WriteLn('$(LOCAL_BUILT_MODULE): $(LOCAL_ADDITIONAL_DEPENDENCIES)') - self.WriteLn('\t$(hide) echo "Gyp timestamp: $@"') - self.WriteLn('\t$(hide) mkdir -p $(dir $@)') - self.WriteLn('\t$(hide) touch $@') - self.WriteLn() - self.WriteLn('LOCAL_2ND_ARCH_VAR_PREFIX :=') - - - def WriteList(self, value_list, variable=None, prefix='', - quoter=make.QuoteIfNecessary, local_pathify=False): - """Write a variable definition that is a list of values. - - E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out - foo = blaha blahb - but in a pretty-printed style. - """ - values = '' - if value_list: - value_list = [quoter(prefix + l) for l in value_list] - if local_pathify: - value_list = [self.LocalPathify(l) for l in value_list] - values = ' \\\n\t' + ' \\\n\t'.join(value_list) - self.fp.write('%s :=%s\n\n' % (variable, values)) - - - def WriteLn(self, text=''): - self.fp.write(text + '\n') - - - def LocalPathify(self, path): - """Convert a subdirectory-relative path into a normalized path which starts - with the make variable $(LOCAL_PATH) (i.e. the top of the project tree). - Absolute paths, or paths that contain variables, are just normalized.""" - if '$(' in path or os.path.isabs(path): - # path is not a file in the project tree in this case, but calling - # normpath is still important for trimming trailing slashes. - return os.path.normpath(path) - local_path = os.path.join('$(LOCAL_PATH)', self.path, path) - local_path = os.path.normpath(local_path) - # Check that normalizing the path didn't ../ itself out of $(LOCAL_PATH) - # - i.e. that the resulting path is still inside the project tree. The - # path may legitimately have ended up containing just $(LOCAL_PATH), though, - # so we don't look for a slash. - assert local_path.startswith('$(LOCAL_PATH)'), ( - 'Path %s attempts to escape from gyp path %s !)' % (path, self.path)) - return local_path - - - def ExpandInputRoot(self, template, expansion, dirname): - if '%(INPUT_ROOT)s' not in template and '%(INPUT_DIRNAME)s' not in template: - return template - path = template % { - 'INPUT_ROOT': expansion, - 'INPUT_DIRNAME': dirname, - } - return os.path.normpath(path) - - -def PerformBuild(data, configurations, params): - # The android backend only supports the default configuration. - options = params['options'] - makefile = os.path.abspath(os.path.join(options.toplevel_dir, - 'GypAndroid.mk')) - env = dict(os.environ) - env['ONE_SHOT_MAKEFILE'] = makefile - arguments = ['make', '-C', os.environ['ANDROID_BUILD_TOP'], 'gyp_all_modules'] - print 'Building: %s' % arguments - subprocess.check_call(arguments, env=env) - - -def GenerateOutput(target_list, target_dicts, data, params): - options = params['options'] - generator_flags = params.get('generator_flags', {}) - builddir_name = generator_flags.get('output_dir', 'out') - limit_to_target_all = generator_flags.get('limit_to_target_all', False) - write_alias_targets = generator_flags.get('write_alias_targets', True) - sdk_version = generator_flags.get('aosp_sdk_version', 0) - android_top_dir = os.environ.get('ANDROID_BUILD_TOP') - assert android_top_dir, '$ANDROID_BUILD_TOP not set; you need to run lunch.' - - def CalculateMakefilePath(build_file, base_name): - """Determine where to write a Makefile for a given gyp file.""" - # Paths in gyp files are relative to the .gyp file, but we want - # paths relative to the source root for the master makefile. Grab - # the path of the .gyp file as the base to relativize against. - # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp". - base_path = gyp.common.RelativePath(os.path.dirname(build_file), - options.depth) - # We write the file in the base_path directory. - output_file = os.path.join(options.depth, base_path, base_name) - assert not options.generator_output, ( - 'The Android backend does not support options.generator_output.') - base_path = gyp.common.RelativePath(os.path.dirname(build_file), - options.toplevel_dir) - return base_path, output_file - - # TODO: search for the first non-'Default' target. This can go - # away when we add verification that all targets have the - # necessary configurations. - default_configuration = None - toolsets = set([target_dicts[target]['toolset'] for target in target_list]) - for target in target_list: - spec = target_dicts[target] - if spec['default_configuration'] != 'Default': - default_configuration = spec['default_configuration'] - break - if not default_configuration: - default_configuration = 'Default' - - srcdir = '.' - makefile_name = 'GypAndroid' + options.suffix + '.mk' - makefile_path = os.path.join(options.toplevel_dir, makefile_name) - assert not options.generator_output, ( - 'The Android backend does not support options.generator_output.') - gyp.common.EnsureDirExists(makefile_path) - root_makefile = open(makefile_path, 'w') - - root_makefile.write(header) - - # We set LOCAL_PATH just once, here, to the top of the project tree. This - # allows all the other paths we use to be relative to the Android.mk file, - # as the Android build system expects. - root_makefile.write('\nLOCAL_PATH := $(call my-dir)\n') - - # Find the list of targets that derive from the gyp file(s) being built. - needed_targets = set() - for build_file in params['build_files']: - for target in gyp.common.AllTargets(target_list, target_dicts, build_file): - needed_targets.add(target) - - build_files = set() - include_list = set() - android_modules = {} - for qualified_target in target_list: - build_file, target, toolset = gyp.common.ParseQualifiedTarget( - qualified_target) - relative_build_file = gyp.common.RelativePath(build_file, - options.toplevel_dir) - build_files.add(relative_build_file) - included_files = data[build_file]['included_files'] - for included_file in included_files: - # The included_files entries are relative to the dir of the build file - # that included them, so we have to undo that and then make them relative - # to the root dir. - relative_include_file = gyp.common.RelativePath( - gyp.common.UnrelativePath(included_file, build_file), - options.toplevel_dir) - abs_include_file = os.path.abspath(relative_include_file) - # If the include file is from the ~/.gyp dir, we should use absolute path - # so that relocating the src dir doesn't break the path. - if (params['home_dot_gyp'] and - abs_include_file.startswith(params['home_dot_gyp'])): - build_files.add(abs_include_file) - else: - build_files.add(relative_include_file) - - base_path, output_file = CalculateMakefilePath(build_file, - target + '.' + toolset + options.suffix + '.mk') - - spec = target_dicts[qualified_target] - configs = spec['configurations'] - - part_of_all = qualified_target in needed_targets - if limit_to_target_all and not part_of_all: - continue - - relative_target = gyp.common.QualifiedTarget(relative_build_file, target, - toolset) - writer = AndroidMkWriter(android_top_dir) - android_module = writer.Write(qualified_target, relative_target, base_path, - output_file, spec, configs, - part_of_all=part_of_all, - write_alias_target=write_alias_targets, - sdk_version=sdk_version) - if android_module in android_modules: - print ('ERROR: Android module names must be unique. The following ' - 'targets both generate Android module name %s.\n %s\n %s' % - (android_module, android_modules[android_module], - qualified_target)) - return - android_modules[android_module] = qualified_target - - # Our root_makefile lives at the source root. Compute the relative path - # from there to the output_file for including. - mkfile_rel_path = gyp.common.RelativePath(output_file, - os.path.dirname(makefile_path)) - include_list.add(mkfile_rel_path) - - root_makefile.write('GYP_CONFIGURATION ?= %s\n' % default_configuration) - root_makefile.write('GYP_VAR_PREFIX ?=\n') - root_makefile.write('GYP_HOST_VAR_PREFIX ?=\n') - root_makefile.write('GYP_HOST_MULTILIB ?= first\n') - - # Write out the sorted list of includes. - root_makefile.write('\n') - for include_file in sorted(include_list): - root_makefile.write('include $(LOCAL_PATH)/' + include_file + '\n') - root_makefile.write('\n') - - if write_alias_targets: - root_makefile.write(ALL_MODULES_FOOTER) - - root_makefile.close() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py deleted file mode 100644 index 17f5e6396c630..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/cmake.py +++ /dev/null @@ -1,1221 +0,0 @@ -# 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_CURRENT_LIST_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_CURRENT_LIST_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, variable, property_name, values, sep): - """Given a set of source files, sets the given property on them.""" - output.write('set_source_files_properties(') - WriteVariable(output, variable) - output.write(' PROPERTIES ') - output.write(property_name) - output.write(' "') - for value in values: - output.write(CMakeStringEscape(value)) - output.write(sep) - output.write('")\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(object): - 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: [(, )] to append with generated source files. - extra_deps: [] 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_CURRENT_LIST_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: [(, )] to append with generated source files. - extra_deps: [] 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_CURRENT_LIST_DIR is where the CMakeLists.txt lives. - # The cwd is the current build directory. - output.write(' WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_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: [] 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(object): - 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(NormjoinPathForceCMakeSource(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_CURRENT_LIST_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', '') - target_type = spec.get('type', '') - target_toolset = spec.get('toolset') - - 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 - - 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. - # A full separation is done here because of flag handing (see below). - s_sources = [] - c_sources = [] - cxx_sources = [] - linkable_sources = [] - other_sources = [] - for src in srcs: - _, ext = os.path.splitext(src) - src_type = COMPILABLE_EXTENSIONS.get(ext, None) - src_norm_path = NormjoinPath(path_from_cmakelists_to_gyp, src); - - if src_type == 's': - s_sources.append(src_norm_path) - elif src_type == 'cc': - c_sources.append(src_norm_path) - elif src_type == 'cxx': - cxx_sources.append(src_norm_path) - elif Linkable(ext): - linkable_sources.append(src_norm_path) - else: - other_sources.append(src_norm_path) - - 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(src) - elif src_type == 'cc': - c_sources.append(src) - elif src_type == 'cxx': - cxx_sources.append(src) - elif Linkable(ext): - linkable_sources.append(src) - else: - other_sources.append(src) - - s_sources_name = None - if s_sources: - s_sources_name = cmake_target_name + '__asm_srcs' - SetVariableList(output, s_sources_name, s_sources) - - c_sources_name = None - if c_sources: - c_sources_name = cmake_target_name + '__c_srcs' - SetVariableList(output, c_sources_name, c_sources) - - cxx_sources_name = None - if cxx_sources: - cxx_sources_name = cmake_target_name + '__cxx_srcs' - SetVariableList(output, cxx_sources_name, cxx_sources) - - linkable_sources_name = None - if linkable_sources: - linkable_sources_name = cmake_target_name + '__linkable_srcs' - SetVariableList(output, linkable_sources_name, linkable_sources) - - other_sources_name = None - if other_sources: - other_sources_name = cmake_target_name + '__other_srcs' - SetVariableList(output, other_sources_name, other_sources) - - # CMake gets upset when executable targets provide no sources. - # http://www.cmake.org/pipermail/cmake/2010-July/038461.html - dummy_sources_name = None - has_sources = (s_sources_name or - c_sources_name or - cxx_sources_name or - linkable_sources_name or - other_sources_name) - if target_type == 'executable' and not has_sources: - dummy_sources_name = cmake_target_name + '__dummy_srcs' - SetVariable(output, dummy_sources_name, - "${obj}.${TOOLSET}/${TARGET}/genc/dummy.c") - output.write('if(NOT EXISTS "') - WriteVariable(output, dummy_sources_name) - output.write('")\n') - output.write(' file(WRITE "') - WriteVariable(output, dummy_sources_name) - output.write('" "")\n') - output.write("endif()\n") - - - # 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 s_sources_name: - WriteVariable(output, s_sources_name, ' ') - if c_sources_name: - WriteVariable(output, c_sources_name, ' ') - if cxx_sources_name: - WriteVariable(output, cxx_sources_name, ' ') - if linkable_sources_name: - WriteVariable(output, linkable_sources_name, ' ') - if other_sources_name: - WriteVariable(output, other_sources_name, ' ') - if dummy_sources_name: - WriteVariable(output, dummy_sources_name, ' ') - - output.write(')\n') - - # 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) - - # Output name and location. - if target_type != 'none': - # Link as 'C' if there are no other files - if not c_sources and not cxx_sources: - SetTargetProperty(output, cmake_target_name, 'LINKER_LANGUAGE', ['C']) - - # Mark uncompiled sources as uncompiled. - if other_sources_name: - output.write('set_source_files_properties(') - WriteVariable(output, other_sources_name, '') - output.write(' PROPERTIES HEADER_FILE_ONLY "TRUE")\n') - - # Mark object sources as linkable. - if linkable_sources_name: - output.write('set_source_files_properties(') - WriteVariable(output, other_sources_name, '') - output.write(' PROPERTIES EXTERNAL_OBJECT "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 == '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'], '') - - # 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... - cflags = config.get('cflags', []) - cflags_c = config.get('cflags_c', []) - cflags_cxx = config.get('cflags_cc', []) - if (not cflags_c or not c_sources) and (not cflags_cxx or not cxx_sources): - SetTargetProperty(output, cmake_target_name, 'COMPILE_FLAGS', cflags, ' ') - - elif 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: - # TODO: This is broken, one cannot generally set properties on files, - # as other targets may require different properties on the same files. - if s_sources and cflags: - SetFilesProperty(output, s_sources_name, 'COMPILE_FLAGS', cflags, ' ') - - if c_sources and (cflags or cflags_c): - flags = [] - flags.extend(cflags) - flags.extend(cflags_c) - SetFilesProperty(output, c_sources_name, 'COMPILE_FLAGS', flags, ' ') - - if cxx_sources and (cflags or cflags_cxx): - flags = [] - flags.extend(cflags) - flags.extend(cflags_cxx) - SetFilesProperty(output, cxx_sources_name, 'COMPILE_FLAGS', flags, ' ') - - # 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') - - gyp_file, project_target, _ = gyp.common.ParseQualifiedTarget(target_list[-1]) - output.write('project(') - output.write(project_target) - output.write(')\n') - - SetVariable(output, 'configuration', config_to_use) - - ar = None - cc = None - cxx = None - - make_global_settings = data[gyp_file].get('make_global_settings', []) - build_to_top = gyp.common.InvertRelativePath(build_dir, - options.toplevel_dir) - for key, value in make_global_settings: - if key == 'AR': - ar = os.path.join(build_to_top, value) - if key == 'CC': - cc = os.path.join(build_to_top, value) - if key == 'CXX': - cxx = os.path.join(build_to_top, value) - - ar = gyp.common.GetEnvironFallback(['AR_target', 'AR'], ar) - cc = gyp.common.GetEnvironFallback(['CC_target', 'CC'], cc) - cxx = gyp.common.GetEnvironFallback(['CXX_target', 'CXX'], cxx) - - if ar: - SetVariable(output, 'CMAKE_AR', ar) - if cc: - SetVariable(output, 'CMAKE_C_COMPILER', cc) - if cxx: - SetVariable(output, 'CMAKE_CXX_COMPILER', cxx) - - # 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') - - if cc: - SetVariable(output, 'CMAKE_ASM_COMPILER', cc) - - SetVariable(output, 'builddir', '${CMAKE_CURRENT_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') - - # Force ninja to use rsp files. Otherwise link and ar lines can get too long, - # resulting in 'Argument list too long' errors. - output.write('set(CMAKE_NINJA_FORCE_RESPONSE_FILE 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/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py deleted file mode 100644 index 160eafe2efeca..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/dump_dependency_json.py +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright (c) 2012 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. - -import collections -import os -import gyp -import gyp.common -import gyp.msvs_emulation -import json -import sys - -generator_supports_multiple_toolsets = True - -generator_wants_static_library_dependencies_adjusted = False - -generator_filelist_paths = { -} - -generator_default_variables = { -} -for dirname in ['INTERMEDIATE_DIR', 'SHARED_INTERMEDIATE_DIR', 'PRODUCT_DIR', - 'LIB_DIR', 'SHARED_LIB_DIR']: - # Some gyp steps fail if these are empty(!). - generator_default_variables[dirname] = 'dir' -for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', - 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', - 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX', - 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX', - 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX', - 'CONFIGURATION_NAME']: - generator_default_variables[unused] = '' - - -def CalculateVariables(default_variables, params): - generator_flags = params.get('generator_flags', {}) - for key, val in generator_flags.items(): - default_variables.setdefault(key, val) - default_variables.setdefault('OS', gyp.common.GetFlavor(params)) - - flavor = gyp.common.GetFlavor(params) - if flavor =='win': - # Copy additional generator configuration data from VS, which is shared - # by the Windows Ninja generator. - import gyp.generator.msvs as msvs_generator - generator_additional_non_configuration_keys = getattr(msvs_generator, - 'generator_additional_non_configuration_keys', []) - generator_additional_path_sections = getattr(msvs_generator, - 'generator_additional_path_sections', []) - - gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) - - -def CalculateGeneratorInputInfo(params): - """Calculate the generator specific info that gets fed to input (called by - gyp).""" - generator_flags = params.get('generator_flags', {}) - if generator_flags.get('adjust_static_libraries', False): - global generator_wants_static_library_dependencies_adjusted - generator_wants_static_library_dependencies_adjusted = True - - toplevel = params['options'].toplevel_dir - generator_dir = os.path.relpath(params['options'].generator_output or '.') - # output_dir: relative path from generator_dir to the build directory. - output_dir = generator_flags.get('output_dir', 'out') - qualified_out_dir = os.path.normpath(os.path.join( - toplevel, generator_dir, output_dir, 'gypfiles')) - global generator_filelist_paths - generator_filelist_paths = { - 'toplevel': toplevel, - 'qualified_out_dir': qualified_out_dir, - } - -def GenerateOutput(target_list, target_dicts, data, params): - # Map of target -> list of targets it depends on. - edges = {} - - # Queue of targets to visit. - targets_to_visit = target_list[:] - - while len(targets_to_visit) > 0: - target = targets_to_visit.pop() - if target in edges: - continue - edges[target] = [] - - for dep in target_dicts[target].get('dependencies', []): - edges[target].append(dep) - targets_to_visit.append(dep) - - try: - filepath = params['generator_flags']['output_dir'] - except KeyError: - filepath = '.' - filename = os.path.join(filepath, 'dump.json') - f = open(filename, 'w') - json.dump(edges, f) - f.close() - print 'Wrote json to %s.' % filename diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py deleted file mode 100644 index 3544347b3bacd..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/eclipse.py +++ /dev/null @@ -1,425 +0,0 @@ -# Copyright (c) 2012 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. - -"""GYP backend that generates Eclipse CDT settings files. - -This backend DOES NOT generate Eclipse CDT projects. Instead, it generates XML -files that can be imported into an Eclipse CDT project. The XML file contains a -list of include paths and symbols (i.e. defines). - -Because a full .cproject definition is not created by this generator, it's not -possible to properly define the include dirs and symbols for each file -individually. Instead, one set of includes/symbols is generated for the entire -project. This works fairly well (and is a vast improvement in general), but may -still result in a few indexer issues here and there. - -This generator has no automated tests, so expect it to be broken. -""" - -from xml.sax.saxutils import escape -import os.path -import subprocess -import gyp -import gyp.common -import gyp.msvs_emulation -import shlex -import xml.etree.cElementTree as ET - -generator_wants_static_library_dependencies_adjusted = False - -generator_default_variables = { -} - -for dirname in ['INTERMEDIATE_DIR', 'PRODUCT_DIR', 'LIB_DIR', 'SHARED_LIB_DIR']: - # Some gyp steps fail if these are empty(!), so we convert them to variables - generator_default_variables[dirname] = '$' + dirname - -for unused in ['RULE_INPUT_PATH', 'RULE_INPUT_ROOT', 'RULE_INPUT_NAME', - 'RULE_INPUT_DIRNAME', 'RULE_INPUT_EXT', - 'EXECUTABLE_PREFIX', 'EXECUTABLE_SUFFIX', - 'STATIC_LIB_PREFIX', 'STATIC_LIB_SUFFIX', - 'SHARED_LIB_PREFIX', 'SHARED_LIB_SUFFIX', - 'CONFIGURATION_NAME']: - generator_default_variables[unused] = '' - -# Include dirs will occasionally use the SHARED_INTERMEDIATE_DIR variable as -# part of the path when dealing with generated headers. This value will be -# replaced dynamically for each configuration. -generator_default_variables['SHARED_INTERMEDIATE_DIR'] = \ - '$SHARED_INTERMEDIATE_DIR' - - -def CalculateVariables(default_variables, params): - generator_flags = params.get('generator_flags', {}) - for key, val in generator_flags.items(): - default_variables.setdefault(key, val) - flavor = gyp.common.GetFlavor(params) - default_variables.setdefault('OS', flavor) - if flavor == 'win': - # Copy additional generator configuration data from VS, which is shared - # by the Eclipse generator. - import gyp.generator.msvs as msvs_generator - generator_additional_non_configuration_keys = getattr(msvs_generator, - 'generator_additional_non_configuration_keys', []) - generator_additional_path_sections = getattr(msvs_generator, - 'generator_additional_path_sections', []) - - gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) - - -def CalculateGeneratorInputInfo(params): - """Calculate the generator specific info that gets fed to input (called by - gyp).""" - generator_flags = params.get('generator_flags', {}) - if generator_flags.get('adjust_static_libraries', False): - global generator_wants_static_library_dependencies_adjusted - generator_wants_static_library_dependencies_adjusted = True - - -def GetAllIncludeDirectories(target_list, target_dicts, - shared_intermediate_dirs, config_name, params, - compiler_path): - """Calculate the set of include directories to be used. - - Returns: - A list including all the include_dir's specified for every target followed - by any include directories that were added as cflag compiler options. - """ - - gyp_includes_set = set() - compiler_includes_list = [] - - # Find compiler's default include dirs. - if compiler_path: - command = shlex.split(compiler_path) - command.extend(['-E', '-xc++', '-v', '-']) - proc = subprocess.Popen(args=command, stdin=subprocess.PIPE, - stdout=subprocess.PIPE, stderr=subprocess.PIPE) - output = proc.communicate()[1] - # Extract the list of include dirs from the output, which has this format: - # ... - # #include "..." search starts here: - # #include <...> search starts here: - # /usr/include/c++/4.6 - # /usr/local/include - # End of search list. - # ... - in_include_list = False - for line in output.splitlines(): - if line.startswith('#include'): - in_include_list = True - continue - if line.startswith('End of search list.'): - break - if in_include_list: - include_dir = line.strip() - if include_dir not in compiler_includes_list: - compiler_includes_list.append(include_dir) - - flavor = gyp.common.GetFlavor(params) - if flavor == 'win': - generator_flags = params.get('generator_flags', {}) - for target_name in target_list: - target = target_dicts[target_name] - if config_name in target['configurations']: - config = target['configurations'][config_name] - - # Look for any include dirs that were explicitly added via cflags. This - # may be done in gyp files to force certain includes to come at the end. - # TODO(jgreenwald): Change the gyp files to not abuse cflags for this, and - # remove this. - if flavor == 'win': - msvs_settings = gyp.msvs_emulation.MsvsSettings(target, generator_flags) - cflags = msvs_settings.GetCflags(config_name) - else: - cflags = config['cflags'] - for cflag in cflags: - if cflag.startswith('-I'): - include_dir = cflag[2:] - if include_dir not in compiler_includes_list: - compiler_includes_list.append(include_dir) - - # Find standard gyp include dirs. - if config.has_key('include_dirs'): - include_dirs = config['include_dirs'] - for shared_intermediate_dir in shared_intermediate_dirs: - for include_dir in include_dirs: - include_dir = include_dir.replace('$SHARED_INTERMEDIATE_DIR', - shared_intermediate_dir) - if not os.path.isabs(include_dir): - base_dir = os.path.dirname(target_name) - - include_dir = base_dir + '/' + include_dir - include_dir = os.path.abspath(include_dir) - - gyp_includes_set.add(include_dir) - - # Generate a list that has all the include dirs. - all_includes_list = list(gyp_includes_set) - all_includes_list.sort() - for compiler_include in compiler_includes_list: - if not compiler_include in gyp_includes_set: - all_includes_list.append(compiler_include) - - # All done. - return all_includes_list - - -def GetCompilerPath(target_list, data, options): - """Determine a command that can be used to invoke the compiler. - - Returns: - If this is a gyp project that has explicit make settings, try to determine - the compiler from that. Otherwise, see if a compiler was specified via the - CC_target environment variable. - """ - # First, see if the compiler is configured in make's settings. - build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) - make_global_settings_dict = data[build_file].get('make_global_settings', {}) - for key, value in make_global_settings_dict: - if key in ['CC', 'CXX']: - return os.path.join(options.toplevel_dir, value) - - # Check to see if the compiler was specified as an environment variable. - for key in ['CC_target', 'CC', 'CXX']: - compiler = os.environ.get(key) - if compiler: - return compiler - - return 'gcc' - - -def GetAllDefines(target_list, target_dicts, data, config_name, params, - compiler_path): - """Calculate the defines for a project. - - Returns: - A dict that includes explict defines declared in gyp files along with all of - the default defines that the compiler uses. - """ - - # Get defines declared in the gyp files. - all_defines = {} - flavor = gyp.common.GetFlavor(params) - if flavor == 'win': - generator_flags = params.get('generator_flags', {}) - for target_name in target_list: - target = target_dicts[target_name] - - if flavor == 'win': - msvs_settings = gyp.msvs_emulation.MsvsSettings(target, generator_flags) - extra_defines = msvs_settings.GetComputedDefines(config_name) - else: - extra_defines = [] - if config_name in target['configurations']: - config = target['configurations'][config_name] - target_defines = config['defines'] - else: - target_defines = [] - for define in target_defines + extra_defines: - split_define = define.split('=', 1) - if len(split_define) == 1: - split_define.append('1') - if split_define[0].strip() in all_defines: - # Already defined - continue - all_defines[split_define[0].strip()] = split_define[1].strip() - # Get default compiler defines (if possible). - if flavor == 'win': - return all_defines # Default defines already processed in the loop above. - if compiler_path: - command = shlex.split(compiler_path) - command.extend(['-E', '-dM', '-']) - cpp_proc = subprocess.Popen(args=command, cwd='.', - stdin=subprocess.PIPE, stdout=subprocess.PIPE) - cpp_output = cpp_proc.communicate()[0] - cpp_lines = cpp_output.split('\n') - for cpp_line in cpp_lines: - if not cpp_line.strip(): - continue - cpp_line_parts = cpp_line.split(' ', 2) - key = cpp_line_parts[1] - if len(cpp_line_parts) >= 3: - val = cpp_line_parts[2] - else: - val = '1' - all_defines[key] = val - - return all_defines - - -def WriteIncludePaths(out, eclipse_langs, include_dirs): - """Write the includes section of a CDT settings export file.""" - - out.write('
    \n') - out.write(' \n') - for lang in eclipse_langs: - out.write(' \n' % lang) - for include_dir in include_dirs: - out.write(' %s\n' % - include_dir) - out.write(' \n') - out.write('
    \n') - - -def WriteMacros(out, eclipse_langs, defines): - """Write the macros section of a CDT settings export file.""" - - out.write('
    \n') - out.write(' \n') - for lang in eclipse_langs: - out.write(' \n' % lang) - for key in sorted(defines.iterkeys()): - out.write(' %s%s\n' % - (escape(key), escape(defines[key]))) - out.write(' \n') - out.write('
    \n') - - -def GenerateOutputForConfig(target_list, target_dicts, data, params, - config_name): - options = params['options'] - generator_flags = params.get('generator_flags', {}) - - # build_dir: relative path from source root to our output files. - # e.g. "out/Debug" - build_dir = os.path.join(generator_flags.get('output_dir', 'out'), - config_name) - - toplevel_build = os.path.join(options.toplevel_dir, build_dir) - # Ninja uses out/Debug/gen while make uses out/Debug/obj/gen as the - # SHARED_INTERMEDIATE_DIR. Include both possible locations. - shared_intermediate_dirs = [os.path.join(toplevel_build, 'obj', 'gen'), - os.path.join(toplevel_build, 'gen')] - - GenerateCdtSettingsFile(target_list, - target_dicts, - data, - params, - config_name, - os.path.join(toplevel_build, - 'eclipse-cdt-settings.xml'), - options, - shared_intermediate_dirs) - GenerateClasspathFile(target_list, - target_dicts, - options.toplevel_dir, - toplevel_build, - os.path.join(toplevel_build, - 'eclipse-classpath.xml')) - - -def GenerateCdtSettingsFile(target_list, target_dicts, data, params, - config_name, out_name, options, - shared_intermediate_dirs): - gyp.common.EnsureDirExists(out_name) - with open(out_name, 'w') as out: - out.write('\n') - out.write('\n') - - eclipse_langs = ['C++ Source File', 'C Source File', 'Assembly Source File', - 'GNU C++', 'GNU C', 'Assembly'] - compiler_path = GetCompilerPath(target_list, data, options) - include_dirs = GetAllIncludeDirectories(target_list, target_dicts, - shared_intermediate_dirs, - config_name, params, compiler_path) - WriteIncludePaths(out, eclipse_langs, include_dirs) - defines = GetAllDefines(target_list, target_dicts, data, config_name, - params, compiler_path) - WriteMacros(out, eclipse_langs, defines) - - out.write('\n') - - -def GenerateClasspathFile(target_list, target_dicts, toplevel_dir, - toplevel_build, out_name): - '''Generates a classpath file suitable for symbol navigation and code - completion of Java code (such as in Android projects) by finding all - .java and .jar files used as action inputs.''' - gyp.common.EnsureDirExists(out_name) - result = ET.Element('classpath') - - def AddElements(kind, paths): - # First, we need to normalize the paths so they are all relative to the - # toplevel dir. - rel_paths = set() - for path in paths: - if os.path.isabs(path): - rel_paths.add(os.path.relpath(path, toplevel_dir)) - else: - rel_paths.add(path) - - for path in sorted(rel_paths): - entry_element = ET.SubElement(result, 'classpathentry') - entry_element.set('kind', kind) - entry_element.set('path', path) - - AddElements('lib', GetJavaJars(target_list, target_dicts, toplevel_dir)) - AddElements('src', GetJavaSourceDirs(target_list, target_dicts, toplevel_dir)) - # Include the standard JRE container and a dummy out folder - AddElements('con', ['org.eclipse.jdt.launching.JRE_CONTAINER']) - # Include a dummy out folder so that Eclipse doesn't use the default /bin - # folder in the root of the project. - AddElements('output', [os.path.join(toplevel_build, '.eclipse-java-build')]) - - ET.ElementTree(result).write(out_name) - - -def GetJavaJars(target_list, target_dicts, toplevel_dir): - '''Generates a sequence of all .jars used as inputs.''' - for target_name in target_list: - target = target_dicts[target_name] - for action in target.get('actions', []): - for input_ in action['inputs']: - if os.path.splitext(input_)[1] == '.jar' and not input_.startswith('$'): - if os.path.isabs(input_): - yield input_ - else: - yield os.path.join(os.path.dirname(target_name), input_) - - -def GetJavaSourceDirs(target_list, target_dicts, toplevel_dir): - '''Generates a sequence of all likely java package root directories.''' - for target_name in target_list: - target = target_dicts[target_name] - for action in target.get('actions', []): - for input_ in action['inputs']: - if (os.path.splitext(input_)[1] == '.java' and - not input_.startswith('$')): - dir_ = os.path.dirname(os.path.join(os.path.dirname(target_name), - input_)) - # If there is a parent 'src' or 'java' folder, navigate up to it - - # these are canonical package root names in Chromium. This will - # break if 'src' or 'java' exists in the package structure. This - # could be further improved by inspecting the java file for the - # package name if this proves to be too fragile in practice. - parent_search = dir_ - while os.path.basename(parent_search) not in ['src', 'java']: - parent_search, _ = os.path.split(parent_search) - if not parent_search or parent_search == toplevel_dir: - # Didn't find a known root, just return the original path - yield dir_ - break - else: - yield parent_search - - -def GenerateOutput(target_list, target_dicts, data, params): - """Generate an XML settings file that can be imported into a CDT project.""" - - if params['options'].generator_output: - raise NotImplementedError("--generator_output not implemented for eclipse") - - 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() - for config_name in config_names: - GenerateOutputForConfig(target_list, target_dicts, data, params, - config_name) - diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py deleted file mode 100644 index 3efdb9966a69a..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypd.py +++ /dev/null @@ -1,94 +0,0 @@ -# Copyright (c) 2011 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. - -"""gypd output module - -This module produces gyp input as its output. Output files are given the -.gypd extension to avoid overwriting the .gyp files that they are generated -from. Internal references to .gyp files (such as those found in -"dependencies" sections) are not adjusted to point to .gypd files instead; -unlike other paths, which are relative to the .gyp or .gypd file, such paths -are relative to the directory from which gyp was run to create the .gypd file. - -This generator module is intended to be a sample and a debugging aid, hence -the "d" for "debug" in .gypd. It is useful to inspect the results of the -various merges, expansions, and conditional evaluations performed by gyp -and to see a representation of what would be fed to a generator module. - -It's not advisable to rename .gypd files produced by this module to .gyp, -because they will have all merges, expansions, and evaluations already -performed and the relevant constructs not present in the output; paths to -dependencies may be wrong; and various sections that do not belong in .gyp -files such as such as "included_files" and "*_excluded" will be present. -Output will also be stripped of comments. This is not intended to be a -general-purpose gyp pretty-printer; for that, you probably just want to -run "pprint.pprint(eval(open('source.gyp').read()))", which will still strip -comments but won't do all of the other things done to this module's output. - -The specific formatting of the output generated by this module is subject -to change. -""" - - -import gyp.common -import errno -import os -import pprint - - -# These variables should just be spit back out as variable references. -_generator_identity_variables = [ - 'CONFIGURATION_NAME', - 'EXECUTABLE_PREFIX', - 'EXECUTABLE_SUFFIX', - 'INTERMEDIATE_DIR', - 'LIB_DIR', - 'PRODUCT_DIR', - 'RULE_INPUT_ROOT', - 'RULE_INPUT_DIRNAME', - 'RULE_INPUT_EXT', - 'RULE_INPUT_NAME', - 'RULE_INPUT_PATH', - 'SHARED_INTERMEDIATE_DIR', - 'SHARED_LIB_DIR', - 'SHARED_LIB_PREFIX', - 'SHARED_LIB_SUFFIX', - 'STATIC_LIB_PREFIX', - 'STATIC_LIB_SUFFIX', -] - -# gypd doesn't define a default value for OS like many other generator -# modules. Specify "-D OS=whatever" on the command line to provide a value. -generator_default_variables = { -} - -# gypd supports multiple toolsets -generator_supports_multiple_toolsets = True - -# TODO(mark): This always uses <, which isn't right. The input module should -# notify the generator to tell it which phase it is operating in, and this -# module should use < for the early phase and then switch to > for the late -# phase. Bonus points for carrying @ back into the output too. -for v in _generator_identity_variables: - generator_default_variables[v] = '<(%s)' % v - - -def GenerateOutput(target_list, target_dicts, data, params): - output_files = {} - for qualified_target in target_list: - [input_file, target] = \ - gyp.common.ParseQualifiedTarget(qualified_target)[0:2] - - if input_file[-4:] != '.gyp': - continue - input_file_stem = input_file[:-4] - output_file = input_file_stem + params['options'].suffix + '.gypd' - - if not output_file in output_files: - output_files[output_file] = input_file - - for output_file, input_file in output_files.iteritems(): - output = open(output_file, 'w') - pprint.pprint(data[input_file], output) - output.close() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py deleted file mode 100644 index bd405f43a993d..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/gypsh.py +++ /dev/null @@ -1,56 +0,0 @@ -# Copyright (c) 2011 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. - -"""gypsh output module - -gypsh is a GYP shell. It's not really a generator per se. All it does is -fire up an interactive Python session with a few local variables set to the -variables passed to the generator. Like gypd, it's intended as a debugging -aid, to facilitate the exploration of .gyp structures after being processed -by the input module. - -The expected usage is "gyp -f gypsh -D OS=desired_os". -""" - - -import code -import sys - - -# All of this stuff about generator variables was lovingly ripped from gypd.py. -# That module has a much better description of what's going on and why. -_generator_identity_variables = [ - 'EXECUTABLE_PREFIX', - 'EXECUTABLE_SUFFIX', - 'INTERMEDIATE_DIR', - 'PRODUCT_DIR', - 'RULE_INPUT_ROOT', - 'RULE_INPUT_DIRNAME', - 'RULE_INPUT_EXT', - 'RULE_INPUT_NAME', - 'RULE_INPUT_PATH', - 'SHARED_INTERMEDIATE_DIR', -] - -generator_default_variables = { -} - -for v in _generator_identity_variables: - generator_default_variables[v] = '<(%s)' % v - - -def GenerateOutput(target_list, target_dicts, data, params): - locals = { - 'target_list': target_list, - 'target_dicts': target_dicts, - 'data': data, - } - - # Use a banner that looks like the stock Python one and like what - # code.interact uses by default, but tack on something to indicate what - # locals are available, and identify gypsh. - banner='Python %s on %s\nlocals.keys() = %s\ngypsh' % \ - (sys.version, sys.platform, repr(sorted(locals.keys()))) - - code.interact(banner, local=locals) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py deleted file mode 100644 index fe801b77ce3b9..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/make.py +++ /dev/null @@ -1,2263 +0,0 @@ -# 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. - -# Notes: -# -# This is all roughly based on the Makefile system used by the Linux -# kernel, but is a non-recursive make -- we put the entire dependency -# graph in front of make and let it figure it out. -# -# The code below generates a separate .mk file for each target, but -# all are sourced by the top-level Makefile. This means that all -# variables in .mk-files clobber one another. Be careful to use := -# where appropriate for immediate evaluation, and similarly to watch -# that you're not relying on a variable value to last beween different -# .mk files. -# -# TODOs: -# -# Global settings and utility functions are currently stuffed in the -# toplevel Makefile. It may make sense to generate some .mk files on -# the side to keep the files readable. - -import os -import re -import sys -import subprocess -import gyp -import gyp.common -import gyp.xcode_emulation -from gyp.common import GetEnvironFallback -from gyp.common import GypError - -import hashlib - -generator_default_variables = { - 'EXECUTABLE_PREFIX': '', - 'EXECUTABLE_SUFFIX': '', - 'STATIC_LIB_PREFIX': 'lib', - 'SHARED_LIB_PREFIX': 'lib', - 'STATIC_LIB_SUFFIX': '.a', - 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/$(TARGET)/geni', - 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen', - 'PRODUCT_DIR': '$(builddir)', - 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', # This gets expanded by Python. - 'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s', # This gets expanded by Python. - 'RULE_INPUT_PATH': '$(abspath $<)', - 'RULE_INPUT_EXT': '$(suffix $<)', - 'RULE_INPUT_NAME': '$(notdir $<)', - 'CONFIGURATION_NAME': '$(BUILDTYPE)', -} - -# Make supports multiple toolsets -generator_supports_multiple_toolsets = True - -# Request sorted dependencies in the order from dependents to dependencies. -generator_wants_sorted_dependencies = False - -# Placates pylint. -generator_additional_non_configuration_keys = [] -generator_additional_path_sections = [] -generator_extra_sources_for_rules = [] -generator_filelist_paths = None - - -def CalculateVariables(default_variables, params): - """Calculate additional variables for use in the build (called by gyp).""" - flavor = gyp.common.GetFlavor(params) - if flavor == 'mac': - default_variables.setdefault('OS', 'mac') - default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib') - default_variables.setdefault('SHARED_LIB_DIR', - generator_default_variables['PRODUCT_DIR']) - default_variables.setdefault('LIB_DIR', - generator_default_variables['PRODUCT_DIR']) - - # Copy additional generator configuration data from Xcode, which is shared - # by the Mac Make generator. - import gyp.generator.xcode as xcode_generator - global generator_additional_non_configuration_keys - generator_additional_non_configuration_keys = getattr(xcode_generator, - 'generator_additional_non_configuration_keys', []) - global generator_additional_path_sections - generator_additional_path_sections = getattr(xcode_generator, - 'generator_additional_path_sections', []) - global generator_extra_sources_for_rules - generator_extra_sources_for_rules = getattr(xcode_generator, - 'generator_extra_sources_for_rules', []) - COMPILABLE_EXTENSIONS.update({'.m': 'objc', '.mm' : 'objcxx'}) - else: - operating_system = flavor - if flavor == 'android': - operating_system = 'linux' # Keep this legacy behavior for now. - default_variables.setdefault('OS', operating_system) - if flavor == 'aix': - default_variables.setdefault('SHARED_LIB_SUFFIX', '.a') - else: - default_variables.setdefault('SHARED_LIB_SUFFIX', '.so') - default_variables.setdefault('SHARED_LIB_DIR','$(builddir)/lib.$(TOOLSET)') - default_variables.setdefault('LIB_DIR', '$(obj).$(TOOLSET)') - - -def CalculateGeneratorInputInfo(params): - """Calculate the generator specific info that gets fed to input (called by - gyp).""" - generator_flags = params.get('generator_flags', {}) - android_ndk_version = generator_flags.get('android_ndk_version', None) - # Android NDK requires a strict link order. - if android_ndk_version: - 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')) - - 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: -# wildcard, sort, foreach, shell, wordlist -# wildcard can handle spaces, the rest can't. -# Since I could find no way to make foreach work with spaces in filenames -# correctly, the .d files have spaces replaced with another character. The .d -# file for -# Chromium\ Framework.framework/foo -# is for example -# out/Release/.deps/out/Release/Chromium?Framework.framework/foo -# This is the replacement character. -SPACE_REPLACEMENT = '?' - - -LINK_COMMANDS_LINUX = """\ -quiet_cmd_alink = AR($(TOOLSET)) $@ -cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) - -quiet_cmd_alink_thin = AR($(TOOLSET)) $@ -cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) - -# Due to circular dependencies between libraries :(, we wrap the -# special "figure out circular dependencies" flags around the entire -# input list during linking. -quiet_cmd_link = LINK($(TOOLSET)) $@ -cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) $(LIBS) -Wl,--end-group - -# We support two kinds of shared objects (.so): -# 1) shared_library, which is just bundling together many dependent libraries -# into a link line. -# 2) loadable_module, which is generating a module intended for dlopen(). -# -# They differ only slightly: -# In the former case, we want to package all dependent code into the .so. -# In the latter case, we want to package just the API exposed by the -# outermost module. -# This means shared_library uses --whole-archive, while loadable_module doesn't. -# (Note that --whole-archive is incompatible with the --start-group used in -# normal linking.) - -# Other shared-object link notes: -# - Set SONAME to the library filename so our binaries don't reference -# the local, absolute paths used on the link command-line. -quiet_cmd_solink = SOLINK($(TOOLSET)) $@ -cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) - -quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) -""" - -LINK_COMMANDS_MAC = """\ -quiet_cmd_alink = LIBTOOL-STATIC $@ -cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^) - -quiet_cmd_link = LINK($(TOOLSET)) $@ -cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) - -quiet_cmd_solink = SOLINK($(TOOLSET)) $@ -cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) - -quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module = $(LINK.$(TOOLSET)) -bundle $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) -""" - -LINK_COMMANDS_ANDROID = """\ -quiet_cmd_alink = AR($(TOOLSET)) $@ -cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) - -quiet_cmd_alink_thin = AR($(TOOLSET)) $@ -cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) - -# Due to circular dependencies between libraries :(, we wrap the -# special "figure out circular dependencies" flags around the entire -# input list during linking. -quiet_cmd_link = LINK($(TOOLSET)) $@ -quiet_cmd_link_host = LINK($(TOOLSET)) $@ -cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ -Wl,--start-group $(LD_INPUTS) -Wl,--end-group $(LIBS) -cmd_link_host = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) - -# Other shared-object link notes: -# - Set SONAME to the library filename so our binaries don't reference -# the local, absolute paths used on the link command-line. -quiet_cmd_solink = SOLINK($(TOOLSET)) $@ -cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--whole-archive $(LD_INPUTS) -Wl,--no-whole-archive $(LIBS) - -quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ -Wl,--start-group $(filter-out FORCE_DO_CMD, $^) -Wl,--end-group $(LIBS) -quiet_cmd_solink_module_host = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module_host = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -Wl,-soname=$(@F) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) -""" - - -LINK_COMMANDS_AIX = """\ -quiet_cmd_alink = AR($(TOOLSET)) $@ -cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) -X32_64 crs $@ $(filter %.o,$^) - -quiet_cmd_alink_thin = AR($(TOOLSET)) $@ -cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) -X32_64 crs $@ $(filter %.o,$^) - -quiet_cmd_link = LINK($(TOOLSET)) $@ -cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) - -quiet_cmd_solink = SOLINK($(TOOLSET)) $@ -cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) - -quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) -""" - - -LINK_COMMANDS_OS390 = """\ -quiet_cmd_alink = AR($(TOOLSET)) $@ -cmd_alink = rm -f $@ && $(AR.$(TOOLSET)) crs $@ $(filter %.o,$^) - -quiet_cmd_alink_thin = AR($(TOOLSET)) $@ -cmd_alink_thin = rm -f $@ && $(AR.$(TOOLSET)) crsT $@ $(filter %.o,$^) - -quiet_cmd_link = LINK($(TOOLSET)) $@ -cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) - -quiet_cmd_solink = SOLINK($(TOOLSET)) $@ -cmd_solink = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(LD_INPUTS) $(LIBS) -Wl,DLL - -quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ -cmd_solink_module = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) -Wl,DLL - -""" - - -# Header of toplevel Makefile. -# This should go into the build tree, but it's easier to keep it here for now. -SHARED_HEADER = ("""\ -# We borrow heavily from the kernel build setup, though we are simpler since -# we don't have Kconfig tweaking settings on us. - -# The implicit make rules have it looking for RCS files, among other things. -# We instead explicitly write all the rules we care about. -# It's even quicker (saves ~200ms) to pass -r on the command line. -MAKEFLAGS=-r - -# The source directory tree. -srcdir := %(srcdir)s -abs_srcdir := $(abspath $(srcdir)) - -# The name of the builddir. -builddir_name ?= %(builddir)s - -# The V=1 flag on command line makes us verbosely print command lines. -ifdef V - quiet= -else - quiet=quiet_ -endif - -# Specify BUILDTYPE=Release on the command line for a release build. -BUILDTYPE ?= %(default_configuration)s - -# Directory all our build output goes into. -# Note that this must be two directories beneath src/ for unit tests to pass, -# as they reach into the src/ directory for data with relative paths. -builddir ?= $(builddir_name)/$(BUILDTYPE) -abs_builddir := $(abspath $(builddir)) -depsdir := $(builddir)/.deps - -# Object output directory. -obj := $(builddir)/obj -abs_obj := $(abspath $(obj)) - -# We build up a list of every single one of the targets so we can slurp in the -# generated dependency rule Makefiles in one pass. -all_deps := - -%(make_global_settings)s - -CC.target ?= %(CC.target)s -CFLAGS.target ?= $(CPPFLAGS) $(CFLAGS) -CXX.target ?= %(CXX.target)s -CXXFLAGS.target ?= $(CPPFLAGS) $(CXXFLAGS) -LINK.target ?= %(LINK.target)s -LDFLAGS.target ?= $(LDFLAGS) -AR.target ?= $(AR) - -# C++ apps need to be linked with g++. -LINK ?= $(CXX.target) - -# TODO(evan): move all cross-compilation logic to gyp-time so we don't need -# to replicate this environment fallback in make as well. -CC.host ?= %(CC.host)s -CFLAGS.host ?= $(CPPFLAGS_host) $(CFLAGS_host) -CXX.host ?= %(CXX.host)s -CXXFLAGS.host ?= $(CPPFLAGS_host) $(CXXFLAGS_host) -LINK.host ?= %(LINK.host)s -LDFLAGS.host ?= -AR.host ?= %(AR.host)s - -# Define a dir function that can handle spaces. -# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions -# "leading spaces cannot appear in the text of the first argument as written. -# These characters can be put into the argument value by variable substitution." -empty := -space := $(empty) $(empty) - -# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces -replace_spaces = $(subst $(space),""" + SPACE_REPLACEMENT + """,$1) -unreplace_spaces = $(subst """ + SPACE_REPLACEMENT + """,$(space),$1) -dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1))) - -# Flags to make gcc output dependency info. Note that you need to be -# careful here to use the flags that ccache and distcc can understand. -# We write to a dep file on the side first and then rename at the end -# so we can't end up with a broken dep file. -depfile = $(depsdir)/$(call replace_spaces,$@).d -DEPFLAGS = %(makedep_args)s -MF $(depfile).raw - -# We have to fixup the deps output in a few ways. -# (1) the file output should mention the proper .o file. -# ccache or distcc lose the path to the target, so we convert a rule of -# the form: -# foobar.o: DEP1 DEP2 -# into -# path/to/foobar.o: DEP1 DEP2 -# (2) we want missing files not to cause us to fail to build. -# We want to rewrite -# foobar.o: DEP1 DEP2 \\ -# DEP3 -# to -# DEP1: -# DEP2: -# DEP3: -# so if the files are missing, they're just considered phony rules. -# We have to do some pretty insane escaping to get those backslashes -# and dollar signs past make, the shell, and sed at the same time. -# Doesn't work with spaces, but that's fine: .d files have spaces in -# their names replaced with other characters.""" -r""" -define fixup_dep -# The depfile may not exist if the input file didn't have any #includes. -touch $(depfile).raw -# Fixup path as in (1). -sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile) -# Add extra rules as in (2). -# We remove slashes and replace spaces with new lines; -# remove blank lines; -# delete the first line and append a colon to the remaining lines. -sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ - grep -v '^$$' |\ - sed -e 1d -e 's|$$|:|' \ - >> $(depfile) -rm $(depfile).raw -endef -""" -""" -# Command definitions: -# - cmd_foo is the actual command to run; -# - quiet_cmd_foo is the brief-output summary of the command. - -quiet_cmd_cc = CC($(TOOLSET)) $@ -cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< - -quiet_cmd_cxx = CXX($(TOOLSET)) $@ -cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< -%(extra_commands)s -quiet_cmd_touch = TOUCH $@ -cmd_touch = touch $@ - -quiet_cmd_copy = COPY $@ -# send stderr to /dev/null to ignore messages when linking directories. -cmd_copy = rm -rf "$@" && cp %(copy_archive_args)s "$<" "$@" - -%(link_commands)s -""" - -r""" -# Define an escape_quotes function to escape single quotes. -# This allows us to handle quotes properly as long as we always use -# use single quotes and escape_quotes. -escape_quotes = $(subst ','\'',$(1)) -# This comment is here just to include a ' to unconfuse syntax highlighting. -# Define an escape_vars function to escape '$' variable syntax. -# This allows us to read/write command lines with shell variables (e.g. -# $LD_LIBRARY_PATH), without triggering make substitution. -escape_vars = $(subst $$,$$$$,$(1)) -# Helper that expands to a shell command to echo a string exactly as it is in -# make. This uses printf instead of echo because printf's behaviour with respect -# to escape sequences is more portable than echo's across different shells -# (e.g., dash, bash). -exact_echo = printf '%%s\n' '$(call escape_quotes,$(1))' -""" -""" -# Helper to compare the command we're about to run against the command -# we logged the last time we ran the command. Produces an empty -# string (false) when the commands match. -# Tricky point: Make has no string-equality test function. -# The kernel uses the following, but it seems like it would have false -# positives, where one string reordered its arguments. -# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \\ -# $(filter-out $(cmd_$@), $(cmd_$(1)))) -# We instead substitute each for the empty string into the other, and -# say they're equal if both substitutions produce the empty string. -# .d files contain """ + SPACE_REPLACEMENT + \ - """ instead of spaces, take that into account. -command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\\ - $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) - -# Helper that is non-empty when a prerequisite changes. -# Normally make does this implicitly, but we force rules to always run -# so we can check their command lines. -# $? -- new prerequisites -# $| -- order-only dependencies -prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) - -# Helper that executes all postbuilds until one fails. -define do_postbuilds - @E=0;\\ - for p in $(POSTBUILDS); do\\ - eval $$p;\\ - E=$$?;\\ - if [ $$E -ne 0 ]; then\\ - break;\\ - fi;\\ - done;\\ - if [ $$E -ne 0 ]; then\\ - rm -rf "$@";\\ - exit $$E;\\ - fi -endef - -# do_cmd: run a command via the above cmd_foo names, if necessary. -# Should always run for a given target to handle command-line changes. -# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. -# Third argument, if non-zero, makes it do POSTBUILDS processing. -# Note: We intentionally do NOT call dirx for depfile, since it contains """ + \ - SPACE_REPLACEMENT + """ for -# spaces already and dirx strips the """ + SPACE_REPLACEMENT + \ - """ characters. -define do_cmd -$(if $(or $(command_changed),$(prereq_changed)), - @$(call exact_echo, $($(quiet)cmd_$(1))) - @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" - $(if $(findstring flock,$(word %(flock_index)d,$(cmd_$1))), - @$(cmd_$(1)) - @echo " $(quiet_cmd_$(1)): Finished", - @$(cmd_$(1)) - ) - @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) - @$(if $(2),$(fixup_dep)) - $(if $(and $(3), $(POSTBUILDS)), - $(call do_postbuilds) - ) -) -endef - -# Declare the "%(default_target)s" target first so it is the default, -# even though we don't have the deps yet. -.PHONY: %(default_target)s -%(default_target)s: - -# make looks for ways to re-generate included makefiles, but in our case, we -# don't have a direct way. Explicitly telling make that it has nothing to do -# for them makes it go faster. -%%.d: ; - -# Use FORCE_DO_CMD to force a target to run. Should be coupled with -# do_cmd. -.PHONY: FORCE_DO_CMD -FORCE_DO_CMD: - -""") - -SHARED_HEADER_MAC_COMMANDS = """ -quiet_cmd_objc = CXX($(TOOLSET)) $@ -cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< - -quiet_cmd_objcxx = CXX($(TOOLSET)) $@ -cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< - -# Commands for precompiled header files. -quiet_cmd_pch_c = CXX($(TOOLSET)) $@ -cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< -quiet_cmd_pch_cc = CXX($(TOOLSET)) $@ -cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< -quiet_cmd_pch_m = CXX($(TOOLSET)) $@ -cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< -quiet_cmd_pch_mm = CXX($(TOOLSET)) $@ -cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< - -# gyp-mac-tool is written next to the root Makefile by gyp. -# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd -# already. -quiet_cmd_mac_tool = MACTOOL $(4) $< -cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@" - -quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ -cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4) - -quiet_cmd_infoplist = INFOPLIST $@ -cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@" -""" - - -def WriteRootHeaderSuffixRules(writer): - extensions = sorted(COMPILABLE_EXTENSIONS.keys(), key=str.lower) - - writer.write('# Suffix rules, putting all outputs into $(obj).\n') - for ext in extensions: - writer.write('$(obj).$(TOOLSET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD\n' % ext) - writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext]) - - writer.write('\n# Try building from generated source, too.\n') - for ext in extensions: - writer.write( - '$(obj).$(TOOLSET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD\n' % ext) - writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext]) - writer.write('\n') - for ext in extensions: - writer.write('$(obj).$(TOOLSET)/%%.o: $(obj)/%%%s FORCE_DO_CMD\n' % ext) - writer.write('\t@$(call do_cmd,%s,1)\n' % COMPILABLE_EXTENSIONS[ext]) - writer.write('\n') - - -SHARED_HEADER_SUFFIX_RULES_COMMENT1 = ("""\ -# Suffix rules, putting all outputs into $(obj). -""") - - -SHARED_HEADER_SUFFIX_RULES_COMMENT2 = ("""\ -# Try building from generated source, too. -""") - - -SHARED_FOOTER = """\ -# "all" is a concatenation of the "all" targets from all the included -# sub-makefiles. This is just here to clarify. -all: - -# Add in dependency-tracking rules. $(all_deps) is the list of every single -# target in our tree. Only consider the ones with .d (dependency) info: -d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) -ifneq ($(d_files),) - include $(d_files) -endif -""" - -header = """\ -# This file is generated by gyp; do not edit. - -""" - -# Maps every compilable file extension to the do_cmd that compiles it. -COMPILABLE_EXTENSIONS = { - '.c': 'cc', - '.cc': 'cxx', - '.cpp': 'cxx', - '.cxx': 'cxx', - '.s': 'cc', - '.S': 'cc', -} - -def Compilable(filename): - """Return true if the file is compilable (should be in OBJS).""" - for res in (filename.endswith(e) for e in COMPILABLE_EXTENSIONS): - if res: - return True - return False - - -def Linkable(filename): - """Return true if the file is linkable (should be on the link line).""" - return filename.endswith('.o') - - -def Target(filename): - """Translate a compilable filename to its .o target.""" - return os.path.splitext(filename)[0] + '.o' - - -def EscapeShellArgument(s): - """Quotes an argument so that it will be interpreted literally by a POSIX - shell. Taken from - http://stackoverflow.com/questions/35817/whats-the-best-way-to-escape-ossystem-calls-in-python - """ - return "'" + s.replace("'", "'\\''") + "'" - - -def EscapeMakeVariableExpansion(s): - """Make has its own variable expansion syntax using $. We must escape it for - string to be interpreted literally.""" - return s.replace('$', '$$') - - -def EscapeCppDefine(s): - """Escapes a CPP define so that it will reach the compiler unaltered.""" - s = EscapeShellArgument(s) - s = EscapeMakeVariableExpansion(s) - # '#' characters must be escaped even embedded in a string, else Make will - # treat it as the start of a comment. - return s.replace('#', r'\#') - - -def QuoteIfNecessary(string): - """TODO: Should this ideally be replaced with one or more of the above - functions?""" - if '"' in string: - string = '"' + string.replace('"', '\\"') + '"' - return string - - -def StringToMakefileVariable(string): - """Convert a string to a value that is acceptable as a make variable name.""" - return re.sub('[^a-zA-Z0-9_]', '_', string) - - -srcdir_prefix = '' -def Sourceify(path): - """Convert a path to its source directory form.""" - if '$(' in path: - return path - if os.path.isabs(path): - return path - return srcdir_prefix + path - - -def QuoteSpaces(s, quote=r'\ '): - return s.replace(' ', quote) - -def SourceifyAndQuoteSpaces(path): - """Convert a path to its source directory form and quote spaces.""" - return QuoteSpaces(Sourceify(path)) - -# TODO: Avoid code duplication with _ValidateSourcesForMSVSProject in msvs.py. -def _ValidateSourcesForOSX(spec, all_sources): - """Makes sure if duplicate basenames are not specified in the source list. - - Arguments: - spec: The target dictionary containing the properties of the target. - """ - if spec.get('type', None) != 'static_library': - return - - basenames = {} - for source in all_sources: - name, ext = os.path.splitext(source) - is_compiled_file = ext in [ - '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S'] - if not is_compiled_file: - continue - basename = os.path.basename(name) # Don't include extension. - basenames.setdefault(basename, []).append(source) - - error = '' - for basename, files in basenames.iteritems(): - if len(files) > 1: - error += ' %s: %s\n' % (basename, ' '.join(files)) - - if error: - print('static library %s has several files with the same basename:\n' % - spec['target_name'] + error + 'libtool on OS X will generate' + - ' warnings for them.') - raise GypError('Duplicate basenames in sources section, see list above') - - -# Map from qualified target to path to output. -target_outputs = {} -# Map from qualified target to any linkable output. A subset -# of target_outputs. E.g. when mybinary depends on liba, we want to -# include liba in the linker line; when otherbinary depends on -# mybinary, we just want to build mybinary first. -target_link_deps = {} - - -class MakefileWriter(object): - """MakefileWriter packages up the writing of one target-specific foobar.mk. - - Its only real entry point is Write(), and is mostly used for namespacing. - """ - - def __init__(self, generator_flags, flavor): - self.generator_flags = generator_flags - self.flavor = flavor - - self.suffix_rules_srcdir = {} - self.suffix_rules_objdir1 = {} - self.suffix_rules_objdir2 = {} - - # Generate suffix rules for all compilable extensions. - for ext in COMPILABLE_EXTENSIONS.keys(): - # Suffix rules for source folder. - self.suffix_rules_srcdir.update({ext: ("""\ -$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(srcdir)/%%%s FORCE_DO_CMD - @$(call do_cmd,%s,1) -""" % (ext, COMPILABLE_EXTENSIONS[ext]))}) - - # Suffix rules for generated source files. - self.suffix_rules_objdir1.update({ext: ("""\ -$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj).$(TOOLSET)/%%%s FORCE_DO_CMD - @$(call do_cmd,%s,1) -""" % (ext, COMPILABLE_EXTENSIONS[ext]))}) - self.suffix_rules_objdir2.update({ext: ("""\ -$(obj).$(TOOLSET)/$(TARGET)/%%.o: $(obj)/%%%s FORCE_DO_CMD - @$(call do_cmd,%s,1) -""" % (ext, COMPILABLE_EXTENSIONS[ext]))}) - - - def Write(self, qualified_target, base_path, output_filename, spec, configs, - part_of_all): - """The main entry point: writes a .mk file for a single target. - - Arguments: - qualified_target: target we're generating - base_path: path relative to source root we're building in, used to resolve - target-relative paths - output_filename: output .mk file name to write - spec, configs: gyp info - part_of_all: flag indicating this target is part of 'all' - """ - gyp.common.EnsureDirExists(output_filename) - - self.fp = open(output_filename, 'w') - - self.fp.write(header) - - self.qualified_target = qualified_target - self.path = base_path - self.target = spec['target_name'] - self.type = spec['type'] - self.toolset = spec['toolset'] - - self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec) - if self.flavor == 'mac': - self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec) - else: - self.xcode_settings = None - - deps, link_deps = self.ComputeDeps(spec) - - # Some of the generation below can add extra output, sources, or - # link dependencies. All of the out params of the functions that - # follow use names like extra_foo. - extra_outputs = [] - extra_sources = [] - extra_link_deps = [] - extra_mac_bundle_resources = [] - mac_bundle_deps = [] - - if self.is_mac_bundle: - self.output = self.ComputeMacBundleOutput(spec) - self.output_binary = self.ComputeMacBundleBinaryOutput(spec) - else: - self.output = self.output_binary = self.ComputeOutput(spec) - - self.is_standalone_static_library = bool( - spec.get('standalone_static_library', 0)) - self._INSTALLABLE_TARGETS = ('executable', 'loadable_module', - 'shared_library') - if (self.is_standalone_static_library or - self.type in self._INSTALLABLE_TARGETS): - self.alias = os.path.basename(self.output) - install_path = self._InstallableTargetInstallPath() - else: - self.alias = self.output - install_path = self.output - - self.WriteLn("TOOLSET := " + self.toolset) - self.WriteLn("TARGET := " + self.target) - - # Actions must come first, since they can generate more OBJs for use below. - if 'actions' in spec: - self.WriteActions(spec['actions'], extra_sources, extra_outputs, - extra_mac_bundle_resources, part_of_all) - - # Rules must be early like actions. - if 'rules' in spec: - self.WriteRules(spec['rules'], extra_sources, extra_outputs, - extra_mac_bundle_resources, part_of_all) - - if 'copies' in spec: - self.WriteCopies(spec['copies'], extra_outputs, part_of_all) - - # Bundle resources. - if self.is_mac_bundle: - all_mac_bundle_resources = ( - spec.get('mac_bundle_resources', []) + extra_mac_bundle_resources) - self.WriteMacBundleResources(all_mac_bundle_resources, mac_bundle_deps) - self.WriteMacInfoPlist(mac_bundle_deps) - - # Sources. - all_sources = spec.get('sources', []) + extra_sources - if all_sources: - if self.flavor == 'mac': - # libtool on OS X generates warnings for duplicate basenames in the same - # target. - _ValidateSourcesForOSX(spec, all_sources) - self.WriteSources( - configs, deps, all_sources, extra_outputs, - extra_link_deps, part_of_all, - gyp.xcode_emulation.MacPrefixHeader( - self.xcode_settings, lambda p: Sourceify(self.Absolutify(p)), - self.Pchify)) - sources = filter(Compilable, all_sources) - if sources: - self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT1) - extensions = set([os.path.splitext(s)[1] for s in sources]) - for ext in extensions: - if ext in self.suffix_rules_srcdir: - self.WriteLn(self.suffix_rules_srcdir[ext]) - self.WriteLn(SHARED_HEADER_SUFFIX_RULES_COMMENT2) - for ext in extensions: - if ext in self.suffix_rules_objdir1: - self.WriteLn(self.suffix_rules_objdir1[ext]) - for ext in extensions: - if ext in self.suffix_rules_objdir2: - self.WriteLn(self.suffix_rules_objdir2[ext]) - self.WriteLn('# End of this set of suffix rules') - - # Add dependency from bundle to bundle binary. - if self.is_mac_bundle: - mac_bundle_deps.append(self.output_binary) - - self.WriteTarget(spec, configs, deps, extra_link_deps + link_deps, - mac_bundle_deps, extra_outputs, part_of_all) - - # Update global list of target outputs, used in dependency tracking. - target_outputs[qualified_target] = install_path - - # Update global list of link dependencies. - if self.type in ('static_library', 'shared_library'): - target_link_deps[qualified_target] = self.output_binary - - # Currently any versions have the same effect, but in future the behavior - # could be different. - if self.generator_flags.get('android_ndk_version', None): - self.WriteAndroidNdkModuleRule(self.target, all_sources, link_deps) - - self.fp.close() - - - def WriteSubMake(self, output_filename, makefile_path, targets, build_dir): - """Write a "sub-project" Makefile. - - This is a small, wrapper Makefile that calls the top-level Makefile to build - the targets from a single gyp file (i.e. a sub-project). - - Arguments: - output_filename: sub-project Makefile name to write - makefile_path: path to the top-level Makefile - targets: list of "all" targets for this sub-project - build_dir: build output directory, relative to the sub-project - """ - 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 - # sub-project dir (see test/subdirectory/gyptest-subdir-all.py). - self.WriteLn('export builddir_name ?= %s' % - os.path.join(os.path.dirname(output_filename), build_dir)) - self.WriteLn('.PHONY: all') - self.WriteLn('all:') - if makefile_path: - makefile_path = ' -C ' + makefile_path - self.WriteLn('\t$(MAKE)%s %s' % (makefile_path, ' '.join(targets))) - self.fp.close() - - - def WriteActions(self, actions, extra_sources, extra_outputs, - extra_mac_bundle_resources, part_of_all): - """Write Makefile code for any 'actions' from the gyp input. - - extra_sources: a list that will be filled in with newly generated source - files, if any - extra_outputs: a list that will be filled in with any outputs of these - actions (used to make other pieces dependent on these - actions) - part_of_all: flag indicating this target is part of 'all' - """ - env = self.GetSortedXcodeEnv() - for action in actions: - name = StringToMakefileVariable('%s_%s' % (self.qualified_target, - action['action_name'])) - self.WriteLn('### Rules for action "%s":' % action['action_name']) - inputs = action['inputs'] - outputs = action['outputs'] - - # Build up a list of outputs. - # Collect the output dirs we'll need. - dirs = set() - for out in outputs: - dir = os.path.split(out)[0] - if dir: - dirs.add(dir) - if int(action.get('process_outputs_as_sources', False)): - extra_sources += outputs - if int(action.get('process_outputs_as_mac_bundle_resources', False)): - extra_mac_bundle_resources += outputs - - # Write the actual command. - action_commands = action['action'] - if self.flavor == 'mac': - action_commands = [gyp.xcode_emulation.ExpandEnvVars(command, env) - for command in action_commands] - command = gyp.common.EncodePOSIXShellList(action_commands) - if 'message' in action: - self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, action['message'])) - else: - self.WriteLn('quiet_cmd_%s = ACTION %s $@' % (name, name)) - if len(dirs) > 0: - command = 'mkdir -p %s' % ' '.join(dirs) + '; ' + command - - cd_action = 'cd %s; ' % Sourceify(self.path or '.') - - # command and cd_action get written to a toplevel variable called - # cmd_foo. Toplevel variables can't handle things that change per - # makefile like $(TARGET), so hardcode the target. - command = command.replace('$(TARGET)', self.target) - cd_action = cd_action.replace('$(TARGET)', self.target) - - # Set LD_LIBRARY_PATH in case the action runs an executable from this - # build which links to shared libs from this build. - # actions run on the host, so they should in theory only use host - # libraries, but until everything is made cross-compile safe, also use - # target libraries. - # TODO(piman): when everything is cross-compile safe, remove lib.target - self.WriteLn('cmd_%s = LD_LIBRARY_PATH=$(builddir)/lib.host:' - '$(builddir)/lib.target:$$LD_LIBRARY_PATH; ' - 'export LD_LIBRARY_PATH; ' - '%s%s' - % (name, cd_action, command)) - self.WriteLn() - outputs = map(self.Absolutify, outputs) - # The makefile rules are all relative to the top dir, but the gyp actions - # are defined relative to their containing dir. This replaces the obj - # variable for the action rule with an absolute version so that the output - # goes in the right place. - # Only write the 'obj' and 'builddir' rules for the "primary" output (:1); - # it's superfluous for the "extra outputs", and this avoids accidentally - # writing duplicate dummy rules for those outputs. - # Same for environment. - self.WriteLn("%s: obj := $(abs_obj)" % QuoteSpaces(outputs[0])) - self.WriteLn("%s: builddir := $(abs_builddir)" % QuoteSpaces(outputs[0])) - self.WriteSortedXcodeEnv(outputs[0], self.GetSortedXcodeEnv()) - - for input in inputs: - assert ' ' not in input, ( - "Spaces in action input filenames not supported (%s)" % input) - for output in outputs: - assert ' ' not in output, ( - "Spaces in action output filenames not supported (%s)" % output) - - # See the comment in WriteCopies about expanding env vars. - outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs] - inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs] - - self.WriteDoCmd(outputs, map(Sourceify, map(self.Absolutify, inputs)), - part_of_all=part_of_all, command=name) - - # Stuff the outputs in a variable so we can refer to them later. - outputs_variable = 'action_%s_outputs' % name - self.WriteLn('%s := %s' % (outputs_variable, ' '.join(outputs))) - extra_outputs.append('$(%s)' % outputs_variable) - self.WriteLn() - - self.WriteLn() - - - def WriteRules(self, rules, extra_sources, extra_outputs, - extra_mac_bundle_resources, part_of_all): - """Write Makefile code for any 'rules' from the gyp input. - - extra_sources: a list that will be filled in with newly generated source - files, if any - extra_outputs: a list that will be filled in with any outputs of these - rules (used to make other pieces dependent on these rules) - part_of_all: flag indicating this target is part of 'all' - """ - env = self.GetSortedXcodeEnv() - for rule in rules: - name = StringToMakefileVariable('%s_%s' % (self.qualified_target, - rule['rule_name'])) - count = 0 - self.WriteLn('### Generated for rule %s:' % name) - - all_outputs = [] - - for rule_source in rule.get('rule_sources', []): - dirs = set() - (rule_source_dirname, rule_source_basename) = os.path.split(rule_source) - (rule_source_root, rule_source_ext) = \ - os.path.splitext(rule_source_basename) - - outputs = [self.ExpandInputRoot(out, rule_source_root, - rule_source_dirname) - for out in rule['outputs']] - - for out in outputs: - dir = os.path.dirname(out) - if dir: - dirs.add(dir) - if int(rule.get('process_outputs_as_sources', False)): - extra_sources += outputs - if int(rule.get('process_outputs_as_mac_bundle_resources', False)): - extra_mac_bundle_resources += outputs - inputs = map(Sourceify, map(self.Absolutify, [rule_source] + - rule.get('inputs', []))) - actions = ['$(call do_cmd,%s_%d)' % (name, count)] - - if name == 'resources_grit': - # HACK: This is ugly. Grit intentionally doesn't touch the - # timestamp of its output file when the file doesn't change, - # which is fine in hash-based dependency systems like scons - # and forge, but not kosher in the make world. After some - # discussion, hacking around it here seems like the least - # amount of pain. - actions += ['@touch --no-create $@'] - - # See the comment in WriteCopies about expanding env vars. - outputs = [gyp.xcode_emulation.ExpandEnvVars(o, env) for o in outputs] - inputs = [gyp.xcode_emulation.ExpandEnvVars(i, env) for i in inputs] - - outputs = map(self.Absolutify, outputs) - all_outputs += outputs - # Only write the 'obj' and 'builddir' rules for the "primary" output - # (:1); it's superfluous for the "extra outputs", and this avoids - # accidentally writing duplicate dummy rules for those outputs. - self.WriteLn('%s: obj := $(abs_obj)' % outputs[0]) - self.WriteLn('%s: builddir := $(abs_builddir)' % outputs[0]) - self.WriteMakeRule(outputs, inputs, actions, - command="%s_%d" % (name, count)) - # Spaces in rule filenames are not supported, but rule variables have - # spaces in them (e.g. RULE_INPUT_PATH expands to '$(abspath $<)'). - # The spaces within the variables are valid, so remove the variables - # before checking. - variables_with_spaces = re.compile(r'\$\([^ ]* \$<\)') - for output in outputs: - output = re.sub(variables_with_spaces, '', output) - assert ' ' not in output, ( - "Spaces in rule filenames not yet supported (%s)" % output) - self.WriteLn('all_deps += %s' % ' '.join(outputs)) - - action = [self.ExpandInputRoot(ac, rule_source_root, - rule_source_dirname) - for ac in rule['action']] - mkdirs = '' - if len(dirs) > 0: - mkdirs = 'mkdir -p %s; ' % ' '.join(dirs) - cd_action = 'cd %s; ' % Sourceify(self.path or '.') - - # action, cd_action, and mkdirs get written to a toplevel variable - # called cmd_foo. Toplevel variables can't handle things that change - # per makefile like $(TARGET), so hardcode the target. - if self.flavor == 'mac': - action = [gyp.xcode_emulation.ExpandEnvVars(command, env) - for command in action] - action = gyp.common.EncodePOSIXShellList(action) - action = action.replace('$(TARGET)', self.target) - cd_action = cd_action.replace('$(TARGET)', self.target) - mkdirs = mkdirs.replace('$(TARGET)', self.target) - - # Set LD_LIBRARY_PATH in case the rule runs an executable from this - # build which links to shared libs from this build. - # rules run on the host, so they should in theory only use host - # libraries, but until everything is made cross-compile safe, also use - # target libraries. - # TODO(piman): when everything is cross-compile safe, remove lib.target - self.WriteLn( - "cmd_%(name)s_%(count)d = LD_LIBRARY_PATH=" - "$(builddir)/lib.host:$(builddir)/lib.target:$$LD_LIBRARY_PATH; " - "export LD_LIBRARY_PATH; " - "%(cd_action)s%(mkdirs)s%(action)s" % { - 'action': action, - 'cd_action': cd_action, - 'count': count, - 'mkdirs': mkdirs, - 'name': name, - }) - self.WriteLn( - 'quiet_cmd_%(name)s_%(count)d = RULE %(name)s_%(count)d $@' % { - 'count': count, - 'name': name, - }) - self.WriteLn() - count += 1 - - outputs_variable = 'rule_%s_outputs' % name - self.WriteList(all_outputs, outputs_variable) - extra_outputs.append('$(%s)' % outputs_variable) - - self.WriteLn('### Finished generating for rule: %s' % name) - self.WriteLn() - self.WriteLn('### Finished generating for all rules') - self.WriteLn('') - - - def WriteCopies(self, copies, extra_outputs, part_of_all): - """Write Makefile code for any 'copies' from the gyp input. - - extra_outputs: a list that will be filled in with any outputs of this action - (used to make other pieces dependent on this action) - part_of_all: flag indicating this target is part of 'all' - """ - self.WriteLn('### Generated for copy rule.') - - variable = StringToMakefileVariable(self.qualified_target + '_copies') - outputs = [] - for copy in copies: - for path in copy['files']: - # Absolutify() may call normpath, and will strip trailing slashes. - path = Sourceify(self.Absolutify(path)) - filename = os.path.split(path)[1] - output = Sourceify(self.Absolutify(os.path.join(copy['destination'], - filename))) - - # If the output path has variables in it, which happens in practice for - # 'copies', writing the environment as target-local doesn't work, - # because the variables are already needed for the target name. - # Copying the environment variables into global make variables doesn't - # work either, because then the .d files will potentially contain spaces - # after variable expansion, and .d file handling cannot handle spaces. - # As a workaround, manually expand variables at gyp time. Since 'copies' - # can't run scripts, there's no need to write the env then. - # WriteDoCmd() will escape spaces for .d files. - env = self.GetSortedXcodeEnv() - output = gyp.xcode_emulation.ExpandEnvVars(output, env) - path = gyp.xcode_emulation.ExpandEnvVars(path, env) - self.WriteDoCmd([output], [path], 'copy', part_of_all) - outputs.append(output) - self.WriteLn('%s = %s' % (variable, ' '.join(map(QuoteSpaces, outputs)))) - extra_outputs.append('$(%s)' % variable) - self.WriteLn() - - - def WriteMacBundleResources(self, resources, bundle_deps): - """Writes Makefile code for 'mac_bundle_resources'.""" - self.WriteLn('### Generated for mac_bundle_resources') - - for output, res in gyp.xcode_emulation.GetMacBundleResources( - generator_default_variables['PRODUCT_DIR'], self.xcode_settings, - map(Sourceify, map(self.Absolutify, resources))): - _, ext = os.path.splitext(output) - if ext != '.xcassets': - # Make does not supports '.xcassets' emulation. - self.WriteDoCmd([output], [res], 'mac_tool,,,copy-bundle-resource', - part_of_all=True) - bundle_deps.append(output) - - - def WriteMacInfoPlist(self, bundle_deps): - """Write Makefile code for bundle Info.plist files.""" - info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist( - generator_default_variables['PRODUCT_DIR'], self.xcode_settings, - lambda p: Sourceify(self.Absolutify(p))) - if not info_plist: - return - if defines: - # Create an intermediate file to store preprocessed results. - intermediate_plist = ('$(obj).$(TOOLSET)/$(TARGET)/' + - os.path.basename(info_plist)) - self.WriteList(defines, intermediate_plist + ': INFOPLIST_DEFINES', '-D', - quoter=EscapeCppDefine) - self.WriteMakeRule([intermediate_plist], [info_plist], - ['$(call do_cmd,infoplist)', - # "Convert" the plist so that any weird whitespace changes from the - # preprocessor do not affect the XML parser in mac_tool. - '@plutil -convert xml1 $@ $@']) - info_plist = intermediate_plist - # plists can contain envvars and substitute them into the file. - self.WriteSortedXcodeEnv( - out, self.GetSortedXcodeEnv(additional_settings=extra_env)) - self.WriteDoCmd([out], [info_plist], 'mac_tool,,,copy-info-plist', - part_of_all=True) - bundle_deps.append(out) - - - def WriteSources(self, configs, deps, sources, - extra_outputs, extra_link_deps, - part_of_all, precompiled_header): - """Write Makefile code for any 'sources' from the gyp input. - These are source files necessary to build the current target. - - configs, deps, sources: input from gyp. - extra_outputs: a list of extra outputs this action should be dependent on; - used to serialize action/rules before compilation - extra_link_deps: a list that will be filled in with any outputs of - compilation (to be used in link lines) - part_of_all: flag indicating this target is part of 'all' - """ - - # Write configuration-specific variables for CFLAGS, etc. - for configname in sorted(configs.keys()): - config = configs[configname] - self.WriteList(config.get('defines'), 'DEFS_%s' % configname, prefix='-D', - quoter=EscapeCppDefine) - - if self.flavor == 'mac': - cflags = self.xcode_settings.GetCflags(configname) - cflags_c = self.xcode_settings.GetCflagsC(configname) - cflags_cc = self.xcode_settings.GetCflagsCC(configname) - cflags_objc = self.xcode_settings.GetCflagsObjC(configname) - cflags_objcc = self.xcode_settings.GetCflagsObjCC(configname) - else: - cflags = config.get('cflags') - cflags_c = config.get('cflags_c') - cflags_cc = config.get('cflags_cc') - - self.WriteLn("# Flags passed to all source files."); - self.WriteList(cflags, 'CFLAGS_%s' % configname) - self.WriteLn("# Flags passed to only C files."); - self.WriteList(cflags_c, 'CFLAGS_C_%s' % configname) - self.WriteLn("# Flags passed to only C++ files."); - self.WriteList(cflags_cc, 'CFLAGS_CC_%s' % configname) - if self.flavor == 'mac': - self.WriteLn("# Flags passed to only ObjC files."); - self.WriteList(cflags_objc, 'CFLAGS_OBJC_%s' % configname) - self.WriteLn("# Flags passed to only ObjC++ files."); - self.WriteList(cflags_objcc, 'CFLAGS_OBJCC_%s' % configname) - includes = config.get('include_dirs') - if includes: - includes = map(Sourceify, map(self.Absolutify, includes)) - self.WriteList(includes, 'INCS_%s' % configname, prefix='-I') - - compilable = filter(Compilable, sources) - objs = map(self.Objectify, map(self.Absolutify, map(Target, compilable))) - self.WriteList(objs, 'OBJS') - - for obj in objs: - assert ' ' not in obj, ( - "Spaces in object filenames not supported (%s)" % obj) - self.WriteLn('# Add to the list of files we specially track ' - 'dependencies for.') - self.WriteLn('all_deps += $(OBJS)') - self.WriteLn() - - # Make sure our dependencies are built first. - if deps: - self.WriteMakeRule(['$(OBJS)'], deps, - comment = 'Make sure our dependencies are built ' - 'before any of us.', - order_only = True) - - # Make sure the actions and rules run first. - # If they generate any extra headers etc., the per-.o file dep tracking - # will catch the proper rebuilds, so order only is still ok here. - if extra_outputs: - self.WriteMakeRule(['$(OBJS)'], extra_outputs, - comment = 'Make sure our actions/rules run ' - 'before any of us.', - order_only = True) - - pchdeps = precompiled_header.GetObjDependencies(compilable, objs ) - if pchdeps: - self.WriteLn('# Dependencies from obj files to their precompiled headers') - for source, obj, gch in pchdeps: - self.WriteLn('%s: %s' % (obj, gch)) - self.WriteLn('# End precompiled header dependencies') - - if objs: - extra_link_deps.append('$(OBJS)') - self.WriteLn("""\ -# CFLAGS et al overrides must be target-local. -# See "Target-specific Variable Values" in the GNU Make manual.""") - self.WriteLn("$(OBJS): TOOLSET := $(TOOLSET)") - self.WriteLn("$(OBJS): GYP_CFLAGS := " - "$(DEFS_$(BUILDTYPE)) " - "$(INCS_$(BUILDTYPE)) " - "%s " % precompiled_header.GetInclude('c') + - "$(CFLAGS_$(BUILDTYPE)) " - "$(CFLAGS_C_$(BUILDTYPE))") - self.WriteLn("$(OBJS): GYP_CXXFLAGS := " - "$(DEFS_$(BUILDTYPE)) " - "$(INCS_$(BUILDTYPE)) " - "%s " % precompiled_header.GetInclude('cc') + - "$(CFLAGS_$(BUILDTYPE)) " - "$(CFLAGS_CC_$(BUILDTYPE))") - if self.flavor == 'mac': - self.WriteLn("$(OBJS): GYP_OBJCFLAGS := " - "$(DEFS_$(BUILDTYPE)) " - "$(INCS_$(BUILDTYPE)) " - "%s " % precompiled_header.GetInclude('m') + - "$(CFLAGS_$(BUILDTYPE)) " - "$(CFLAGS_C_$(BUILDTYPE)) " - "$(CFLAGS_OBJC_$(BUILDTYPE))") - self.WriteLn("$(OBJS): GYP_OBJCXXFLAGS := " - "$(DEFS_$(BUILDTYPE)) " - "$(INCS_$(BUILDTYPE)) " - "%s " % precompiled_header.GetInclude('mm') + - "$(CFLAGS_$(BUILDTYPE)) " - "$(CFLAGS_CC_$(BUILDTYPE)) " - "$(CFLAGS_OBJCC_$(BUILDTYPE))") - - self.WritePchTargets(precompiled_header.GetPchBuildCommands()) - - # If there are any object files in our input file list, link them into our - # output. - extra_link_deps += filter(Linkable, sources) - - self.WriteLn() - - def WritePchTargets(self, pch_commands): - """Writes make rules to compile prefix headers.""" - if not pch_commands: - return - - for gch, lang_flag, lang, input in pch_commands: - extra_flags = { - 'c': '$(CFLAGS_C_$(BUILDTYPE))', - 'cc': '$(CFLAGS_CC_$(BUILDTYPE))', - 'm': '$(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE))', - 'mm': '$(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE))', - }[lang] - var_name = { - 'c': 'GYP_PCH_CFLAGS', - 'cc': 'GYP_PCH_CXXFLAGS', - 'm': 'GYP_PCH_OBJCFLAGS', - 'mm': 'GYP_PCH_OBJCXXFLAGS', - }[lang] - self.WriteLn("%s: %s := %s " % (gch, var_name, lang_flag) + - "$(DEFS_$(BUILDTYPE)) " - "$(INCS_$(BUILDTYPE)) " - "$(CFLAGS_$(BUILDTYPE)) " + - extra_flags) - - self.WriteLn('%s: %s FORCE_DO_CMD' % (gch, input)) - self.WriteLn('\t@$(call do_cmd,pch_%s,1)' % lang) - self.WriteLn('') - assert ' ' not in gch, ( - "Spaces in gch filenames not supported (%s)" % gch) - self.WriteLn('all_deps += %s' % gch) - self.WriteLn('') - - - def ComputeOutputBasename(self, spec): - """Return the 'output basename' of a gyp spec. - - E.g., the loadable module 'foobar' in directory 'baz' will produce - 'libfoobar.so' - """ - assert not self.is_mac_bundle - - if self.flavor == 'mac' and self.type in ( - 'static_library', 'executable', 'shared_library', 'loadable_module'): - return self.xcode_settings.GetExecutablePath() - - target = spec['target_name'] - target_prefix = '' - target_ext = '' - if self.type == 'static_library': - if target[:3] == 'lib': - target = target[3:] - target_prefix = 'lib' - target_ext = '.a' - elif self.type in ('loadable_module', 'shared_library'): - if target[:3] == 'lib': - target = target[3:] - target_prefix = 'lib' - if self.flavor == 'aix': - target_ext = '.a' - else: - target_ext = '.so' - elif self.type == 'none': - target = '%s.stamp' % target - elif self.type != 'executable': - print ("ERROR: What output file should be generated?", - "type", self.type, "target", target) - - target_prefix = spec.get('product_prefix', target_prefix) - target = spec.get('product_name', target) - product_ext = spec.get('product_extension') - if product_ext: - target_ext = '.' + product_ext - - return target_prefix + target + target_ext - - - def _InstallImmediately(self): - return self.toolset == 'target' and self.flavor == 'mac' and self.type in ( - 'static_library', 'executable', 'shared_library', 'loadable_module') - - - def ComputeOutput(self, spec): - """Return the 'output' (full output path) of a gyp spec. - - E.g., the loadable module 'foobar' in directory 'baz' will produce - '$(obj)/baz/libfoobar.so' - """ - assert not self.is_mac_bundle - - path = os.path.join('$(obj).' + self.toolset, self.path) - if self.type == 'executable' or self._InstallImmediately(): - path = '$(builddir)' - path = spec.get('product_dir', path) - return os.path.join(path, self.ComputeOutputBasename(spec)) - - - def ComputeMacBundleOutput(self, spec): - """Return the 'output' (full output path) to a bundle output directory.""" - assert self.is_mac_bundle - path = generator_default_variables['PRODUCT_DIR'] - return os.path.join(path, self.xcode_settings.GetWrapperName()) - - - def ComputeMacBundleBinaryOutput(self, spec): - """Return the 'output' (full output path) to the binary in a bundle.""" - path = generator_default_variables['PRODUCT_DIR'] - return os.path.join(path, self.xcode_settings.GetExecutablePath()) - - - def ComputeDeps(self, spec): - """Compute the dependencies of a gyp spec. - - Returns a tuple (deps, link_deps), where each is a list of - filenames that will need to be put in front of make for either - building (deps) or linking (link_deps). - """ - deps = [] - link_deps = [] - if 'dependencies' in spec: - deps.extend([target_outputs[dep] for dep in spec['dependencies'] - if target_outputs[dep]]) - for dep in spec['dependencies']: - if dep in target_link_deps: - link_deps.append(target_link_deps[dep]) - deps.extend(link_deps) - # TODO: It seems we need to transitively link in libraries (e.g. -lfoo)? - # This hack makes it work: - # link_deps.extend(spec.get('libraries', [])) - return (gyp.common.uniquer(deps), gyp.common.uniquer(link_deps)) - - - def WriteDependencyOnExtraOutputs(self, target, extra_outputs): - self.WriteMakeRule([self.output_binary], extra_outputs, - comment = 'Build our special outputs first.', - order_only = True) - - - def WriteTarget(self, spec, configs, deps, link_deps, bundle_deps, - extra_outputs, part_of_all): - """Write Makefile code to produce the final target of the gyp spec. - - spec, configs: input from gyp. - deps, link_deps: dependency lists; see ComputeDeps() - extra_outputs: any extra outputs that our target should depend on - part_of_all: flag indicating this target is part of 'all' - """ - - self.WriteLn('### Rules for final target.') - - if extra_outputs: - self.WriteDependencyOnExtraOutputs(self.output_binary, extra_outputs) - self.WriteMakeRule(extra_outputs, deps, - comment=('Preserve order dependency of ' - 'special output on deps.'), - order_only = True) - - target_postbuilds = {} - if self.type != 'none': - for configname in sorted(configs.keys()): - config = configs[configname] - if self.flavor == 'mac': - ldflags = self.xcode_settings.GetLdflags(configname, - generator_default_variables['PRODUCT_DIR'], - lambda p: Sourceify(self.Absolutify(p))) - - # TARGET_POSTBUILDS_$(BUILDTYPE) is added to postbuilds later on. - gyp_to_build = gyp.common.InvertRelativePath(self.path) - target_postbuild = self.xcode_settings.AddImplicitPostbuilds( - configname, - QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build, - self.output))), - QuoteSpaces(os.path.normpath(os.path.join(gyp_to_build, - self.output_binary)))) - if target_postbuild: - target_postbuilds[configname] = target_postbuild - else: - ldflags = config.get('ldflags', []) - # Compute an rpath for this output if needed. - if any(dep.endswith('.so') or '.so.' in dep for dep in deps): - # We want to get the literal string "$ORIGIN" into the link command, - # so we need lots of escaping. - ldflags.append(r'-Wl,-rpath=\$$ORIGIN/lib.%s/' % self.toolset) - ldflags.append(r'-Wl,-rpath-link=\$(builddir)/lib.%s/' % - self.toolset) - library_dirs = config.get('library_dirs', []) - ldflags += [('-L%s' % library_dir) for library_dir in library_dirs] - self.WriteList(ldflags, 'LDFLAGS_%s' % configname) - if self.flavor == 'mac': - self.WriteList(self.xcode_settings.GetLibtoolflags(configname), - 'LIBTOOLFLAGS_%s' % configname) - libraries = spec.get('libraries') - if libraries: - # Remove duplicate entries - libraries = gyp.common.uniquer(libraries) - if self.flavor == 'mac': - libraries = self.xcode_settings.AdjustLibraries(libraries) - self.WriteList(libraries, 'LIBS') - self.WriteLn('%s: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE))' % - QuoteSpaces(self.output_binary)) - self.WriteLn('%s: LIBS := $(LIBS)' % QuoteSpaces(self.output_binary)) - - if self.flavor == 'mac': - self.WriteLn('%s: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE))' % - QuoteSpaces(self.output_binary)) - - # Postbuild actions. Like actions, but implicitly depend on the target's - # output. - postbuilds = [] - if self.flavor == 'mac': - if target_postbuilds: - postbuilds.append('$(TARGET_POSTBUILDS_$(BUILDTYPE))') - postbuilds.extend( - gyp.xcode_emulation.GetSpecPostbuildCommands(spec)) - - if postbuilds: - # Envvars may be referenced by TARGET_POSTBUILDS_$(BUILDTYPE), - # so we must output its definition first, since we declare variables - # using ":=". - self.WriteSortedXcodeEnv(self.output, self.GetSortedXcodePostbuildEnv()) - - for configname in target_postbuilds: - self.WriteLn('%s: TARGET_POSTBUILDS_%s := %s' % - (QuoteSpaces(self.output), - configname, - gyp.common.EncodePOSIXShellList(target_postbuilds[configname]))) - - # Postbuilds expect to be run in the gyp file's directory, so insert an - # implicit postbuild to cd to there. - postbuilds.insert(0, gyp.common.EncodePOSIXShellList(['cd', self.path])) - for i in xrange(len(postbuilds)): - if not postbuilds[i].startswith('$'): - postbuilds[i] = EscapeShellArgument(postbuilds[i]) - self.WriteLn('%s: builddir := $(abs_builddir)' % QuoteSpaces(self.output)) - self.WriteLn('%s: POSTBUILDS := %s' % ( - QuoteSpaces(self.output), ' '.join(postbuilds))) - - # A bundle directory depends on its dependencies such as bundle resources - # and bundle binary. When all dependencies have been built, the bundle - # needs to be packaged. - if self.is_mac_bundle: - # If the framework doesn't contain a binary, then nothing depends - # on the actions -- make the framework depend on them directly too. - self.WriteDependencyOnExtraOutputs(self.output, extra_outputs) - - # Bundle dependencies. Note that the code below adds actions to this - # target, so if you move these two lines, move the lines below as well. - self.WriteList(map(QuoteSpaces, bundle_deps), 'BUNDLE_DEPS') - self.WriteLn('%s: $(BUNDLE_DEPS)' % QuoteSpaces(self.output)) - - # After the framework is built, package it. Needs to happen before - # postbuilds, since postbuilds depend on this. - if self.type in ('shared_library', 'loadable_module'): - self.WriteLn('\t@$(call do_cmd,mac_package_framework,,,%s)' % - self.xcode_settings.GetFrameworkVersion()) - - # Bundle postbuilds can depend on the whole bundle, so run them after - # the bundle is packaged, not already after the bundle binary is done. - if postbuilds: - self.WriteLn('\t@$(call do_postbuilds)') - postbuilds = [] # Don't write postbuilds for target's output. - - # Needed by test/mac/gyptest-rebuild.py. - self.WriteLn('\t@true # No-op, used by tests') - - # Since this target depends on binary and resources which are in - # nested subfolders, the framework directory will be older than - # its dependencies usually. To prevent this rule from executing - # on every build (expensive, especially with postbuilds), expliclity - # update the time on the framework directory. - self.WriteLn('\t@touch -c %s' % QuoteSpaces(self.output)) - - if postbuilds: - assert not self.is_mac_bundle, ('Postbuilds for bundles should be done ' - 'on the bundle, not the binary (target \'%s\')' % self.target) - assert 'product_dir' not in spec, ('Postbuilds do not work with ' - 'custom product_dir') - - if self.type == 'executable': - self.WriteLn('%s: LD_INPUTS := %s' % ( - QuoteSpaces(self.output_binary), - ' '.join(map(QuoteSpaces, link_deps)))) - if self.toolset == 'host' and self.flavor == 'android': - self.WriteDoCmd([self.output_binary], link_deps, 'link_host', - part_of_all, postbuilds=postbuilds) - else: - self.WriteDoCmd([self.output_binary], link_deps, 'link', part_of_all, - postbuilds=postbuilds) - - elif self.type == 'static_library': - for link_dep in link_deps: - assert ' ' not in link_dep, ( - "Spaces in alink input filenames not supported (%s)" % link_dep) - if (self.flavor not in ('mac', 'openbsd', 'netbsd', 'win') and not - self.is_standalone_static_library): - self.WriteDoCmd([self.output_binary], link_deps, 'alink_thin', - part_of_all, postbuilds=postbuilds) - else: - self.WriteDoCmd([self.output_binary], link_deps, 'alink', part_of_all, - postbuilds=postbuilds) - elif self.type == 'shared_library': - self.WriteLn('%s: LD_INPUTS := %s' % ( - QuoteSpaces(self.output_binary), - ' '.join(map(QuoteSpaces, link_deps)))) - self.WriteDoCmd([self.output_binary], link_deps, 'solink', part_of_all, - postbuilds=postbuilds) - elif self.type == 'loadable_module': - for link_dep in link_deps: - assert ' ' not in link_dep, ( - "Spaces in module input filenames not supported (%s)" % link_dep) - if self.toolset == 'host' and self.flavor == 'android': - self.WriteDoCmd([self.output_binary], link_deps, 'solink_module_host', - part_of_all, postbuilds=postbuilds) - else: - self.WriteDoCmd( - [self.output_binary], link_deps, 'solink_module', part_of_all, - postbuilds=postbuilds) - elif self.type == 'none': - # Write a stamp line. - self.WriteDoCmd([self.output_binary], deps, 'touch', part_of_all, - postbuilds=postbuilds) - else: - print "WARNING: no output for", self.type, target - - # Add an alias for each target (if there are any outputs). - # Installable target aliases are created below. - if ((self.output and self.output != self.target) and - (self.type not in self._INSTALLABLE_TARGETS)): - self.WriteMakeRule([self.target], [self.output], - comment='Add target alias', phony = True) - if part_of_all: - self.WriteMakeRule(['all'], [self.target], - comment = 'Add target alias to "all" target.', - phony = True) - - # Add special-case rules for our installable targets. - # 1) They need to install to the build dir or "product" dir. - # 2) They get shortcuts for building (e.g. "make chrome"). - # 3) They are part of "make all". - if (self.type in self._INSTALLABLE_TARGETS or - self.is_standalone_static_library): - if self.type == 'shared_library': - file_desc = 'shared library' - elif self.type == 'static_library': - file_desc = 'static library' - else: - file_desc = 'executable' - install_path = self._InstallableTargetInstallPath() - installable_deps = [self.output] - if (self.flavor == 'mac' and not 'product_dir' in spec and - self.toolset == 'target'): - # On mac, products are created in install_path immediately. - assert install_path == self.output, '%s != %s' % ( - install_path, self.output) - - # Point the target alias to the final binary output. - self.WriteMakeRule([self.target], [install_path], - comment='Add target alias', phony = True) - if install_path != self.output: - assert not self.is_mac_bundle # See comment a few lines above. - self.WriteDoCmd([install_path], [self.output], 'copy', - comment = 'Copy this to the %s output path.' % - file_desc, part_of_all=part_of_all) - installable_deps.append(install_path) - if self.output != self.alias and self.alias != self.target: - self.WriteMakeRule([self.alias], installable_deps, - comment = 'Short alias for building this %s.' % - file_desc, phony = True) - if part_of_all: - self.WriteMakeRule(['all'], [install_path], - comment = 'Add %s to "all" target.' % file_desc, - phony = True) - - - def WriteList(self, value_list, variable=None, prefix='', - quoter=QuoteIfNecessary): - """Write a variable definition that is a list of values. - - E.g. WriteList(['a','b'], 'foo', prefix='blah') writes out - foo = blaha blahb - but in a pretty-printed style. - """ - values = '' - if value_list: - value_list = [quoter(prefix + l) for l in value_list] - values = ' \\\n\t' + ' \\\n\t'.join(value_list) - self.fp.write('%s :=%s\n\n' % (variable, values)) - - - def WriteDoCmd(self, outputs, inputs, command, part_of_all, comment=None, - postbuilds=False): - """Write a Makefile rule that uses do_cmd. - - This makes the outputs dependent on the command line that was run, - as well as support the V= make command line flag. - """ - suffix = '' - if postbuilds: - assert ',' not in command - suffix = ',,1' # Tell do_cmd to honor $POSTBUILDS - self.WriteMakeRule(outputs, inputs, - actions = ['$(call do_cmd,%s%s)' % (command, suffix)], - comment = comment, - command = command, - force = True) - # Add our outputs to the list of targets we read depfiles from. - # all_deps is only used for deps file reading, and for deps files we replace - # spaces with ? because escaping doesn't work with make's $(sort) and - # other functions. - outputs = [QuoteSpaces(o, SPACE_REPLACEMENT) for o in outputs] - self.WriteLn('all_deps += %s' % ' '.join(outputs)) - - - def WriteMakeRule(self, outputs, inputs, actions=None, comment=None, - order_only=False, force=False, phony=False, command=None): - """Write a Makefile rule, with some extra tricks. - - outputs: a list of outputs for the rule (note: this is not directly - supported by make; see comments below) - inputs: a list of inputs for the rule - actions: a list of shell commands to run for the rule - comment: a comment to put in the Makefile above the rule (also useful - for making this Python script's code self-documenting) - order_only: if true, makes the dependency order-only - force: if true, include FORCE_DO_CMD as an order-only dep - phony: if true, the rule does not actually generate the named output, the - output is just a name to run the rule - command: (optional) command name to generate unambiguous labels - """ - outputs = map(QuoteSpaces, outputs) - inputs = map(QuoteSpaces, inputs) - - if comment: - self.WriteLn('# ' + comment) - if phony: - self.WriteLn('.PHONY: ' + ' '.join(outputs)) - if actions: - self.WriteLn("%s: TOOLSET := $(TOOLSET)" % outputs[0]) - force_append = ' FORCE_DO_CMD' if force else '' - - if order_only: - # Order only rule: Just write a simple rule. - # TODO(evanm): just make order_only a list of deps instead of this hack. - self.WriteLn('%s: | %s%s' % - (' '.join(outputs), ' '.join(inputs), force_append)) - elif len(outputs) == 1: - # Regular rule, one output: Just write a simple rule. - self.WriteLn('%s: %s%s' % (outputs[0], ' '.join(inputs), force_append)) - else: - # Regular rule, more than one output: Multiple outputs are tricky in - # make. We will write three rules: - # - All outputs depend on an intermediate file. - # - Make .INTERMEDIATE depend on the intermediate. - # - The intermediate file depends on the inputs and executes the - # actual command. - # - The intermediate recipe will 'touch' the intermediate file. - # - The multi-output rule will have an do-nothing recipe. - - # Hash the target name to avoid generating overlong filenames. - cmddigest = hashlib.sha1(command if command else self.target).hexdigest() - intermediate = "%s.intermediate" % cmddigest - self.WriteLn('%s: %s' % (' '.join(outputs), intermediate)) - self.WriteLn('\t%s' % '@:'); - self.WriteLn('%s: %s' % ('.INTERMEDIATE', intermediate)) - self.WriteLn('%s: %s%s' % - (intermediate, ' '.join(inputs), force_append)) - actions.insert(0, '$(call do_cmd,touch)') - - if actions: - for action in actions: - self.WriteLn('\t%s' % action) - self.WriteLn() - - - def WriteAndroidNdkModuleRule(self, module_name, all_sources, link_deps): - """Write a set of LOCAL_XXX definitions for Android NDK. - - These variable definitions will be used by Android NDK but do nothing for - non-Android applications. - - Arguments: - module_name: Android NDK module name, which must be unique among all - module names. - all_sources: A list of source files (will be filtered by Compilable). - link_deps: A list of link dependencies, which must be sorted in - the order from dependencies to dependents. - """ - if self.type not in ('executable', 'shared_library', 'static_library'): - return - - self.WriteLn('# Variable definitions for Android applications') - self.WriteLn('include $(CLEAR_VARS)') - self.WriteLn('LOCAL_MODULE := ' + module_name) - self.WriteLn('LOCAL_CFLAGS := $(CFLAGS_$(BUILDTYPE)) ' - '$(DEFS_$(BUILDTYPE)) ' - # LOCAL_CFLAGS is applied to both of C and C++. There is - # no way to specify $(CFLAGS_C_$(BUILDTYPE)) only for C - # sources. - '$(CFLAGS_C_$(BUILDTYPE)) ' - # $(INCS_$(BUILDTYPE)) includes the prefix '-I' while - # LOCAL_C_INCLUDES does not expect it. So put it in - # LOCAL_CFLAGS. - '$(INCS_$(BUILDTYPE))') - # LOCAL_CXXFLAGS is obsolete and LOCAL_CPPFLAGS is preferred. - self.WriteLn('LOCAL_CPPFLAGS := $(CFLAGS_CC_$(BUILDTYPE))') - self.WriteLn('LOCAL_C_INCLUDES :=') - self.WriteLn('LOCAL_LDLIBS := $(LDFLAGS_$(BUILDTYPE)) $(LIBS)') - - # Detect the C++ extension. - cpp_ext = {'.cc': 0, '.cpp': 0, '.cxx': 0} - default_cpp_ext = '.cpp' - for filename in all_sources: - ext = os.path.splitext(filename)[1] - if ext in cpp_ext: - cpp_ext[ext] += 1 - if cpp_ext[ext] > cpp_ext[default_cpp_ext]: - default_cpp_ext = ext - self.WriteLn('LOCAL_CPP_EXTENSION := ' + default_cpp_ext) - - self.WriteList(map(self.Absolutify, filter(Compilable, all_sources)), - 'LOCAL_SRC_FILES') - - # Filter out those which do not match prefix and suffix and produce - # the resulting list without prefix and suffix. - def DepsToModules(deps, prefix, suffix): - modules = [] - for filepath in deps: - filename = os.path.basename(filepath) - if filename.startswith(prefix) and filename.endswith(suffix): - modules.append(filename[len(prefix):-len(suffix)]) - return modules - - # Retrieve the default value of 'SHARED_LIB_SUFFIX' - params = {'flavor': 'linux'} - default_variables = {} - CalculateVariables(default_variables, params) - - self.WriteList( - DepsToModules(link_deps, - generator_default_variables['SHARED_LIB_PREFIX'], - default_variables['SHARED_LIB_SUFFIX']), - 'LOCAL_SHARED_LIBRARIES') - self.WriteList( - DepsToModules(link_deps, - generator_default_variables['STATIC_LIB_PREFIX'], - generator_default_variables['STATIC_LIB_SUFFIX']), - 'LOCAL_STATIC_LIBRARIES') - - if self.type == 'executable': - self.WriteLn('include $(BUILD_EXECUTABLE)') - elif self.type == 'shared_library': - self.WriteLn('include $(BUILD_SHARED_LIBRARY)') - elif self.type == 'static_library': - self.WriteLn('include $(BUILD_STATIC_LIBRARY)') - self.WriteLn() - - - def WriteLn(self, text=''): - self.fp.write(text + '\n') - - - def GetSortedXcodeEnv(self, additional_settings=None): - return gyp.xcode_emulation.GetSortedXcodeEnv( - self.xcode_settings, "$(abs_builddir)", - os.path.join("$(abs_srcdir)", self.path), "$(BUILDTYPE)", - additional_settings) - - - def GetSortedXcodePostbuildEnv(self): - # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack. - # TODO(thakis): It would be nice to have some general mechanism instead. - strip_save_file = self.xcode_settings.GetPerTargetSetting( - 'CHROMIUM_STRIP_SAVE_FILE', '') - # Even if strip_save_file is empty, explicitly write it. Else a postbuild - # might pick up an export from an earlier target. - return self.GetSortedXcodeEnv( - additional_settings={'CHROMIUM_STRIP_SAVE_FILE': strip_save_file}) - - - def WriteSortedXcodeEnv(self, target, env): - for k, v in env: - # For - # foo := a\ b - # the escaped space does the right thing. For - # export foo := a\ b - # it does not -- the backslash is written to the env as literal character. - # So don't escape spaces in |env[k]|. - self.WriteLn('%s: export %s := %s' % (QuoteSpaces(target), k, v)) - - - def Objectify(self, path): - """Convert a path to its output directory form.""" - if '$(' in path: - path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/' % self.toolset) - if not '$(obj)' in path: - path = '$(obj).%s/$(TARGET)/%s' % (self.toolset, path) - return path - - - def Pchify(self, path, lang): - """Convert a prefix header path to its output directory form.""" - path = self.Absolutify(path) - if '$(' in path: - path = path.replace('$(obj)/', '$(obj).%s/$(TARGET)/pch-%s' % - (self.toolset, lang)) - return path - return '$(obj).%s/$(TARGET)/pch-%s/%s' % (self.toolset, lang, path) - - - def Absolutify(self, path): - """Convert a subdirectory-relative path into a base-relative path. - Skips over paths that contain variables.""" - if '$(' in path: - # Don't call normpath in this case, as it might collapse the - # path too aggressively if it features '..'. However it's still - # important to strip trailing slashes. - return path.rstrip('/') - return os.path.normpath(os.path.join(self.path, path)) - - - def ExpandInputRoot(self, template, expansion, dirname): - if '%(INPUT_ROOT)s' not in template and '%(INPUT_DIRNAME)s' not in template: - return template - path = template % { - 'INPUT_ROOT': expansion, - 'INPUT_DIRNAME': dirname, - } - return path - - - def _InstallableTargetInstallPath(self): - """Returns the location of the final output for an installable target.""" - # Xcode puts shared_library results into PRODUCT_DIR, and some gyp files - # rely on this. Emulate this behavior for mac. - - # XXX(TooTallNate): disabling this code since we don't want this behavior... - #if (self.type == 'shared_library' and - # (self.flavor != 'mac' or self.toolset != 'target')): - # # Install all shared libs into a common directory (per toolset) for - # # convenient access with LD_LIBRARY_PATH. - # return '$(builddir)/lib.%s/%s' % (self.toolset, self.alias) - return '$(builddir)/' + self.alias - - -def WriteAutoRegenerationRule(params, root_makefile, makefile_name, - build_files): - """Write the target to regenerate the Makefile.""" - options = params['options'] - build_files_args = [gyp.common.RelativePath(filename, options.toplevel_dir) - for filename in params['build_files_arg']] - - gyp_binary = gyp.common.FixIfRelativePath(params['gyp_binary'], - options.toplevel_dir) - if not gyp_binary.startswith(os.sep): - gyp_binary = os.path.join('.', gyp_binary) - - root_makefile.write( - "quiet_cmd_regen_makefile = ACTION Regenerating $@\n" - "cmd_regen_makefile = cd $(srcdir); %(cmd)s\n" - "%(makefile_name)s: %(deps)s\n" - "\t$(call do_cmd,regen_makefile)\n\n" % { - 'makefile_name': makefile_name, - 'deps': ' '.join(map(SourceifyAndQuoteSpaces, build_files)), - 'cmd': gyp.common.EncodePOSIXShellList( - [gyp_binary, '-fmake'] + - gyp.RegenerateFlags(options) + - build_files_args)}) - - -def PerformBuild(data, configurations, params): - options = params['options'] - for config in configurations: - arguments = ['make'] - if options.toplevel_dir and options.toplevel_dir != '.': - arguments += '-C', options.toplevel_dir - arguments.append('BUILDTYPE=' + config) - print 'Building [%s]: %s' % (config, arguments) - subprocess.check_call(arguments) - - -def GenerateOutput(target_list, target_dicts, data, params): - options = params['options'] - flavor = gyp.common.GetFlavor(params) - generator_flags = params.get('generator_flags', {}) - builddir_name = generator_flags.get('output_dir', 'out') - android_ndk_version = generator_flags.get('android_ndk_version', None) - default_target = generator_flags.get('default_target', 'all') - - def CalculateMakefilePath(build_file, base_name): - """Determine where to write a Makefile for a given gyp file.""" - # Paths in gyp files are relative to the .gyp file, but we want - # paths relative to the source root for the master makefile. Grab - # the path of the .gyp file as the base to relativize against. - # E.g. "foo/bar" when we're constructing targets for "foo/bar/baz.gyp". - base_path = gyp.common.RelativePath(os.path.dirname(build_file), - options.depth) - # 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.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 - - # TODO: search for the first non-'Default' target. This can go - # away when we add verification that all targets have the - # necessary configurations. - default_configuration = None - toolsets = set([target_dicts[target]['toolset'] for target in target_list]) - for target in target_list: - spec = target_dicts[target] - if spec['default_configuration'] != 'Default': - default_configuration = spec['default_configuration'] - break - if not default_configuration: - default_configuration = 'Default' - - srcdir = '.' - makefile_name = 'Makefile' + options.suffix - makefile_path = os.path.join(options.toplevel_dir, makefile_name) - if options.generator_output: - global srcdir_prefix - makefile_path = os.path.join( - options.toplevel_dir, options.generator_output, makefile_name) - srcdir = gyp.common.RelativePath(srcdir, options.generator_output) - srcdir_prefix = '$(srcdir)/' - - flock_command= 'flock' - copy_archive_arguments = '-af' - makedep_arguments = '-MMD' - header_params = { - 'default_target': default_target, - 'builddir': builddir_name, - 'default_configuration': default_configuration, - 'flock': flock_command, - 'flock_index': 1, - 'link_commands': LINK_COMMANDS_LINUX, - 'extra_commands': '', - 'srcdir': srcdir, - 'copy_archive_args': copy_archive_arguments, - 'makedep_args': makedep_arguments, - } - if flavor == 'mac': - flock_command = './gyp-mac-tool flock' - header_params.update({ - 'flock': flock_command, - 'flock_index': 2, - 'link_commands': LINK_COMMANDS_MAC, - 'extra_commands': SHARED_HEADER_MAC_COMMANDS, - }) - elif flavor == 'android': - header_params.update({ - 'link_commands': LINK_COMMANDS_ANDROID, - }) - elif flavor == 'zos': - copy_archive_arguments = '-fPR' - makedep_arguments = '-qmakedep=gcc' - header_params.update({ - 'copy_archive_args': copy_archive_arguments, - 'makedep_args': makedep_arguments, - 'link_commands': LINK_COMMANDS_OS390, - }) - elif flavor == 'solaris': - header_params.update({ - 'flock': './gyp-flock-tool flock', - 'flock_index': 2, - }) - elif flavor == 'freebsd': - # Note: OpenBSD has sysutils/flock. lockf seems to be FreeBSD specific. - header_params.update({ - 'flock': 'lockf', - }) - elif flavor == 'openbsd': - copy_archive_arguments = '-pPRf' - header_params.update({ - 'copy_archive_args': copy_archive_arguments, - }) - elif flavor == 'aix': - copy_archive_arguments = '-pPRf' - header_params.update({ - 'copy_archive_args': copy_archive_arguments, - 'link_commands': LINK_COMMANDS_AIX, - 'flock': './gyp-flock-tool flock', - 'flock_index': 2, - }) - - header_params.update({ - 'CC.target': GetEnvironFallback(('CC_target', 'CC'), '$(CC)'), - 'AR.target': GetEnvironFallback(('AR_target', 'AR'), '$(AR)'), - 'CXX.target': GetEnvironFallback(('CXX_target', 'CXX'), '$(CXX)'), - 'LINK.target': GetEnvironFallback(('LINK_target', 'LINK'), '$(LINK)'), - 'CC.host': GetEnvironFallback(('CC_host', 'CC'), 'gcc'), - 'AR.host': GetEnvironFallback(('AR_host', 'AR'), 'ar'), - 'CXX.host': GetEnvironFallback(('CXX_host', 'CXX'), 'g++'), - 'LINK.host': GetEnvironFallback(('LINK_host', 'LINK'), '$(CXX.host)'), - }) - - build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) - make_global_settings_array = data[build_file].get('make_global_settings', []) - wrappers = {} - for key, value in make_global_settings_array: - if key.endswith('_wrapper'): - wrappers[key[:-len('_wrapper')]] = '$(abspath %s)' % value - make_global_settings = '' - for key, value in make_global_settings_array: - if re.match('.*_wrapper', key): - continue - if value[0] != '$': - value = '$(abspath %s)' % value - wrapper = wrappers.get(key) - if wrapper: - value = '%s %s' % (wrapper, value) - del wrappers[key] - if key in ('CC', 'CC.host', 'CXX', 'CXX.host'): - make_global_settings += ( - 'ifneq (,$(filter $(origin %s), undefined default))\n' % key) - # Let gyp-time envvars win over global settings. - 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: - make_global_settings += '%s ?= %s\n' % (key, value) - # TODO(ukai): define cmd when only wrapper is specified in - # make_global_settings. - - header_params['make_global_settings'] = make_global_settings - - 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 - # could be different. - if android_ndk_version: - root_makefile.write( - '# Define LOCAL_PATH for build of Android applications.\n' - 'LOCAL_PATH := $(call my-dir)\n' - '\n') - for toolset in toolsets: - root_makefile.write('TOOLSET := %s\n' % toolset) - WriteRootHeaderSuffixRules(root_makefile) - - # Put build-time support tools next to the root Makefile. - dest_path = os.path.dirname(makefile_path) - gyp.common.CopyTool(flavor, dest_path) - - # Find the list of targets that derive from the gyp file(s) being built. - needed_targets = set() - for build_file in params['build_files']: - for target in gyp.common.AllTargets(target_list, target_dicts, build_file): - needed_targets.add(target) - - build_files = set() - include_list = set() - for qualified_target in target_list: - build_file, target, toolset = gyp.common.ParseQualifiedTarget( - qualified_target) - - 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. %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'] - for included_file in included_files: - # The included_files entries are relative to the dir of the build file - # that included them, so we have to undo that and then make them relative - # to the root dir. - relative_include_file = gyp.common.RelativePath( - gyp.common.UnrelativePath(included_file, build_file), - options.toplevel_dir) - abs_include_file = os.path.abspath(relative_include_file) - # If the include file is from the ~/.gyp dir, we should use absolute path - # so that relocating the src dir doesn't break the path. - if (params['home_dot_gyp'] and - abs_include_file.startswith(params['home_dot_gyp'])): - build_files.add(abs_include_file) - else: - build_files.add(relative_include_file) - - base_path, output_file = CalculateMakefilePath(build_file, - target + '.' + toolset + options.suffix + '.mk') - - spec = target_dicts[qualified_target] - configs = spec['configurations'] - - if flavor == 'mac': - gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec) - - writer = MakefileWriter(generator_flags, flavor) - writer.Write(qualified_target, base_path, output_file, spec, configs, - part_of_all=qualified_target in needed_targets) - - # Our root_makefile lives at the source root. Compute the relative path - # from there to the output_file for including. - mkfile_rel_path = gyp.common.RelativePath(output_file, - os.path.dirname(makefile_path)) - include_list.add(mkfile_rel_path) - - # Write out per-gyp (sub-project) Makefiles. - depth_rel_path = gyp.common.RelativePath(options.depth, os.getcwd()) - for build_file in build_files: - # The paths in build_files were relativized above, so undo that before - # testing against the non-relativized items in target_list and before - # calculating the Makefile path. - build_file = os.path.join(depth_rel_path, build_file) - gyp_targets = [target_dicts[target]['target_name'] for target in target_list - if target.startswith(build_file) and - target in needed_targets] - # Only generate Makefiles for gyp files with targets. - if not gyp_targets: - continue - base_path, output_file = CalculateMakefilePath(build_file, - os.path.splitext(os.path.basename(build_file))[0] + '.Makefile') - makefile_rel_path = gyp.common.RelativePath(os.path.dirname(makefile_path), - os.path.dirname(output_file)) - writer.WriteSubMake(output_file, makefile_rel_path, gyp_targets, - builddir_name) - - - # Write out the sorted list of includes. - root_makefile.write('\n') - for include_file in sorted(include_list): - # We wrap each .mk include in an if statement so users can tell make to - # not load a file by setting NO_LOAD. The below make code says, only - # load the .mk file if the .mk filename doesn't start with a token in - # NO_LOAD. - root_makefile.write( - "ifeq ($(strip $(foreach prefix,$(NO_LOAD),\\\n" - " $(findstring $(join ^,$(prefix)),\\\n" - " $(join ^," + include_file + ")))),)\n") - root_makefile.write(" include " + include_file + "\n") - root_makefile.write("endif\n") - root_makefile.write('\n') - - if (not generator_flags.get('standalone') - and generator_flags.get('auto_regeneration', True)): - WriteAutoRegenerationRule(params, root_makefile, makefile_name, build_files) - - root_makefile.write(SHARED_FOOTER) - - root_makefile.close() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py deleted file mode 100644 index 3901ba94161e6..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs.py +++ /dev/null @@ -1,3494 +0,0 @@ -# Copyright (c) 2012 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. - -import copy -import ntpath -import os -import posixpath -import re -import subprocess -import sys - -import gyp.common -import gyp.easy_xml as easy_xml -import gyp.generator.ninja as ninja_generator -import gyp.MSVSNew as MSVSNew -import gyp.MSVSProject as MSVSProject -import gyp.MSVSSettings as MSVSSettings -import gyp.MSVSToolFile as MSVSToolFile -import gyp.MSVSUserFile as MSVSUserFile -import gyp.MSVSUtil as MSVSUtil -import gyp.MSVSVersion as MSVSVersion -from gyp.common import GypError -from gyp.common import OrderedSet - -# 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, -# IncrediBuild BuildConsole will parse the solution file, but then -# silently skip building the target causing hard to track down errors. -# Note that this only happens with the BuildConsole, and does not occur -# if IncrediBuild is executed from inside Visual Studio. This regex -# validates that the string looks like a GUID with all uppercase hex -# letters. -VALID_MSVS_GUID_CHARS = re.compile(r'^[A-F0-9\-]+$') - - -generator_default_variables = { - 'EXECUTABLE_PREFIX': '', - 'EXECUTABLE_SUFFIX': '.exe', - 'STATIC_LIB_PREFIX': '', - 'SHARED_LIB_PREFIX': '', - 'STATIC_LIB_SUFFIX': '.lib', - 'SHARED_LIB_SUFFIX': '.dll', - 'INTERMEDIATE_DIR': '$(IntDir)', - 'SHARED_INTERMEDIATE_DIR': '$(OutDir)obj/global_intermediate', - 'OS': 'win', - 'PRODUCT_DIR': '$(OutDir)', - 'LIB_DIR': '$(OutDir)lib', - 'RULE_INPUT_ROOT': '$(InputName)', - 'RULE_INPUT_DIRNAME': '$(InputDir)', - 'RULE_INPUT_EXT': '$(InputExt)', - 'RULE_INPUT_NAME': '$(InputFileName)', - 'RULE_INPUT_PATH': '$(InputPath)', - 'CONFIGURATION_NAME': '$(ConfigurationName)', -} - - -# The msvs specific sections that hold paths -generator_additional_path_sections = [ - 'msvs_cygwin_dirs', - 'msvs_props', -] - - -generator_additional_non_configuration_keys = [ - 'msvs_cygwin_dirs', - 'msvs_cygwin_shell', - 'msvs_large_pdb', - 'msvs_shard', - 'msvs_external_builder', - 'msvs_external_builder_out_dir', - 'msvs_external_builder_build_cmd', - 'msvs_external_builder_clean_cmd', - 'msvs_external_builder_clcompile_cmd', - 'msvs_enable_winrt', - 'msvs_requires_importlibrary', - 'msvs_enable_winphone', - 'msvs_application_type_revision', - 'msvs_target_platform_version', - 'msvs_target_platform_minversion', -] - - -# List of precompiled header related keys. -precomp_keys = [ - 'msvs_precompiled_header', - 'msvs_precompiled_source', -] - - -cached_username = None - - -cached_domain = None - - -# 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 -# 64-bit. -def _GetDomainAndUserName(): - if sys.platform not in ('win32', 'cygwin'): - return ('DOMAIN', 'USERNAME') - global cached_username - global cached_domain - if not cached_domain or not cached_username: - domain = os.environ.get('USERDOMAIN') - username = os.environ.get('USERNAME') - if not domain or not username: - call = subprocess.Popen(['net', 'config', 'Workstation'], - stdout=subprocess.PIPE) - config = call.communicate()[0] - username_re = re.compile(r'^User name\s+(\S+)', re.MULTILINE) - username_match = username_re.search(config) - if username_match: - username = username_match.group(1) - domain_re = re.compile(r'^Logon domain\s+(\S+)', re.MULTILINE) - domain_match = domain_re.search(config) - if domain_match: - domain = domain_match.group(1) - cached_domain = domain - cached_username = username - return (cached_domain, cached_username) - -fixpath_prefix = None - - -def _NormalizedSource(source): - """Normalize the path. - - But not if that gets rid of a variable, as this may expand to something - larger than one directory. - - Arguments: - source: The path to be normalize.d - - Returns: - The normalized path. - """ - normalized = os.path.normpath(source) - if source.count('$') == normalized.count('$'): - source = normalized - return source - - -def _FixPath(path): - """Convert paths to a form that will make sense in a vcproj file. - - Arguments: - path: The path to convert, may contain / etc. - Returns: - The path with all slashes made into backslashes. - """ - if fixpath_prefix and path and not os.path.isabs(path) and not path[0] == '$': - path = os.path.join(fixpath_prefix, path) - path = path.replace('/', '\\') - path = _NormalizedSource(path) - if path and path[-1] == '\\': - path = path[:-1] - return path - - -def _FixPaths(paths): - """Fix each of the paths of the list.""" - return [_FixPath(i) for i in paths] - - -def _ConvertSourcesToFilterHierarchy(sources, prefix=None, excluded=None, - 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 - layout of the source tree. - For example: - _ConvertSourcesToFilterHierarchy([['a', 'bob1.c'], ['b', 'bob2.c']], - prefix=['joe']) - --> - [MSVSProject.Filter('a', contents=['joe\\a\\bob1.c']), - MSVSProject.Filter('b', contents=['joe\\b\\bob2.c'])] - """ - if not prefix: prefix = [] - result = [] - excluded_result = [] - folders = OrderedDict() - # Gather files into the final result, excluded, or folders. - for s in sources: - if len(s) == 1: - filename = _NormalizedSource('\\'.join(prefix + s)) - if filename in excluded: - excluded_result.append(filename) - else: - result.append(filename) - 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], - excluded=excluded, - list_excluded=list_excluded, - msvs_version=msvs_version) - contents = MSVSProject.Filter(f, contents=contents) - result.append(contents) - return result - - -def _ToolAppend(tools, tool_name, setting, value, only_if_unset=False): - if not value: return - _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset) - - -def _ToolSetOrAppend(tools, tool_name, setting, value, only_if_unset=False): - # TODO(bradnelson): ugly hack, fix this more generally!!! - if 'Directories' in setting or 'Dependencies' in setting: - if type(value) == str: - value = value.replace('/', '\\') - else: - value = [i.replace('/', '\\') for i in value] - if not tools.get(tool_name): - tools[tool_name] = dict() - tool = tools[tool_name] - if tool.get(setting): - if only_if_unset: return - if type(tool[setting]) == list and type(value) == list: - tool[setting] += value - else: - raise TypeError( - 'Appending "%s" to a non-list setting "%s" for tool "%s" is ' - 'not allowed, previous value: %s' % ( - value, setting, tool_name, str(tool[setting]))) - else: - tool[setting] = value - - -def _ConfigPlatform(config_data): - return config_data.get('msvs_configuration_platform', 'Win32') - - -def _ConfigBaseName(config_name, platform_name): - if config_name.endswith('_' + platform_name): - return config_name[0:-len(platform_name) - 1] - else: - return config_name - - -def _ConfigFullName(config_name, config_data): - platform_name = _ConfigPlatform(config_data) - return '%s|%s' % (_ConfigBaseName(config_name, platform_name), platform_name) - - -def _ConfigWindowsTargetPlatformVersion(config_data): - ver = config_data.get('msvs_windows_target_platform_version') - if not ver or re.match(r'^\d+', ver): - return ver - for key in [r'HKLM\Software\Microsoft\Microsoft SDKs\Windows\%s', - r'HKLM\Software\Wow6432Node\Microsoft\Microsoft SDKs\Windows\%s']: - sdkdir = MSVSVersion._RegistryGetValue(key % ver, 'InstallationFolder') - if not sdkdir: - continue - version = MSVSVersion._RegistryGetValue(key % ver, 'ProductVersion') or '' - # find a matching entry in sdkdir\include - names = sorted([x for x in os.listdir(r'%s\include' % sdkdir) \ - if x.startswith(version)], reverse = True) - return names[0] - - -def _BuildCommandLineForRuleRaw(spec, cmd, cygwin_shell, has_input_path, - quote_cmd, do_setup_env): - - if [x for x in cmd if '$(InputDir)' in x]: - input_dir_preamble = ( - 'set INPUTDIR=$(InputDir)\n' - 'if NOT DEFINED INPUTDIR set INPUTDIR=.\\\n' - 'set INPUTDIR=%INPUTDIR:~0,-1%\n' - ) - else: - input_dir_preamble = '' - - if cygwin_shell: - # Find path to cygwin. - cygwin_dir = _FixPath(spec.get('msvs_cygwin_dirs', ['.'])[0]) - # Prepare command. - direct_cmd = cmd - direct_cmd = [i.replace('$(IntDir)', - '`cygpath -m "${INTDIR}"`') for i in direct_cmd] - direct_cmd = [i.replace('$(OutDir)', - '`cygpath -m "${OUTDIR}"`') for i in direct_cmd] - direct_cmd = [i.replace('$(InputDir)', - '`cygpath -m "${INPUTDIR}"`') for i in direct_cmd] - if has_input_path: - direct_cmd = [i.replace('$(InputPath)', - '`cygpath -m "${INPUTPATH}"`') - for i in direct_cmd] - direct_cmd = ['\\"%s\\"' % i.replace('"', '\\\\\\"') for i in direct_cmd] - # direct_cmd = gyp.common.EncodePOSIXShellList(direct_cmd) - direct_cmd = ' '.join(direct_cmd) - # TODO(quote): regularize quoting path names throughout the module - cmd = '' - if do_setup_env: - cmd += 'call "$(ProjectDir)%(cygwin_dir)s\\setup_env.bat" && ' - cmd += 'set CYGWIN=nontsec&& ' - if direct_cmd.find('NUMBER_OF_PROCESSORS') >= 0: - cmd += 'set /a NUMBER_OF_PROCESSORS_PLUS_1=%%NUMBER_OF_PROCESSORS%%+1&& ' - if direct_cmd.find('INTDIR') >= 0: - cmd += 'set INTDIR=$(IntDir)&& ' - if direct_cmd.find('OUTDIR') >= 0: - cmd += 'set OUTDIR=$(OutDir)&& ' - if has_input_path and direct_cmd.find('INPUTPATH') >= 0: - cmd += 'set INPUTPATH=$(InputPath) && ' - cmd += 'bash -c "%(cmd)s"' - cmd = cmd % {'cygwin_dir': cygwin_dir, - 'cmd': direct_cmd} - return input_dir_preamble + cmd - else: - # Convert cat --> type to mimic unix. - if cmd[0] == 'cat': - command = ['type'] - else: - command = [cmd[0].replace('/', '\\')] - # Add call before command to ensure that commands can be tied together one - # after the other without aborting in Incredibuild, since IB makes a bat - # file out of the raw command string, and some commands (like python) are - # actually batch files themselves. - command.insert(0, 'call') - # Fix the paths - # TODO(quote): This is a really ugly heuristic, and will miss path fixing - # for arguments like "--arg=path" or "/opt:path". - # If the argument starts with a slash or dash, it's probably a command line - # switch - arguments = [i if (i[:1] in "/-") else _FixPath(i) for i in cmd[1:]] - arguments = [i.replace('$(InputDir)', '%INPUTDIR%') for i in arguments] - arguments = [MSVSSettings.FixVCMacroSlashes(i) for i in arguments] - if quote_cmd: - # Support a mode for using cmd directly. - # Convert any paths to native form (first element is used directly). - # TODO(quote): regularize quoting path names throughout the module - arguments = ['"%s"' % i for i in arguments] - # Collapse into a single command. - return input_dir_preamble + ' '.join(command + arguments) - - -def _BuildCommandLineForRule(spec, rule, has_input_path, do_setup_env): - # Currently this weird argument munging is used to duplicate the way a - # python script would need to be run as part of the chrome tree. - # Eventually we should add some sort of rule_default option to set this - # per project. For now the behavior chrome needs is the default. - mcs = rule.get('msvs_cygwin_shell') - if mcs is None: - mcs = int(spec.get('msvs_cygwin_shell', 1)) - elif isinstance(mcs, str): - mcs = int(mcs) - quote_cmd = int(rule.get('msvs_quote_cmd', 1)) - return _BuildCommandLineForRuleRaw(spec, rule['action'], mcs, has_input_path, - quote_cmd, do_setup_env=do_setup_env) - - -def _AddActionStep(actions_dict, inputs, outputs, description, command): - """Merge action into an existing list of actions. - - Care must be taken so that actions which have overlapping inputs either don't - get assigned to the same input, or get collapsed into one. - - Arguments: - actions_dict: dictionary keyed on input name, which maps to a list of - dicts describing the actions attached to that input file. - inputs: list of inputs - outputs: list of outputs - description: description of the action - command: command line to execute - """ - # Require there to be at least one input (call sites will ensure this). - assert inputs - - action = { - 'inputs': inputs, - 'outputs': outputs, - 'description': description, - 'command': command, - } - - # Pick where to stick this action. - # While less than optimal in terms of build time, attach them to the first - # input for now. - chosen_input = inputs[0] - - # Add it there. - if chosen_input not in actions_dict: - actions_dict[chosen_input] = [] - actions_dict[chosen_input].append(action) - - -def _AddCustomBuildToolForMSVS(p, spec, primary_input, - inputs, outputs, description, cmd): - """Add a custom build tool to execute something. - - Arguments: - p: the target project - spec: the target project dict - primary_input: input file to attach the build tool to - inputs: list of inputs - outputs: list of outputs - description: description of the action - cmd: command line to execute - """ - inputs = _FixPaths(inputs) - outputs = _FixPaths(outputs) - tool = MSVSProject.Tool( - 'VCCustomBuildTool', - {'Description': description, - 'AdditionalDependencies': ';'.join(inputs), - 'Outputs': ';'.join(outputs), - 'CommandLine': cmd, - }) - # Add to the properties of primary input for each config. - for config_name, c_data in spec['configurations'].iteritems(): - p.AddFileConfig(_FixPath(primary_input), - _ConfigFullName(config_name, c_data), tools=[tool]) - - -def _AddAccumulatedActionsToMSVS(p, spec, actions_dict): - """Add actions accumulated into an actions_dict, merging as needed. - - Arguments: - p: the target project - spec: the target project dict - actions_dict: dictionary keyed on input name, which maps to a list of - dicts describing the actions attached to that input file. - """ - for primary_input in actions_dict: - inputs = OrderedSet() - outputs = OrderedSet() - descriptions = [] - commands = [] - for action in actions_dict[primary_input]: - 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. - description = ', and also '.join(descriptions) - command = '\r\n'.join(commands) - _AddCustomBuildToolForMSVS(p, spec, - primary_input=primary_input, - inputs=inputs, - outputs=outputs, - description=description, - cmd=command) - - -def _RuleExpandPath(path, input_file): - """Given the input file to which a rule applied, string substitute a path. - - Arguments: - path: a path to string expand - input_file: the file to which the rule applied. - Returns: - The string substituted path. - """ - path = path.replace('$(InputName)', - os.path.splitext(os.path.split(input_file)[1])[0]) - path = path.replace('$(InputDir)', os.path.dirname(input_file)) - path = path.replace('$(InputExt)', - os.path.splitext(os.path.split(input_file)[1])[1]) - path = path.replace('$(InputFileName)', os.path.split(input_file)[1]) - path = path.replace('$(InputPath)', input_file) - return path - - -def _FindRuleTriggerFiles(rule, sources): - """Find the list of files which a particular rule applies to. - - Arguments: - rule: the rule in question - sources: the set of all known source files for this project - Returns: - The list of sources that trigger a particular rule. - """ - return rule.get('rule_sources', []) - - -def _RuleInputsAndOutputs(rule, trigger_file): - """Find the inputs and outputs generated by a rule. - - Arguments: - rule: the rule in question. - trigger_file: the main trigger for this rule. - Returns: - The pair of (inputs, outputs) involved in this rule. - """ - raw_inputs = _FixPaths(rule.get('inputs', [])) - raw_outputs = _FixPaths(rule.get('outputs', [])) - inputs = OrderedSet() - outputs = OrderedSet() - inputs.add(trigger_file) - for i in raw_inputs: - inputs.add(_RuleExpandPath(i, trigger_file)) - for o in raw_outputs: - outputs.add(_RuleExpandPath(o, trigger_file)) - return (inputs, outputs) - - -def _GenerateNativeRulesForMSVS(p, rules, output_dir, spec, options): - """Generate a native rules file. - - Arguments: - p: the target project - rules: the set of rules to include - output_dir: the directory in which the project/gyp resides - spec: the project dict - options: global generator options - """ - rules_filename = '%s%s.rules' % (spec['target_name'], - options.suffix) - rules_file = MSVSToolFile.Writer(os.path.join(output_dir, rules_filename), - spec['target_name']) - # Add each rule. - for r in rules: - rule_name = r['rule_name'] - rule_ext = r['extension'] - inputs = _FixPaths(r.get('inputs', [])) - outputs = _FixPaths(r.get('outputs', [])) - # Skip a rule with no action and no inputs. - if 'action' not in r and not r.get('rule_sources', []): - continue - cmd = _BuildCommandLineForRule(spec, r, has_input_path=True, - do_setup_env=True) - rules_file.AddCustomBuildRule(name=rule_name, - description=r.get('message', rule_name), - extensions=[rule_ext], - additional_dependencies=inputs, - outputs=outputs, - cmd=cmd) - # Write out rules file. - rules_file.WriteIfChanged() - - # Add rules file to project. - p.AddToolFile(rules_filename) - - -def _Cygwinify(path): - path = path.replace('$(OutDir)', '$(OutDirCygwin)') - path = path.replace('$(IntDir)', '$(IntDirCygwin)') - return path - - -def _GenerateExternalRules(rules, output_dir, spec, - sources, options, actions_to_add): - """Generate an external makefile to do a set of rules. - - Arguments: - rules: the list of rules to include - output_dir: path containing project and gyp files - spec: project specification data - sources: set of sources known - options: global generator options - actions_to_add: The list of actions we will add to. - """ - filename = '%s_rules%s.mk' % (spec['target_name'], options.suffix) - mk_file = gyp.common.WriteOnDiff(os.path.join(output_dir, filename)) - # Find cygwin style versions of some paths. - 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 = 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(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]) - # Get the unique output directories for this rule. - output_dirs = [os.path.split(i)[0] for i in outputs] - for od in output_dirs: - all_output_dirs.add(od) - first_outputs_cyg = [_Cygwinify(i) for i in first_outputs] - # Write out all: target, including mkdir for each output directory. - mk_file.write('all: %s\n' % ' '.join(first_outputs_cyg)) - for od in all_output_dirs: - if od: - mk_file.write('\tmkdir -p `cygpath -u "%s"`\n' % od) - mk_file.write('\n') - # Define how each output is generated. - for rule in rules: - trigger_files = _FindRuleTriggerFiles(rule, sources) - for tf in trigger_files: - # Get all the inputs and outputs for this rule for this trigger file. - inputs, outputs = _RuleInputsAndOutputs(rule, tf) - inputs = [_Cygwinify(i) for i in inputs] - outputs = [_Cygwinify(i) for i in outputs] - # Prepare the command line for this rule. - cmd = [_RuleExpandPath(c, tf) for c in rule['action']] - cmd = ['"%s"' % i for i in cmd] - cmd = ' '.join(cmd) - # Add it to the makefile. - mk_file.write('%s: %s\n' % (' '.join(outputs), ' '.join(inputs))) - mk_file.write('\t%s\n\n' % cmd) - # Close up the file. - mk_file.close() - - # Add makefile to list of sources. - sources.add(filename) - # Add a build action to call makefile. - cmd = ['make', - 'OutDir=$(OutDir)', - 'IntDir=$(IntDir)', - '-j', '${NUMBER_OF_PROCESSORS_PLUS_1}', - '-f', filename] - cmd = _BuildCommandLineForRuleRaw(spec, cmd, True, False, True, True) - # Insert makefile as 0'th input, so it gets the action attached there, - # as this is easier to understand from in the IDE. - all_inputs = list(all_inputs) - all_inputs.insert(0, filename) - _AddActionStep(actions_to_add, - inputs=_FixPaths(all_inputs), - outputs=_FixPaths(all_outputs), - description='Running external rules for %s' % - spec['target_name'], - command=cmd) - - -def _EscapeEnvironmentVariableExpansion(s): - """Escapes % characters. - - Escapes any % characters so that Windows-style environment variable - expansions will leave them alone. - See http://connect.microsoft.com/VisualStudio/feedback/details/106127/cl-d-name-text-containing-percentage-characters-doesnt-compile - to understand why we have to do this. - - Args: - s: The string to be escaped. - - Returns: - The escaped string. - """ - s = s.replace('%', '%%') - return s - - -quote_replacer_regex = re.compile(r'(\\*)"') - - -def _EscapeCommandLineArgumentForMSVS(s): - """Escapes a Windows command-line argument. - - So that the Win32 CommandLineToArgv function will turn the escaped result back - into the original string. - See http://msdn.microsoft.com/en-us/library/17w5ykft.aspx - ("Parsing C++ Command-Line Arguments") to understand why we have to do - this. - - Args: - s: the string to be escaped. - Returns: - the escaped string. - """ - - def _Replace(match): - # For a literal quote, CommandLineToArgv requires an odd number of - # backslashes preceding it, and it produces half as many literal backslashes - # (rounded down). So we need to produce 2n+1 backslashes. - return 2 * match.group(1) + '\\"' - - # Escape all quotes so that they are interpreted literally. - s = quote_replacer_regex.sub(_Replace, s) - # Now add unescaped quotes so that any whitespace is interpreted literally. - s = '"' + s + '"' - return s - - -delimiters_replacer_regex = re.compile(r'(\\*)([,;]+)') - - -def _EscapeVCProjCommandLineArgListItem(s): - """Escapes command line arguments for MSVS. - - The VCProj format stores string lists in a single string using commas and - semi-colons as separators, which must be quoted if they are to be - interpreted literally. However, command-line arguments may already have - quotes, and the VCProj parser is ignorant of the backslash escaping - convention used by CommandLineToArgv, so the command-line quotes and the - VCProj quotes may not be the same quotes. So to store a general - command-line argument in a VCProj list, we need to parse the existing - quoting according to VCProj's convention and quote any delimiters that are - not already quoted by that convention. The quotes that we add will also be - seen by CommandLineToArgv, so if backslashes precede them then we also have - to escape those backslashes according to the CommandLineToArgv - convention. - - Args: - s: the string to be escaped. - Returns: - the escaped string. - """ - - def _Replace(match): - # For a non-literal quote, CommandLineToArgv requires an even number of - # backslashes preceding it, and it produces half as many literal - # backslashes. So we need to produce 2n backslashes. - return 2 * match.group(1) + '"' + match.group(2) + '"' - - segments = s.split('"') - # The unquoted segments are at the even-numbered indices. - for i in range(0, len(segments), 2): - segments[i] = delimiters_replacer_regex.sub(_Replace, segments[i]) - # Concatenate back into a single string - s = '"'.join(segments) - if len(segments) % 2 == 0: - # String ends while still quoted according to VCProj's convention. This - # means the delimiter and the next list item that follow this one in the - # .vcproj file will be misinterpreted as part of this item. There is nothing - # we can do about this. Adding an extra quote would correct the problem in - # the VCProj but cause the same problem on the final command-line. Moving - # the item to the end of the list does works, but that's only possible if - # there's only one such item. Let's just warn the user. - print >> sys.stderr, ('Warning: MSVS may misinterpret the odd number of ' + - 'quotes in ' + s) - return s - - -def _EscapeCppDefineForMSVS(s): - """Escapes a CPP define so that it will reach the compiler unaltered.""" - s = _EscapeEnvironmentVariableExpansion(s) - s = _EscapeCommandLineArgumentForMSVS(s) - s = _EscapeVCProjCommandLineArgListItem(s) - # cl.exe replaces literal # characters with = in preprocesor definitions for - # some reason. Octal-encode to work around that. - s = s.replace('#', '\\%03o' % ord('#')) - return s - - -quote_replacer_regex2 = re.compile(r'(\\+)"') - - -def _EscapeCommandLineArgumentForMSBuild(s): - """Escapes a Windows command-line argument for use by MSBuild.""" - - def _Replace(match): - return (len(match.group(1)) / 2 * 4) * '\\' + '\\"' - - # Escape all quotes so that they are interpreted literally. - s = quote_replacer_regex2.sub(_Replace, s) - return s - - -def _EscapeMSBuildSpecialCharacters(s): - escape_dictionary = { - '%': '%25', - '$': '%24', - '@': '%40', - "'": '%27', - ';': '%3B', - '?': '%3F', - '*': '%2A' - } - result = ''.join([escape_dictionary.get(c, c) for c in s]) - return result - - -def _EscapeCppDefineForMSBuild(s): - """Escapes a CPP define so that it will reach the compiler unaltered.""" - s = _EscapeEnvironmentVariableExpansion(s) - s = _EscapeCommandLineArgumentForMSBuild(s) - s = _EscapeMSBuildSpecialCharacters(s) - # cl.exe replaces literal # characters with = in preprocesor definitions for - # some reason. Octal-encode to work around that. - s = s.replace('#', '\\%03o' % ord('#')) - return s - - -def _GenerateRulesForMSVS(p, output_dir, options, spec, - sources, excluded_sources, - actions_to_add): - """Generate all the rules for a particular project. - - Arguments: - p: the project - output_dir: directory to emit rules to - options: global options passed to the generator - spec: the specification for this project - sources: the set of all known source files in this project - excluded_sources: the set of sources excluded from normal processing - actions_to_add: deferred list of actions to add in - """ - rules = spec.get('rules', []) - rules_native = [r for r in rules if not int(r.get('msvs_external_rule', 0))] - rules_external = [r for r in rules if int(r.get('msvs_external_rule', 0))] - - # Handle rules that use a native rules file. - if rules_native: - _GenerateNativeRulesForMSVS(p, rules_native, output_dir, spec, options) - - # Handle external rules (non-native rules). - if rules_external: - _GenerateExternalRules(rules_external, output_dir, spec, - sources, options, actions_to_add) - _AdjustSourcesForRules(rules, sources, excluded_sources, False) - - -def _AdjustSourcesForRules(rules, sources, excluded_sources, is_msbuild): - # Add outputs generated by each rule (if applicable). - for rule in rules: - # Add in the outputs from this rule. - trigger_files = _FindRuleTriggerFiles(rule, sources) - for trigger_file in trigger_files: - # Remove trigger_file from excluded_sources to let the rule be triggered - # (e.g. rule trigger ax_enums.idl is added to excluded_sources - # because it's also in an action's inputs in the same project) - excluded_sources.discard(_FixPath(trigger_file)) - # Done if not processing outputs as sources. - if int(rule.get('process_outputs_as_sources', False)): - inputs, outputs = _RuleInputsAndOutputs(rule, trigger_file) - inputs = OrderedSet(_FixPaths(inputs)) - outputs = OrderedSet(_FixPaths(outputs)) - inputs.remove(_FixPath(trigger_file)) - sources.update(inputs) - if not is_msbuild: - excluded_sources.update(inputs) - sources.update(outputs) - - -def _FilterActionsFromExcluded(excluded_sources, actions_to_add): - """Take inputs with actions attached out of the list of exclusions. - - Arguments: - excluded_sources: list of source files not to be built. - actions_to_add: dict of actions keyed on source file they're attached to. - Returns: - excluded_sources with files that have actions attached removed. - """ - must_keep = OrderedSet(_FixPaths(actions_to_add.keys())) - return [s for s in excluded_sources if s not in must_keep] - - -def _GetDefaultConfiguration(spec): - return spec['configurations'][spec['default_configuration']] - - -def _GetGuidOfProject(proj_path, spec): - """Get the guid for the project. - - Arguments: - proj_path: Path of the vcproj or vcxproj file to generate. - spec: The target dictionary containing the properties of the target. - Returns: - the guid. - Raises: - ValueError: if the specified GUID is invalid. - """ - # Pluck out the default configuration. - default_config = _GetDefaultConfiguration(spec) - # Decide the guid of the project. - guid = default_config.get('msvs_guid') - if guid: - if VALID_MSVS_GUID_CHARS.match(guid) is None: - raise ValueError('Invalid MSVS guid: "%s". Must match regex: "%s".' % - (guid, VALID_MSVS_GUID_CHARS.pattern)) - guid = '{%s}' % guid - guid = guid or MSVSNew.MakeGuid(proj_path) - return guid - - -def _GetMsbuildToolsetOfProject(proj_path, spec, version): - """Get the platform toolset for the project. - - Arguments: - proj_path: Path of the vcproj or vcxproj file to generate. - spec: The target dictionary containing the properties of the target. - version: The MSVSVersion object. - Returns: - the platform toolset string or None. - """ - # Pluck out the default configuration. - default_config = _GetDefaultConfiguration(spec) - toolset = default_config.get('msbuild_toolset') - if not toolset and version.DefaultToolset(): - toolset = version.DefaultToolset() - return toolset - - -def _GenerateProject(project, options, version, generator_flags): - """Generates a vcproj file. - - Arguments: - project: the MSVSProject object. - options: global generator options. - version: the MSVSVersion object. - generator_flags: dict of generator-specific flags. - Returns: - A list of source files that cannot be found on disk. - """ - default_config = _GetDefaultConfiguration(project.spec) - - # Skip emitting anything if told to with msvs_existing_vcproj option. - if default_config.get('msvs_existing_vcproj'): - return [] - - if version.UsesVcxproj(): - return _GenerateMSBuildProject(project, options, version, generator_flags) - else: - return _GenerateMSVSProject(project, options, version, generator_flags) - - -# TODO: Avoid code duplication with _ValidateSourcesForOSX in make.py. -def _ValidateSourcesForMSVSProject(spec, version): - """Makes sure if duplicate basenames are not specified in the source list. - - Arguments: - spec: The target dictionary containing the properties of the target. - version: The VisualStudioVersion object. - """ - # This validation should not be applied to MSVC2010 and later. - assert not version.UsesVcxproj() - - # TODO: Check if MSVC allows this for loadable_module targets. - if spec.get('type', None) not in ('static_library', 'shared_library'): - return - sources = spec.get('sources', []) - basenames = {} - for source in sources: - name, ext = os.path.splitext(source) - is_compiled_file = ext in [ - '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S'] - if not is_compiled_file: - continue - basename = os.path.basename(name) # Don't include extension. - basenames.setdefault(basename, []).append(source) - - error = '' - for basename, files in basenames.iteritems(): - if len(files) > 1: - error += ' %s: %s\n' % (basename, ' '.join(files)) - - if error: - print('static library %s has several files with the same basename:\n' % - spec['target_name'] + error + 'MSVC08 cannot handle that.') - raise GypError('Duplicate basenames in sources section, see list above') - - -def _GenerateMSVSProject(project, options, version, generator_flags): - """Generates a .vcproj file. It may create .rules and .user files too. - - Arguments: - project: The project object we will generate the file for. - options: Global options passed to the generator. - version: The VisualStudioVersion object. - generator_flags: dict of generator-specific flags. - """ - spec = project.spec - gyp.common.EnsureDirExists(project.path) - - platforms = _GetUniquePlatforms(spec) - p = MSVSProject.Writer(project.path, version, spec['target_name'], - project.guid, platforms) - - # Get directory project file is in. - project_dir = os.path.split(project.path)[0] - gyp_path = _NormalizedSource(project.build_file) - relative_path_of_gyp_file = gyp.common.RelativePath(gyp_path, project_dir) - - config_type = _GetMSVSConfigurationType(spec, project.build_file) - for config_name, config in spec['configurations'].iteritems(): - _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config) - - # MSVC08 and prior version cannot handle duplicate basenames in the same - # target. - # TODO: Take excluded sources into consideration if possible. - _ValidateSourcesForMSVSProject(spec, version) - - # Prepare list of sources and excluded sources. - gyp_file = os.path.split(project.build_file)[1] - sources, excluded_sources = _PrepareListOfSources(spec, generator_flags, - gyp_file) - - # Add rules. - actions_to_add = {} - _GenerateRulesForMSVS(p, project_dir, options, spec, - sources, excluded_sources, - 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, version)) - - # Add in files. - missing_sources = _VerifySourcesExist(sources, project_dir) - p.AddFiles(sources) - - _AddToolFilesToMSVS(p, spec) - _HandlePreCompiledHeaders(p, sources, spec) - _AddActions(actions_to_add, spec, relative_path_of_gyp_file) - _AddCopies(actions_to_add, spec) - _WriteMSVSUserFile(project.path, version, spec) - - # NOTE: this stanza must appear after all actions have been decided. - # Don't excluded sources with actions attached, or they won't run. - excluded_sources = _FilterActionsFromExcluded( - excluded_sources, actions_to_add) - _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl, - list_excluded) - _AddAccumulatedActionsToMSVS(p, spec, actions_to_add) - - # Write it out. - p.WriteIfChanged() - - return missing_sources - - -def _GetUniquePlatforms(spec): - """Returns the list of unique platforms for this spec, e.g ['win32', ...]. - - Arguments: - spec: The target dictionary containing the properties of the target. - Returns: - The MSVSUserFile object created. - """ - # Gather list of unique platforms. - platforms = OrderedSet() - for configuration in spec['configurations']: - platforms.add(_ConfigPlatform(spec['configurations'][configuration])) - platforms = list(platforms) - return platforms - - -def _CreateMSVSUserFile(proj_path, version, spec): - """Generates a .user file for the user running this Gyp program. - - Arguments: - proj_path: The path of the project file being created. The .user file - shares the same path (with an appropriate suffix). - version: The VisualStudioVersion object. - spec: The target dictionary containing the properties of the target. - Returns: - The MSVSUserFile object created. - """ - (domain, username) = _GetDomainAndUserName() - vcuser_filename = '.'.join([proj_path, domain, username, 'user']) - user_file = MSVSUserFile.Writer(vcuser_filename, version, - spec['target_name']) - return user_file - - -def _GetMSVSConfigurationType(spec, build_file): - """Returns the configuration type for this project. - - It's a number defined by Microsoft. May raise an exception. - - Args: - spec: The target dictionary containing the properties of the target. - build_file: The path of the gyp file. - Returns: - An integer, the configuration type. - """ - try: - config_type = { - 'executable': '1', # .exe - 'shared_library': '2', # .dll - 'loadable_module': '2', # .dll - 'static_library': '4', # .lib - 'none': '10', # Utility type - }[spec['type']] - except KeyError: - if spec.get('type'): - raise GypError('Target type %s is not a valid target type for ' - 'target %s in %s.' % - (spec['type'], spec['target_name'], build_file)) - else: - raise GypError('Missing type field for target %s in %s.' % - (spec['target_name'], build_file)) - return config_type - - -def _AddConfigurationToMSVSProject(p, spec, config_type, config_name, config): - """Adds a configuration to the MSVS project. - - Many settings in a vcproj file are specific to a configuration. This - function the main part of the vcproj file that's configuration specific. - - Arguments: - p: The target project being generated. - spec: The target dictionary containing the properties of the target. - config_type: The configuration type, a number as defined by Microsoft. - config_name: The name of the configuration. - config: The dictionary that defines the special processing to be done - for this configuration. - """ - # Get the information for this configuration - include_dirs, midl_include_dirs, resource_include_dirs = \ - _GetIncludeDirs(config) - libraries = _GetLibraries(spec) - library_dirs = _GetLibraryDirs(config) - out_file, vc_tool, _ = _GetOutputFilePathAndTool(spec, msbuild=False) - defines = _GetDefines(config) - defines = [_EscapeCppDefineForMSVS(d) for d in defines] - disabled_warnings = _GetDisabledWarnings(config) - prebuild = config.get('msvs_prebuild') - postbuild = config.get('msvs_postbuild') - def_file = _GetModuleDefinition(spec) - precompiled_header = config.get('msvs_precompiled_header') - - # Prepare the list of tools as a dictionary. - tools = dict() - # Add in user specified msvs_settings. - msvs_settings = config.get('msvs_settings', {}) - MSVSSettings.ValidateMSVSSettings(msvs_settings) - - # Prevent default library inheritance from the environment. - _ToolAppend(tools, 'VCLinkerTool', 'AdditionalDependencies', ['$(NOINHERIT)']) - - for tool in msvs_settings: - settings = config['msvs_settings'][tool] - for setting in settings: - _ToolAppend(tools, tool, setting, settings[setting]) - # Add the information to the appropriate tool - _ToolAppend(tools, 'VCCLCompilerTool', - 'AdditionalIncludeDirectories', include_dirs) - _ToolAppend(tools, 'VCMIDLTool', - 'AdditionalIncludeDirectories', midl_include_dirs) - _ToolAppend(tools, 'VCResourceCompilerTool', - 'AdditionalIncludeDirectories', resource_include_dirs) - # Add in libraries. - _ToolAppend(tools, 'VCLinkerTool', 'AdditionalDependencies', libraries) - _ToolAppend(tools, 'VCLinkerTool', 'AdditionalLibraryDirectories', - library_dirs) - if out_file: - _ToolAppend(tools, vc_tool, 'OutputFile', out_file, only_if_unset=True) - # Add defines. - _ToolAppend(tools, 'VCCLCompilerTool', 'PreprocessorDefinitions', defines) - _ToolAppend(tools, 'VCResourceCompilerTool', 'PreprocessorDefinitions', - defines) - # Change program database directory to prevent collisions. - _ToolAppend(tools, 'VCCLCompilerTool', 'ProgramDataBaseFileName', - '$(IntDir)$(ProjectName)\\vc80.pdb', only_if_unset=True) - # Add disabled warnings. - _ToolAppend(tools, 'VCCLCompilerTool', - 'DisableSpecificWarnings', disabled_warnings) - # Add Pre-build. - _ToolAppend(tools, 'VCPreBuildEventTool', 'CommandLine', prebuild) - # Add Post-build. - _ToolAppend(tools, 'VCPostBuildEventTool', 'CommandLine', postbuild) - # Turn on precompiled headers if appropriate. - if precompiled_header: - precompiled_header = os.path.split(precompiled_header)[1] - _ToolAppend(tools, 'VCCLCompilerTool', 'UsePrecompiledHeader', '2') - _ToolAppend(tools, 'VCCLCompilerTool', - 'PrecompiledHeaderThrough', precompiled_header) - _ToolAppend(tools, 'VCCLCompilerTool', - 'ForcedIncludeFiles', precompiled_header) - # Loadable modules don't generate import libraries; - # tell dependent projects to not expect one. - if spec['type'] == 'loadable_module': - _ToolAppend(tools, 'VCLinkerTool', 'IgnoreImportLibrary', 'true') - # Set the module definition file if any. - if def_file: - _ToolAppend(tools, 'VCLinkerTool', 'ModuleDefinitionFile', def_file) - - _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name) - - -def _GetIncludeDirs(config): - """Returns the list of directories to be used for #include directives. - - Arguments: - config: The dictionary that defines the special processing to be done - for this configuration. - Returns: - The list of directory paths. - """ - # TODO(bradnelson): include_dirs should really be flexible enough not to - # require this sort of thing. - include_dirs = ( - config.get('include_dirs', []) + - config.get('msvs_system_include_dirs', [])) - midl_include_dirs = ( - config.get('midl_include_dirs', []) + - config.get('msvs_system_include_dirs', [])) - resource_include_dirs = config.get('resource_include_dirs', include_dirs) - include_dirs = _FixPaths(include_dirs) - midl_include_dirs = _FixPaths(midl_include_dirs) - resource_include_dirs = _FixPaths(resource_include_dirs) - return include_dirs, midl_include_dirs, resource_include_dirs - - -def _GetLibraryDirs(config): - """Returns the list of directories to be used for library search paths. - - Arguments: - config: The dictionary that defines the special processing to be done - for this configuration. - Returns: - The list of directory paths. - """ - - library_dirs = config.get('library_dirs', []) - library_dirs = _FixPaths(library_dirs) - return library_dirs - - -def _GetLibraries(spec): - """Returns the list of libraries for this configuration. - - Arguments: - spec: The target dictionary containing the properties of the target. - Returns: - The list of directory paths. - """ - libraries = spec.get('libraries', []) - # Strip out -l, as it is not used on windows (but is needed so we can pass - # 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 = OrderedSet() - unique_libraries_list = [] - for entry in reversed(libraries): - library = re.sub(r'^\-l', '', entry) - if not os.path.splitext(library)[1]: - library += '.lib' - if library not in found: - found.add(library) - unique_libraries_list.append(library) - unique_libraries_list.reverse() - return unique_libraries_list - - -def _GetOutputFilePathAndTool(spec, msbuild): - """Returns the path and tool to use for this target. - - Figures out the path of the file this spec will create and the name of - the VC tool that will create it. - - Arguments: - spec: The target dictionary containing the properties of the target. - Returns: - A triple of (file path, name of the vc tool, name of the msbuild tool) - """ - # Select a name for the output file. - out_file = '' - vc_tool = '' - msbuild_tool = '' - output_file_map = { - 'executable': ('VCLinkerTool', 'Link', '$(OutDir)', '.exe'), - 'shared_library': ('VCLinkerTool', 'Link', '$(OutDir)', '.dll'), - 'loadable_module': ('VCLinkerTool', 'Link', '$(OutDir)', '.dll'), - 'static_library': ('VCLibrarianTool', 'Lib', '$(OutDir)lib\\', '.lib'), - } - output_file_props = output_file_map.get(spec['type']) - if output_file_props and int(spec.get('msvs_auto_output_file', 1)): - vc_tool, msbuild_tool, out_dir, suffix = output_file_props - if spec.get('standalone_static_library', 0): - out_dir = '$(OutDir)' - out_dir = spec.get('product_dir', out_dir) - product_extension = spec.get('product_extension') - if product_extension: - suffix = '.' + product_extension - elif msbuild: - suffix = '$(TargetExt)' - prefix = spec.get('product_prefix', '') - product_name = spec.get('product_name', '$(ProjectName)') - out_file = ntpath.join(out_dir, prefix + product_name + suffix) - return out_file, vc_tool, msbuild_tool - - -def _GetOutputTargetExt(spec): - """Returns the extension for this target, including the dot - - If product_extension is specified, set target_extension to this to avoid - MSB8012, returns None otherwise. Ignores any target_extension settings in - the input files. - - Arguments: - spec: The target dictionary containing the properties of the target. - Returns: - A string with the extension, or None - """ - target_extension = spec.get('product_extension') - if target_extension: - return '.' + target_extension - return None - - -def _GetDefines(config): - """Returns the list of preprocessor definitions for this configuation. - - Arguments: - config: The dictionary that defines the special processing to be done - for this configuration. - Returns: - The list of preprocessor definitions. - """ - defines = [] - for d in config.get('defines', []): - if type(d) == list: - fd = '='.join([str(dpart) for dpart in d]) - else: - fd = str(d) - defines.append(fd) - return defines - - -def _GetDisabledWarnings(config): - return [str(i) for i in config.get('msvs_disabled_warnings', [])] - - -def _GetModuleDefinition(spec): - def_file = '' - if spec['type'] in ['shared_library', 'loadable_module', 'executable']: - def_files = [s for s in spec.get('sources', []) if s.endswith('.def')] - if len(def_files) == 1: - def_file = _FixPath(def_files[0]) - elif def_files: - raise ValueError( - 'Multiple module definition files in one target, target %s lists ' - 'multiple .def files: %s' % ( - spec['target_name'], ' '.join(def_files))) - return def_file - - -def _ConvertToolsToExpectedForm(tools): - """Convert tools to a form expected by Visual Studio. - - Arguments: - tools: A dictionary of settings; the tool name is the key. - Returns: - A list of Tool objects. - """ - tool_list = [] - for tool, settings in tools.iteritems(): - # Collapse settings with lists. - settings_fixed = {} - for setting, value in settings.iteritems(): - if type(value) == list: - if ((tool == 'VCLinkerTool' and - setting == 'AdditionalDependencies') or - setting == 'AdditionalOptions'): - settings_fixed[setting] = ' '.join(value) - else: - settings_fixed[setting] = ';'.join(value) - else: - settings_fixed[setting] = value - # Add in this tool. - tool_list.append(MSVSProject.Tool(tool, settings_fixed)) - return tool_list - - -def _AddConfigurationToMSVS(p, spec, tools, config, config_type, config_name): - """Add to the project file the configuration specified by config. - - Arguments: - p: The target project being generated. - spec: the target project dict. - tools: A dictionary of settings; the tool name is the key. - config: The dictionary that defines the special processing to be done - for this configuration. - config_type: The configuration type, a number as defined by Microsoft. - config_name: The name of the configuration. - """ - attributes = _GetMSVSAttributes(spec, config, config_type) - # Add in this configuration. - tool_list = _ConvertToolsToExpectedForm(tools) - p.AddConfig(_ConfigFullName(config_name, config), - attrs=attributes, tools=tool_list) - - -def _GetMSVSAttributes(spec, config, config_type): - # Prepare configuration attributes. - prepared_attrs = {} - source_attrs = config.get('msvs_configuration_attributes', {}) - for a in source_attrs: - prepared_attrs[a] = source_attrs[a] - # Add props files. - vsprops_dirs = config.get('msvs_props', []) - vsprops_dirs = _FixPaths(vsprops_dirs) - if vsprops_dirs: - prepared_attrs['InheritedPropertySheets'] = ';'.join(vsprops_dirs) - # Set configuration type. - prepared_attrs['ConfigurationType'] = config_type - output_dir = prepared_attrs.get('OutputDirectory', - '$(SolutionDir)$(ConfigurationName)') - prepared_attrs['OutputDirectory'] = _FixPath(output_dir) + '\\' - if 'IntermediateDirectory' not in prepared_attrs: - intermediate = '$(ConfigurationName)\\obj\\$(ProjectName)' - prepared_attrs['IntermediateDirectory'] = _FixPath(intermediate) + '\\' - else: - intermediate = _FixPath(prepared_attrs['IntermediateDirectory']) + '\\' - intermediate = MSVSSettings.FixVCMacroSlashes(intermediate) - prepared_attrs['IntermediateDirectory'] = intermediate - return prepared_attrs - - -def _AddNormalizedSources(sources_set, sources_array): - sources_set.update(_NormalizedSource(s) for s in sources_array) - - -def _PrepareListOfSources(spec, generator_flags, gyp_file): - """Prepare list of sources and excluded sources. - - Besides the sources specified directly in the spec, adds the gyp file so - that a change to it will cause a re-compile. Also adds appropriate sources - for actions and copies. Assumes later stage will un-exclude files which - have custom build steps attached. - - Arguments: - spec: The target dictionary containing the properties of the target. - gyp_file: The name of the gyp file. - Returns: - A pair of (list of sources, list of excluded sources). - The sources will be relative to the gyp file. - """ - sources = OrderedSet() - _AddNormalizedSources(sources, spec.get('sources', [])) - excluded_sources = OrderedSet() - # Add in the gyp file. - if not generator_flags.get('standalone'): - sources.add(gyp_file) - - # Add in 'action' inputs and outputs. - for a in spec.get('actions', []): - inputs = a['inputs'] - inputs = [_NormalizedSource(i) for i in inputs] - # Add all inputs to sources and excluded sources. - inputs = OrderedSet(inputs) - sources.update(inputs) - if not spec.get('msvs_external_builder'): - excluded_sources.update(inputs) - if int(a.get('process_outputs_as_sources', False)): - _AddNormalizedSources(sources, a.get('outputs', [])) - # Add in 'copies' inputs and outputs. - for cpy in spec.get('copies', []): - _AddNormalizedSources(sources, cpy.get('files', [])) - return (sources, excluded_sources) - - -def _AdjustSourcesAndConvertToFilterHierarchy( - spec, options, gyp_dir, sources, excluded_sources, list_excluded, version): - """Adjusts the list of sources and excluded sources. - - Also converts the sets to lists. - - Arguments: - spec: The target dictionary containing the properties of the target. - options: Global generator options. - 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(OrderedSet(spec.get('sources_excluded', []))) - # Add excluded sources into sources for good measure. - sources.update(excluded_sources) - # Convert to proper windows form. - # NOTE: sources goes from being a set to a list here. - # NOTE: excluded_sources goes from being a set to a list here. - sources = _FixPaths(sources) - # Convert to proper windows form. - excluded_sources = _FixPaths(excluded_sources) - - excluded_idl = _IdlFilesHandledNonNatively(spec, sources) - - precompiled_related = _GetPrecompileRelatedFiles(spec) - # Find the excluded ones, minus the precompiled header related ones. - fully_excluded = [i for i in excluded_sources if i not in precompiled_related] - - # Convert to folders and the right slashes. - sources = [i.split('\\') for i in sources] - sources = _ConvertSourcesToFilterHierarchy(sources, excluded=fully_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. - if version.UsesVcxproj(): - while all([isinstance(s, MSVSProject.Filter) for s in sources]) \ - and len(set([s.name for s in sources])) == 1: - assert all([len(s.contents) == 1 for s in sources]) - sources = [s.contents[0] for s in sources] - else: - while len(sources) == 1 and isinstance(sources[0], MSVSProject.Filter): - sources = sources[0].contents - - return sources, excluded_sources, excluded_idl - - -def _IdlFilesHandledNonNatively(spec, sources): - # If any non-native rules use 'idl' as an extension exclude idl files. - # Gather a list here to use later. - using_idl = False - for rule in spec.get('rules', []): - if rule['extension'] == 'idl' and int(rule.get('msvs_external_rule', 0)): - using_idl = True - break - if using_idl: - excluded_idl = [i for i in sources if i.endswith('.idl')] - else: - excluded_idl = [] - return excluded_idl - - -def _GetPrecompileRelatedFiles(spec): - # Gather a list of precompiled header related sources. - precompiled_related = [] - for _, config in spec['configurations'].iteritems(): - for k in precomp_keys: - f = config.get(k) - if f: - precompiled_related.append(_FixPath(f)) - return precompiled_related - - -def _ExcludeFilesFromBeingBuilt(p, spec, excluded_sources, excluded_idl, - list_excluded): - exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl) - for file_name, excluded_configs in exclusions.iteritems(): - if (not list_excluded and - len(excluded_configs) == len(spec['configurations'])): - # If we're not listing excluded files, then they won't appear in the - # project, so don't try to configure them to be excluded. - pass - else: - for config_name, config in excluded_configs: - p.AddFileConfig(file_name, _ConfigFullName(config_name, config), - {'ExcludedFromBuild': 'true'}) - - -def _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl): - exclusions = {} - # Exclude excluded sources from being built. - for f in excluded_sources: - excluded_configs = [] - for config_name, config in spec['configurations'].iteritems(): - precomped = [_FixPath(config.get(i, '')) for i in precomp_keys] - # Don't do this for ones that are precompiled header related. - if f not in precomped: - excluded_configs.append((config_name, config)) - exclusions[f] = excluded_configs - # If any non-native rules use 'idl' as an extension exclude idl files. - # Exclude them now. - for f in excluded_idl: - excluded_configs = [] - for config_name, config in spec['configurations'].iteritems(): - excluded_configs.append((config_name, config)) - exclusions[f] = excluded_configs - return exclusions - - -def _AddToolFilesToMSVS(p, spec): - # Add in tool files (rules). - tool_files = OrderedSet() - for _, config in spec['configurations'].iteritems(): - for f in config.get('msvs_tool_files', []): - tool_files.add(f) - for f in tool_files: - p.AddToolFile(f) - - -def _HandlePreCompiledHeaders(p, sources, spec): - # Pre-compiled header source stubs need a different compiler flag - # (generate precompiled header) and any source file not of the same - # kind (i.e. C vs. C++) as the precompiled header source stub needs - # to have use of precompiled headers disabled. - extensions_excluded_from_precompile = [] - for config_name, config in spec['configurations'].iteritems(): - source = config.get('msvs_precompiled_source') - if source: - source = _FixPath(source) - # UsePrecompiledHeader=1 for if using precompiled headers. - tool = MSVSProject.Tool('VCCLCompilerTool', - {'UsePrecompiledHeader': '1'}) - p.AddFileConfig(source, _ConfigFullName(config_name, config), - {}, tools=[tool]) - basename, extension = os.path.splitext(source) - if extension == '.c': - extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx'] - else: - extensions_excluded_from_precompile = ['.c'] - def DisableForSourceTree(source_tree): - for source in source_tree: - if isinstance(source, MSVSProject.Filter): - DisableForSourceTree(source.contents) - else: - basename, extension = os.path.splitext(source) - if extension in extensions_excluded_from_precompile: - for config_name, config in spec['configurations'].iteritems(): - tool = MSVSProject.Tool('VCCLCompilerTool', - {'UsePrecompiledHeader': '0', - 'ForcedIncludeFiles': '$(NOINHERIT)'}) - p.AddFileConfig(_FixPath(source), - _ConfigFullName(config_name, config), - {}, tools=[tool]) - # Do nothing if there was no precompiled source. - if extensions_excluded_from_precompile: - DisableForSourceTree(sources) - - -def _AddActions(actions_to_add, spec, relative_path_of_gyp_file): - # Add actions. - actions = spec.get('actions', []) - # Don't setup_env every time. When all the actions are run together in one - # batch file in VS, the PATH will grow too long. - # Membership in this set means that the cygwin environment has been set up, - # and does not need to be set up again. - have_setup_env = set() - for a in actions: - # Attach actions to the gyp file if nothing else is there. - inputs = a.get('inputs') or [relative_path_of_gyp_file] - attached_to = inputs[0] - need_setup_env = attached_to not in have_setup_env - cmd = _BuildCommandLineForRule(spec, a, has_input_path=False, - do_setup_env=need_setup_env) - have_setup_env.add(attached_to) - # Add the action. - _AddActionStep(actions_to_add, - inputs=inputs, - outputs=a.get('outputs', []), - description=a.get('message', a['action_name']), - command=cmd) - - -def _WriteMSVSUserFile(project_path, version, spec): - # Add run_as and test targets. - if 'run_as' in spec: - run_as = spec['run_as'] - action = run_as.get('action', []) - environment = run_as.get('environment', []) - working_directory = run_as.get('working_directory', '.') - elif int(spec.get('test', 0)): - action = ['$(TargetPath)', '--gtest_print_time'] - environment = [] - working_directory = '.' - else: - return # Nothing to add - # Write out the user file. - user_file = _CreateMSVSUserFile(project_path, version, spec) - for config_name, c_data in spec['configurations'].iteritems(): - user_file.AddDebugSettings(_ConfigFullName(config_name, c_data), - action, environment, working_directory) - user_file.WriteIfChanged() - - -def _AddCopies(actions_to_add, spec): - copies = _GetCopies(spec) - for inputs, outputs, cmd, description in copies: - _AddActionStep(actions_to_add, inputs=inputs, outputs=outputs, - description=description, command=cmd) - - -def _GetCopies(spec): - copies = [] - # Add copies. - for cpy in spec.get('copies', []): - for src in cpy.get('files', []): - dst = os.path.join(cpy['destination'], os.path.basename(src)) - # _AddCustomBuildToolForMSVS() will call _FixPath() on the inputs and - # outputs, so do the same for our generated command line. - if src.endswith('/'): - src_bare = src[:-1] - base_dir = posixpath.split(src_bare)[0] - outer_dir = posixpath.split(src_bare)[1] - cmd = 'cd "%s" && xcopy /e /f /y "%s" "%s\\%s\\"' % ( - _FixPath(base_dir), outer_dir, _FixPath(dst), outer_dir) - copies.append(([src], ['dummy_copies', dst], cmd, - 'Copying %s to %s' % (src, dst))) - else: - cmd = 'mkdir "%s" 2>nul & set ERRORLEVEL=0 & copy /Y "%s" "%s"' % ( - _FixPath(cpy['destination']), _FixPath(src), _FixPath(dst)) - copies.append(([src], [dst], cmd, 'Copying %s to %s' % (src, dst))) - return copies - - -def _GetPathDict(root, path): - # |path| will eventually be empty (in the recursive calls) if it was initially - # relative; otherwise it will eventually end up as '\', 'D:\', etc. - if not path or path.endswith(os.sep): - return root - parent, folder = os.path.split(path) - parent_dict = _GetPathDict(root, parent) - if folder not in parent_dict: - parent_dict[folder] = dict() - return parent_dict[folder] - - -def _DictsToFolders(base_path, bucket, flat): - # Convert to folders recursively. - children = [] - for folder, contents in bucket.iteritems(): - if type(contents) == dict: - folder_children = _DictsToFolders(os.path.join(base_path, folder), - contents, flat) - if flat: - children += folder_children - else: - folder_children = MSVSNew.MSVSFolder(os.path.join(base_path, folder), - name='(' + folder + ')', - entries=folder_children) - children.append(folder_children) - else: - children.append(contents) - return children - - -def _CollapseSingles(parent, node): - # Recursively explorer the tree of dicts looking for projects which are - # the sole item in a folder which has the same name as the project. Bring - # such projects up one level. - if (type(node) == dict and - len(node) == 1 and - node.keys()[0] == parent + '.vcproj'): - return node[node.keys()[0]] - if type(node) != dict: - return node - for child in node: - node[child] = _CollapseSingles(child, node[child]) - return node - - -def _GatherSolutionFolders(sln_projects, project_objects, flat): - root = {} - # Convert into a tree of dicts on path. - for p in sln_projects: - gyp_file, target = gyp.common.ParseQualifiedTarget(p)[0:2] - gyp_dir = os.path.dirname(gyp_file) - path_dict = _GetPathDict(root, gyp_dir) - path_dict[target + '.vcproj'] = project_objects[p] - # Walk down from the top until we hit a folder that has more than one entry. - # In practice, this strips the top-level "src/" dir from the hierarchy in - # the solution. - while len(root) == 1 and type(root[root.keys()[0]]) == dict: - root = root[root.keys()[0]] - # Collapse singles. - root = _CollapseSingles('', root) - # Merge buckets until everything is a root entry. - return _DictsToFolders('', root, flat) - - -def _GetPathOfProject(qualified_target, spec, options, msvs_version): - default_config = _GetDefaultConfiguration(spec) - proj_filename = default_config.get('msvs_existing_vcproj') - if not proj_filename: - proj_filename = (spec['target_name'] + options.suffix + - msvs_version.ProjectExtension()) - - build_file = gyp.common.BuildFile(qualified_target) - proj_path = os.path.join(os.path.dirname(build_file), proj_filename) - fix_prefix = None - if options.generator_output: - project_dir_path = os.path.dirname(os.path.abspath(proj_path)) - proj_path = os.path.join(options.generator_output, proj_path) - fix_prefix = gyp.common.RelativePath(project_dir_path, - os.path.dirname(proj_path)) - return proj_path, fix_prefix - - -def _GetPlatformOverridesOfProject(spec): - # Prepare a dict indicating which project configurations are used for which - # solution configurations for this target. - config_platform_overrides = {} - for config_name, c in spec['configurations'].iteritems(): - config_fullname = _ConfigFullName(config_name, c) - platform = c.get('msvs_target_platform', _ConfigPlatform(c)) - fixed_config_fullname = '%s|%s' % ( - _ConfigBaseName(config_name, _ConfigPlatform(c)), platform) - config_platform_overrides[config_fullname] = fixed_config_fullname - return config_platform_overrides - - -def _CreateProjectObjects(target_list, target_dicts, options, msvs_version): - """Create a MSVSProject object for the targets found in target list. - - Arguments: - target_list: the list of targets to generate project objects for. - target_dicts: the dictionary of specifications. - options: global generator options. - msvs_version: the MSVSVersion object. - Returns: - A set of created projects, keyed by target. - """ - global fixpath_prefix - # Generate each project. - projects = {} - for qualified_target in target_list: - spec = target_dicts[qualified_target] - if spec['toolset'] != 'target': - raise GypError( - 'Multiple toolsets not supported in msvs build (target %s)' % - qualified_target) - proj_path, fixpath_prefix = _GetPathOfProject(qualified_target, spec, - options, msvs_version) - guid = _GetGuidOfProject(proj_path, spec) - overrides = _GetPlatformOverridesOfProject(spec) - build_file = gyp.common.BuildFile(qualified_target) - # Create object for this project. - obj = MSVSNew.MSVSProject( - proj_path, - name=spec['target_name'], - guid=guid, - spec=spec, - build_file=build_file, - config_platform_overrides=overrides, - fixpath_prefix=fixpath_prefix) - # Set project toolset if any (MS build only) - if msvs_version.UsesVcxproj(): - obj.set_msbuild_toolset( - _GetMsbuildToolsetOfProject(proj_path, spec, msvs_version)) - projects[qualified_target] = obj - # Set all the dependencies, but not if we are using an external builder like - # ninja - for project in projects.values(): - if not project.spec.get('msvs_external_builder'): - deps = project.spec.get('dependencies', []) - deps = [projects[d] for d in deps] - project.set_dependencies(deps) - return projects - - -def _InitNinjaFlavor(params, target_list, target_dicts): - """Initialize targets for the ninja flavor. - - This sets up the necessary variables in the targets to generate msvs projects - that use ninja as an external builder. The variables in the spec are only set - if they have not been set. This allows individual specs to override the - default values initialized here. - Arguments: - params: Params provided to the generator. - target_list: List of target pairs: 'base/base.gyp:base'. - target_dicts: Dict of target properties keyed on target pair. - """ - for qualified_target in target_list: - spec = target_dicts[qualified_target] - if spec.get('msvs_external_builder'): - # The spec explicitly defined an external builder, so don't change it. - continue - - path_to_ninja = spec.get('msvs_path_to_ninja', 'ninja.exe') - - spec['msvs_external_builder'] = 'ninja' - if not spec.get('msvs_external_builder_out_dir'): - gyp_file, _, _ = gyp.common.ParseQualifiedTarget(qualified_target) - gyp_dir = os.path.dirname(gyp_file) - configuration = '$(Configuration)' - if params.get('target_arch') == 'x64': - configuration += '_x64' - spec['msvs_external_builder_out_dir'] = os.path.join( - gyp.common.RelativePath(params['options'].toplevel_dir, gyp_dir), - ninja_generator.ComputeOutputDir(params), - configuration) - if not spec.get('msvs_external_builder_build_cmd'): - spec['msvs_external_builder_build_cmd'] = [ - path_to_ninja, - '-C', - '$(OutDir)', - '$(ProjectName)', - ] - if not spec.get('msvs_external_builder_clean_cmd'): - spec['msvs_external_builder_clean_cmd'] = [ - path_to_ninja, - '-C', - '$(OutDir)', - '-tclean', - '$(ProjectName)', - ] - - -def CalculateVariables(default_variables, params): - """Generated variables that require params to be known.""" - - generator_flags = params.get('generator_flags', {}) - - # Select project file format version (if unset, default to auto detecting). - msvs_version = MSVSVersion.SelectVisualStudioVersion( - generator_flags.get('msvs_version', 'auto')) - # Stash msvs_version for later (so we don't have to probe the system twice). - params['msvs_version'] = msvs_version - - # Set a variable so conditions can be based on msvs_version. - default_variables['MSVS_VERSION'] = msvs_version.ShortName() - - # To determine processor word size on Windows, in addition to checking - # PROCESSOR_ARCHITECTURE (which reflects the word size of the current - # process), it is also necessary to check PROCESSOR_ARCITEW6432 (which - # contains the actual word size of the system when running thru WOW64). - if (os.environ.get('PROCESSOR_ARCHITECTURE', '').find('64') >= 0 or - os.environ.get('PROCESSOR_ARCHITEW6432', '').find('64') >= 0): - default_variables['MSVS_OS_BITS'] = 64 - else: - default_variables['MSVS_OS_BITS'] = 32 - - if gyp.common.GetFlavor(params) == 'ninja': - default_variables['SHARED_INTERMEDIATE_DIR'] = '$(OutDir)gen' - - -def PerformBuild(data, configurations, params): - options = params['options'] - msvs_version = params['msvs_version'] - devenv = os.path.join(msvs_version.path, 'Common7', 'IDE', 'devenv.com') - - for build_file, build_file_dict in data.iteritems(): - (build_file_root, build_file_ext) = os.path.splitext(build_file) - if build_file_ext != '.gyp': - continue - sln_path = build_file_root + options.suffix + '.sln' - if options.generator_output: - sln_path = os.path.join(options.generator_output, sln_path) - - for config in configurations: - arguments = [devenv, sln_path, '/Build', config] - print 'Building [%s]: %s' % (config, arguments) - rtn = subprocess.check_call(arguments) - - -def GenerateOutput(target_list, target_dicts, data, params): - """Generate .sln and .vcproj files. - - This is the entry point for this generator. - Arguments: - target_list: List of target pairs: 'base/base.gyp:base'. - target_dicts: Dict of target properties keyed on target pair. - data: Dictionary containing per .gyp data. - """ - global fixpath_prefix - - options = params['options'] - - # Get the project file format version back out of where we stashed it in - # GeneratorCalculatedVariables. - msvs_version = params['msvs_version'] - - generator_flags = params.get('generator_flags', {}) - - # Optionally shard targets marked with 'msvs_shard': SHARD_COUNT. - (target_list, target_dicts) = MSVSUtil.ShardTargets(target_list, target_dicts) - - # Optionally use the large PDB workaround for targets marked with - # 'msvs_large_pdb': 1. - (target_list, target_dicts) = MSVSUtil.InsertLargePdbShims( - target_list, target_dicts, generator_default_variables) - - # Optionally configure each spec to use ninja as the external builder. - if params.get('flavor') == 'ninja': - _InitNinjaFlavor(params, target_list, target_dicts) - - # Prepare the set of configurations. - configs = set() - for qualified_target in target_list: - spec = target_dicts[qualified_target] - for config_name, config in spec['configurations'].iteritems(): - configs.add(_ConfigFullName(config_name, config)) - configs = list(configs) - - # Figure out all the projects that will be generated and their guids - project_objects = _CreateProjectObjects(target_list, target_dicts, options, - msvs_version) - - # Generate each project. - missing_sources = [] - for project in project_objects.values(): - fixpath_prefix = project.fixpath_prefix - missing_sources.extend(_GenerateProject(project, options, msvs_version, - generator_flags)) - fixpath_prefix = None - - for build_file in data: - # Validate build_file extension - if not build_file.endswith('.gyp'): - continue - sln_path = os.path.splitext(build_file)[0] + options.suffix + '.sln' - if options.generator_output: - sln_path = os.path.join(options.generator_output, sln_path) - # Get projects in the solution, and their dependents. - sln_projects = gyp.common.BuildFileTargets(target_list, build_file) - sln_projects += gyp.common.DeepDependencyTargets(target_dicts, sln_projects) - # Create folder hierarchy. - root_entries = _GatherSolutionFolders( - sln_projects, project_objects, flat=msvs_version.FlatSolution()) - # Create solution. - sln = MSVSNew.MSVSSolution(sln_path, - entries=root_entries, - variants=configs, - websiteProperties=False, - version=msvs_version) - sln.Write() - - if missing_sources: - error_message = "Missing input files:\n" + \ - '\n'.join(set(missing_sources)) - if generator_flags.get('msvs_error_on_missing_sources', False): - raise GypError(error_message) - else: - print >> sys.stdout, "Warning: " + error_message - - -def _GenerateMSBuildFiltersFile(filters_path, source_files, - rule_dependencies, extension_to_rule_name): - """Generate the filters file. - - This file is used by Visual Studio to organize the presentation of source - files into folders. - - Arguments: - filters_path: The path of the file to be created. - source_files: The hierarchical structure of all the sources. - extension_to_rule_name: A dictionary mapping file extensions to rules. - """ - filter_group = [] - source_group = [] - _AppendFiltersForMSBuild('', source_files, rule_dependencies, - extension_to_rule_name, filter_group, source_group) - if filter_group: - content = ['Project', - {'ToolsVersion': '4.0', - 'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003' - }, - ['ItemGroup'] + filter_group, - ['ItemGroup'] + source_group - ] - easy_xml.WriteXmlIfChanged(content, filters_path, pretty=True, win32=True) - elif os.path.exists(filters_path): - # We don't need this filter anymore. Delete the old filter file. - os.unlink(filters_path) - - -def _AppendFiltersForMSBuild(parent_filter_name, sources, rule_dependencies, - extension_to_rule_name, - filter_group, source_group): - """Creates the list of filters and sources to be added in the filter file. - - Args: - parent_filter_name: The name of the filter under which the sources are - found. - sources: The hierarchy of filters and sources to process. - extension_to_rule_name: A dictionary mapping file extensions to rules. - filter_group: The list to which filter entries will be appended. - source_group: The list to which source entries will be appeneded. - """ - for source in sources: - if isinstance(source, MSVSProject.Filter): - # We have a sub-filter. Create the name of that sub-filter. - if not parent_filter_name: - filter_name = source.name - else: - filter_name = '%s\\%s' % (parent_filter_name, source.name) - # Add the filter to the group. - filter_group.append( - ['Filter', {'Include': filter_name}, - ['UniqueIdentifier', MSVSNew.MakeGuid(source.name)]]) - # Recurse and add its dependents. - _AppendFiltersForMSBuild(filter_name, source.contents, - rule_dependencies, extension_to_rule_name, - filter_group, source_group) - else: - # It's a source. Create a source entry. - _, element = _MapFileToMsBuildSourceType(source, rule_dependencies, - extension_to_rule_name) - source_entry = [element, {'Include': source}] - # Specify the filter it is part of, if any. - if parent_filter_name: - source_entry.append(['Filter', parent_filter_name]) - source_group.append(source_entry) - - -def _MapFileToMsBuildSourceType(source, rule_dependencies, - extension_to_rule_name): - """Returns the group and element type of the source file. - - Arguments: - source: The source file name. - extension_to_rule_name: A dictionary mapping file extensions to rules. - - Returns: - A pair of (group this file should be part of, the label of element) - """ - _, ext = os.path.splitext(source) - if ext in extension_to_rule_name: - group = 'rule' - element = extension_to_rule_name[ext] - elif ext in ['.cc', '.cpp', '.c', '.cxx', '.mm']: - group = 'compile' - element = 'ClCompile' - elif ext in ['.h', '.hxx']: - group = 'include' - element = 'ClInclude' - elif ext == '.rc': - group = 'resource' - element = 'ResourceCompile' - elif ext == '.asm': - group = 'masm' - element = 'MASM' - elif ext == '.idl': - group = 'midl' - element = 'Midl' - elif source in rule_dependencies: - group = 'rule_dependency' - element = 'CustomBuild' - else: - group = 'none' - element = 'None' - return (group, element) - - -def _GenerateRulesForMSBuild(output_dir, options, spec, - sources, excluded_sources, - props_files_of_rules, targets_files_of_rules, - actions_to_add, rule_dependencies, - extension_to_rule_name): - # MSBuild rules are implemented using three files: an XML file, a .targets - # file and a .props file. - # See http://blogs.msdn.com/b/vcblog/archive/2010/04/21/quick-help-on-vs2010-custom-build-rule.aspx - # for more details. - rules = spec.get('rules', []) - rules_native = [r for r in rules if not int(r.get('msvs_external_rule', 0))] - rules_external = [r for r in rules if int(r.get('msvs_external_rule', 0))] - - msbuild_rules = [] - for rule in rules_native: - # Skip a rule with no action and no inputs. - if 'action' not in rule and not rule.get('rule_sources', []): - continue - msbuild_rule = MSBuildRule(rule, spec) - msbuild_rules.append(msbuild_rule) - rule_dependencies.update(msbuild_rule.additional_dependencies.split(';')) - extension_to_rule_name[msbuild_rule.extension] = msbuild_rule.rule_name - if msbuild_rules: - base = spec['target_name'] + options.suffix - props_name = base + '.props' - targets_name = base + '.targets' - xml_name = base + '.xml' - - props_files_of_rules.add(props_name) - targets_files_of_rules.add(targets_name) - - props_path = os.path.join(output_dir, props_name) - targets_path = os.path.join(output_dir, targets_name) - xml_path = os.path.join(output_dir, xml_name) - - _GenerateMSBuildRulePropsFile(props_path, msbuild_rules) - _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules) - _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules) - - if rules_external: - _GenerateExternalRules(rules_external, output_dir, spec, - sources, options, actions_to_add) - _AdjustSourcesForRules(rules, sources, excluded_sources, True) - - -class MSBuildRule(object): - """Used to store information used to generate an MSBuild rule. - - Attributes: - rule_name: The rule name, sanitized to use in XML. - target_name: The name of the target. - after_targets: The name of the AfterTargets element. - before_targets: The name of the BeforeTargets element. - depends_on: The name of the DependsOn element. - compute_output: The name of the ComputeOutput element. - dirs_to_make: The name of the DirsToMake element. - inputs: The name of the _inputs element. - tlog: The name of the _tlog element. - extension: The extension this rule applies to. - description: The message displayed when this rule is invoked. - additional_dependencies: A string listing additional dependencies. - outputs: The outputs of this rule. - command: The command used to run the rule. - """ - - def __init__(self, rule, spec): - self.display_name = rule['rule_name'] - # Assure that the rule name is only characters and numbers - self.rule_name = re.sub(r'\W', '_', self.display_name) - # Create the various element names, following the example set by the - # Visual Studio 2008 to 2010 conversion. I don't know if VS2010 - # is sensitive to the exact names. - self.target_name = '_' + self.rule_name - self.after_targets = self.rule_name + 'AfterTargets' - self.before_targets = self.rule_name + 'BeforeTargets' - self.depends_on = self.rule_name + 'DependsOn' - self.compute_output = 'Compute%sOutput' % self.rule_name - self.dirs_to_make = self.rule_name + 'DirsToMake' - self.inputs = self.rule_name + '_inputs' - self.tlog = self.rule_name + '_tlog' - self.extension = rule['extension'] - if not self.extension.startswith('.'): - self.extension = '.' + self.extension - - self.description = MSVSSettings.ConvertVCMacrosToMSBuild( - rule.get('message', self.rule_name)) - old_additional_dependencies = _FixPaths(rule.get('inputs', [])) - self.additional_dependencies = ( - ';'.join([MSVSSettings.ConvertVCMacrosToMSBuild(i) - for i in old_additional_dependencies])) - old_outputs = _FixPaths(rule.get('outputs', [])) - self.outputs = ';'.join([MSVSSettings.ConvertVCMacrosToMSBuild(i) - for i in old_outputs]) - old_command = _BuildCommandLineForRule(spec, rule, has_input_path=True, - do_setup_env=True) - self.command = MSVSSettings.ConvertVCMacrosToMSBuild(old_command) - - -def _GenerateMSBuildRulePropsFile(props_path, msbuild_rules): - """Generate the .props file.""" - content = ['Project', - {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003'}] - for rule in msbuild_rules: - content.extend([ - ['PropertyGroup', - {'Condition': "'$(%s)' == '' and '$(%s)' == '' and " - "'$(ConfigurationType)' != 'Makefile'" % (rule.before_targets, - rule.after_targets) - }, - [rule.before_targets, 'Midl'], - [rule.after_targets, 'CustomBuild'], - ], - ['PropertyGroup', - [rule.depends_on, - {'Condition': "'$(ConfigurationType)' != 'Makefile'"}, - '_SelectedFiles;$(%s)' % rule.depends_on - ], - ], - ['ItemDefinitionGroup', - [rule.rule_name, - ['CommandLineTemplate', rule.command], - ['Outputs', rule.outputs], - ['ExecutionDescription', rule.description], - ['AdditionalDependencies', rule.additional_dependencies], - ], - ] - ]) - easy_xml.WriteXmlIfChanged(content, props_path, pretty=True, win32=True) - - -def _GenerateMSBuildRuleTargetsFile(targets_path, msbuild_rules): - """Generate the .targets file.""" - content = ['Project', - {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003' - } - ] - item_group = [ - 'ItemGroup', - ['PropertyPageSchema', - {'Include': '$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml'} - ] - ] - for rule in msbuild_rules: - item_group.append( - ['AvailableItemName', - {'Include': rule.rule_name}, - ['Targets', rule.target_name], - ]) - content.append(item_group) - - for rule in msbuild_rules: - content.append( - ['UsingTask', - {'TaskName': rule.rule_name, - 'TaskFactory': 'XamlTaskFactory', - 'AssemblyName': 'Microsoft.Build.Tasks.v4.0' - }, - ['Task', '$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml'], - ]) - for rule in msbuild_rules: - rule_name = rule.rule_name - target_outputs = '%%(%s.Outputs)' % rule_name - target_inputs = ('%%(%s.Identity);%%(%s.AdditionalDependencies);' - '$(MSBuildProjectFile)') % (rule_name, rule_name) - rule_inputs = '%%(%s.Identity)' % rule_name - extension_condition = ("'%(Extension)'=='.obj' or " - "'%(Extension)'=='.res' or " - "'%(Extension)'=='.rsc' or " - "'%(Extension)'=='.lib'") - remove_section = [ - 'ItemGroup', - {'Condition': "'@(SelectedFiles)' != ''"}, - [rule_name, - {'Remove': '@(%s)' % rule_name, - 'Condition': "'%(Identity)' != '@(SelectedFiles)'" - } - ] - ] - inputs_section = [ - 'ItemGroup', - [rule.inputs, {'Include': '%%(%s.AdditionalDependencies)' % rule_name}] - ] - logging_section = [ - 'ItemGroup', - [rule.tlog, - {'Include': '%%(%s.Outputs)' % rule_name, - 'Condition': ("'%%(%s.Outputs)' != '' and " - "'%%(%s.ExcludedFromBuild)' != 'true'" % - (rule_name, rule_name)) - }, - ['Source', "@(%s, '|')" % rule_name], - ['Inputs', "@(%s -> '%%(Fullpath)', ';')" % rule.inputs], - ], - ] - message_section = [ - 'Message', - {'Importance': 'High', - 'Text': '%%(%s.ExecutionDescription)' % rule_name - } - ] - write_tlog_section = [ - 'WriteLinesToFile', - {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != " - "'true'" % (rule.tlog, rule.tlog), - 'File': '$(IntDir)$(ProjectName).write.1.tlog', - 'Lines': "^%%(%s.Source);@(%s->'%%(Fullpath)')" % (rule.tlog, - rule.tlog) - } - ] - read_tlog_section = [ - 'WriteLinesToFile', - {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != " - "'true'" % (rule.tlog, rule.tlog), - 'File': '$(IntDir)$(ProjectName).read.1.tlog', - 'Lines': "^%%(%s.Source);%%(%s.Inputs)" % (rule.tlog, rule.tlog) - } - ] - command_and_input_section = [ - rule_name, - {'Condition': "'@(%s)' != '' and '%%(%s.ExcludedFromBuild)' != " - "'true'" % (rule_name, rule_name), - 'EchoOff': 'true', - 'StandardOutputImportance': 'High', - 'StandardErrorImportance': 'High', - 'CommandLineTemplate': '%%(%s.CommandLineTemplate)' % rule_name, - 'AdditionalOptions': '%%(%s.AdditionalOptions)' % rule_name, - 'Inputs': rule_inputs - } - ] - content.extend([ - ['Target', - {'Name': rule.target_name, - 'BeforeTargets': '$(%s)' % rule.before_targets, - 'AfterTargets': '$(%s)' % rule.after_targets, - 'Condition': "'@(%s)' != ''" % rule_name, - 'DependsOnTargets': '$(%s);%s' % (rule.depends_on, - rule.compute_output), - 'Outputs': target_outputs, - 'Inputs': target_inputs - }, - remove_section, - inputs_section, - logging_section, - message_section, - write_tlog_section, - read_tlog_section, - command_and_input_section, - ], - ['PropertyGroup', - ['ComputeLinkInputsTargets', - '$(ComputeLinkInputsTargets);', - '%s;' % rule.compute_output - ], - ['ComputeLibInputsTargets', - '$(ComputeLibInputsTargets);', - '%s;' % rule.compute_output - ], - ], - ['Target', - {'Name': rule.compute_output, - 'Condition': "'@(%s)' != ''" % rule_name - }, - ['ItemGroup', - [rule.dirs_to_make, - {'Condition': "'@(%s)' != '' and " - "'%%(%s.ExcludedFromBuild)' != 'true'" % (rule_name, rule_name), - 'Include': '%%(%s.Outputs)' % rule_name - } - ], - ['Link', - {'Include': '%%(%s.Identity)' % rule.dirs_to_make, - 'Condition': extension_condition - } - ], - ['Lib', - {'Include': '%%(%s.Identity)' % rule.dirs_to_make, - 'Condition': extension_condition - } - ], - ['ImpLib', - {'Include': '%%(%s.Identity)' % rule.dirs_to_make, - 'Condition': extension_condition - } - ], - ], - ['MakeDir', - {'Directories': ("@(%s->'%%(RootDir)%%(Directory)')" % - rule.dirs_to_make) - } - ] - ], - ]) - easy_xml.WriteXmlIfChanged(content, targets_path, pretty=True, win32=True) - - -def _GenerateMSBuildRuleXmlFile(xml_path, msbuild_rules): - # Generate the .xml file - content = [ - 'ProjectSchemaDefinitions', - {'xmlns': ('clr-namespace:Microsoft.Build.Framework.XamlTypes;' - 'assembly=Microsoft.Build.Framework'), - 'xmlns:x': 'http://schemas.microsoft.com/winfx/2006/xaml', - 'xmlns:sys': 'clr-namespace:System;assembly=mscorlib', - 'xmlns:transformCallback': - 'Microsoft.Cpp.Dev10.ConvertPropertyCallback' - } - ] - for rule in msbuild_rules: - content.extend([ - ['Rule', - {'Name': rule.rule_name, - 'PageTemplate': 'tool', - 'DisplayName': rule.display_name, - 'Order': '200' - }, - ['Rule.DataSource', - ['DataSource', - {'Persistence': 'ProjectFile', - 'ItemType': rule.rule_name - } - ] - ], - ['Rule.Categories', - ['Category', - {'Name': 'General'}, - ['Category.DisplayName', - ['sys:String', 'General'], - ], - ], - ['Category', - {'Name': 'Command Line', - 'Subtype': 'CommandLine' - }, - ['Category.DisplayName', - ['sys:String', 'Command Line'], - ], - ], - ], - ['StringListProperty', - {'Name': 'Inputs', - 'Category': 'Command Line', - 'IsRequired': 'true', - 'Switch': ' ' - }, - ['StringListProperty.DataSource', - ['DataSource', - {'Persistence': 'ProjectFile', - 'ItemType': rule.rule_name, - 'SourceType': 'Item' - } - ] - ], - ], - ['StringProperty', - {'Name': 'CommandLineTemplate', - 'DisplayName': 'Command Line', - 'Visible': 'False', - 'IncludeInCommandLine': 'False' - } - ], - ['DynamicEnumProperty', - {'Name': rule.before_targets, - 'Category': 'General', - 'EnumProvider': 'Targets', - 'IncludeInCommandLine': 'False' - }, - ['DynamicEnumProperty.DisplayName', - ['sys:String', 'Execute Before'], - ], - ['DynamicEnumProperty.Description', - ['sys:String', 'Specifies the targets for the build customization' - ' to run before.' - ], - ], - ['DynamicEnumProperty.ProviderSettings', - ['NameValuePair', - {'Name': 'Exclude', - 'Value': '^%s|^Compute' % rule.before_targets - } - ] - ], - ['DynamicEnumProperty.DataSource', - ['DataSource', - {'Persistence': 'ProjectFile', - 'HasConfigurationCondition': 'true' - } - ] - ], - ], - ['DynamicEnumProperty', - {'Name': rule.after_targets, - 'Category': 'General', - 'EnumProvider': 'Targets', - 'IncludeInCommandLine': 'False' - }, - ['DynamicEnumProperty.DisplayName', - ['sys:String', 'Execute After'], - ], - ['DynamicEnumProperty.Description', - ['sys:String', ('Specifies the targets for the build customization' - ' to run after.') - ], - ], - ['DynamicEnumProperty.ProviderSettings', - ['NameValuePair', - {'Name': 'Exclude', - 'Value': '^%s|^Compute' % rule.after_targets - } - ] - ], - ['DynamicEnumProperty.DataSource', - ['DataSource', - {'Persistence': 'ProjectFile', - 'ItemType': '', - 'HasConfigurationCondition': 'true' - } - ] - ], - ], - ['StringListProperty', - {'Name': 'Outputs', - 'DisplayName': 'Outputs', - 'Visible': 'False', - 'IncludeInCommandLine': 'False' - } - ], - ['StringProperty', - {'Name': 'ExecutionDescription', - 'DisplayName': 'Execution Description', - 'Visible': 'False', - 'IncludeInCommandLine': 'False' - } - ], - ['StringListProperty', - {'Name': 'AdditionalDependencies', - 'DisplayName': 'Additional Dependencies', - 'IncludeInCommandLine': 'False', - 'Visible': 'false' - } - ], - ['StringProperty', - {'Subtype': 'AdditionalOptions', - 'Name': 'AdditionalOptions', - 'Category': 'Command Line' - }, - ['StringProperty.DisplayName', - ['sys:String', 'Additional Options'], - ], - ['StringProperty.Description', - ['sys:String', 'Additional Options'], - ], - ], - ], - ['ItemType', - {'Name': rule.rule_name, - 'DisplayName': rule.display_name - } - ], - ['FileExtension', - {'Name': '*' + rule.extension, - 'ContentType': rule.rule_name - } - ], - ['ContentType', - {'Name': rule.rule_name, - 'DisplayName': '', - 'ItemType': rule.rule_name - } - ] - ]) - easy_xml.WriteXmlIfChanged(content, xml_path, pretty=True, win32=True) - - -def _GetConfigurationAndPlatform(name, settings): - configuration = name.rsplit('_', 1)[0] - platform = settings.get('msvs_configuration_platform', 'Win32') - return (configuration, platform) - - -def _GetConfigurationCondition(name, settings): - return (r"'$(Configuration)|$(Platform)'=='%s|%s'" % - _GetConfigurationAndPlatform(name, settings)) - - -def _GetMSBuildProjectConfigurations(configurations): - group = ['ItemGroup', {'Label': 'ProjectConfigurations'}] - for (name, settings) in sorted(configurations.iteritems()): - configuration, platform = _GetConfigurationAndPlatform(name, settings) - designation = '%s|%s' % (configuration, platform) - group.append( - ['ProjectConfiguration', {'Include': designation}, - ['Configuration', configuration], - ['Platform', platform]]) - return [group] - - -def _GetMSBuildGlobalProperties(spec, guid, gyp_file_name): - namespace = os.path.splitext(gyp_file_name)[0] - properties = [ - ['PropertyGroup', {'Label': 'Globals'}, - ['ProjectGuid', guid], - ['Keyword', 'Win32Proj'], - ['RootNamespace', namespace], - ['IgnoreWarnCompileDuplicatedFilename', 'true'], - ] - ] - - if os.environ.get('PROCESSOR_ARCHITECTURE') == 'AMD64' or \ - os.environ.get('PROCESSOR_ARCHITEW6432') == 'AMD64': - properties[0].append(['PreferredToolArchitecture', 'x64']) - - if spec.get('msvs_enable_winrt'): - properties[0].append(['DefaultLanguage', 'en-US']) - properties[0].append(['AppContainerApplication', 'true']) - if spec.get('msvs_application_type_revision'): - app_type_revision = spec.get('msvs_application_type_revision') - properties[0].append(['ApplicationTypeRevision', app_type_revision]) - else: - properties[0].append(['ApplicationTypeRevision', '8.1']) - - if spec.get('msvs_target_platform_version'): - target_platform_version = spec.get('msvs_target_platform_version') - properties[0].append(['WindowsTargetPlatformVersion', - target_platform_version]) - if spec.get('msvs_target_platform_minversion'): - target_platform_minversion = spec.get('msvs_target_platform_minversion') - properties[0].append(['WindowsTargetPlatformMinVersion', - target_platform_minversion]) - else: - properties[0].append(['WindowsTargetPlatformMinVersion', - target_platform_version]) - if spec.get('msvs_enable_winphone'): - properties[0].append(['ApplicationType', 'Windows Phone']) - else: - properties[0].append(['ApplicationType', 'Windows Store']) - - platform_name = None - msvs_windows_target_platform_version = None - for configuration in spec['configurations'].itervalues(): - platform_name = platform_name or _ConfigPlatform(configuration) - msvs_windows_target_platform_version = \ - msvs_windows_target_platform_version or \ - _ConfigWindowsTargetPlatformVersion(configuration) - if platform_name and msvs_windows_target_platform_version: - break - - if platform_name == 'ARM': - properties[0].append(['WindowsSDKDesktopARMSupport', 'true']) - if msvs_windows_target_platform_version: - properties[0].append(['WindowsTargetPlatformVersion', \ - str(msvs_windows_target_platform_version)]) - - return properties - -def _GetMSBuildConfigurationDetails(spec, build_file): - properties = {} - for name, settings in spec['configurations'].iteritems(): - msbuild_attributes = _GetMSBuildAttributes(spec, settings, build_file) - condition = _GetConfigurationCondition(name, settings) - character_set = msbuild_attributes.get('CharacterSet') - _AddConditionalProperty(properties, condition, 'ConfigurationType', - msbuild_attributes['ConfigurationType']) - if character_set: - if 'msvs_enable_winrt' not in spec : - _AddConditionalProperty(properties, condition, 'CharacterSet', - character_set) - return _GetMSBuildPropertyGroup(spec, 'Configuration', properties) - - -def _GetMSBuildLocalProperties(msbuild_toolset): - # Currently the only local property we support is PlatformToolset - properties = {} - if msbuild_toolset: - properties = [ - ['PropertyGroup', {'Label': 'Locals'}, - ['PlatformToolset', msbuild_toolset], - ] - ] - return properties - - -def _GetMSBuildPropertySheets(configurations): - user_props = r'$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props' - additional_props = {} - props_specified = False - for name, settings in sorted(configurations.iteritems()): - configuration = _GetConfigurationCondition(name, settings) - if settings.has_key('msbuild_props'): - additional_props[configuration] = _FixPaths(settings['msbuild_props']) - props_specified = True - else: - additional_props[configuration] = '' - - if not props_specified: - return [ - ['ImportGroup', - {'Label': 'PropertySheets'}, - ['Import', - {'Project': user_props, - 'Condition': "exists('%s')" % user_props, - 'Label': 'LocalAppDataPlatform' - } - ] - ] - ] - else: - sheets = [] - for condition, props in additional_props.iteritems(): - import_group = [ - 'ImportGroup', - {'Label': 'PropertySheets', - 'Condition': condition - }, - ['Import', - {'Project': user_props, - 'Condition': "exists('%s')" % user_props, - 'Label': 'LocalAppDataPlatform' - } - ] - ] - for props_file in props: - import_group.append(['Import', {'Project':props_file}]) - sheets.append(import_group) - return sheets - -def _ConvertMSVSBuildAttributes(spec, config, build_file): - config_type = _GetMSVSConfigurationType(spec, build_file) - msvs_attributes = _GetMSVSAttributes(spec, config, config_type) - msbuild_attributes = {} - for a in msvs_attributes: - if a in ['IntermediateDirectory', 'OutputDirectory']: - directory = MSVSSettings.ConvertVCMacrosToMSBuild(msvs_attributes[a]) - if not directory.endswith('\\'): - directory += '\\' - msbuild_attributes[a] = directory - elif a == 'CharacterSet': - msbuild_attributes[a] = _ConvertMSVSCharacterSet(msvs_attributes[a]) - elif a == 'ConfigurationType': - msbuild_attributes[a] = _ConvertMSVSConfigurationType(msvs_attributes[a]) - else: - print 'Warning: Do not know how to convert MSVS attribute ' + a - return msbuild_attributes - - -def _ConvertMSVSCharacterSet(char_set): - if char_set.isdigit(): - char_set = { - '0': 'MultiByte', - '1': 'Unicode', - '2': 'MultiByte', - }[char_set] - return char_set - - -def _ConvertMSVSConfigurationType(config_type): - if config_type.isdigit(): - config_type = { - '1': 'Application', - '2': 'DynamicLibrary', - '4': 'StaticLibrary', - '10': 'Utility' - }[config_type] - return config_type - - -def _GetMSBuildAttributes(spec, config, build_file): - if 'msbuild_configuration_attributes' not in config: - msbuild_attributes = _ConvertMSVSBuildAttributes(spec, config, build_file) - - else: - config_type = _GetMSVSConfigurationType(spec, build_file) - config_type = _ConvertMSVSConfigurationType(config_type) - msbuild_attributes = config.get('msbuild_configuration_attributes', {}) - msbuild_attributes.setdefault('ConfigurationType', config_type) - output_dir = msbuild_attributes.get('OutputDirectory', - '$(SolutionDir)$(Configuration)') - msbuild_attributes['OutputDirectory'] = _FixPath(output_dir) + '\\' - if 'IntermediateDirectory' not in msbuild_attributes: - intermediate = _FixPath('$(Configuration)') + '\\' - msbuild_attributes['IntermediateDirectory'] = intermediate - if 'CharacterSet' in msbuild_attributes: - msbuild_attributes['CharacterSet'] = _ConvertMSVSCharacterSet( - msbuild_attributes['CharacterSet']) - if 'TargetName' not in msbuild_attributes: - prefix = spec.get('product_prefix', '') - product_name = spec.get('product_name', '$(ProjectName)') - target_name = prefix + product_name - msbuild_attributes['TargetName'] = target_name - if 'TargetExt' not in msbuild_attributes and 'product_extension' in spec: - ext = spec.get('product_extension') - msbuild_attributes['TargetExt'] = '.' + ext - - if spec.get('msvs_external_builder'): - external_out_dir = spec.get('msvs_external_builder_out_dir', '.') - msbuild_attributes['OutputDirectory'] = _FixPath(external_out_dir) + '\\' - - # Make sure that 'TargetPath' matches 'Lib.OutputFile' or 'Link.OutputFile' - # (depending on the tool used) to avoid MSB8012 warning. - msbuild_tool_map = { - 'executable': 'Link', - 'shared_library': 'Link', - 'loadable_module': 'Link', - 'static_library': 'Lib', - } - msbuild_tool = msbuild_tool_map.get(spec['type']) - if msbuild_tool: - msbuild_settings = config['finalized_msbuild_settings'] - out_file = msbuild_settings[msbuild_tool].get('OutputFile') - if out_file: - msbuild_attributes['TargetPath'] = _FixPath(out_file) - target_ext = msbuild_settings[msbuild_tool].get('TargetExt') - if target_ext: - msbuild_attributes['TargetExt'] = target_ext - - return msbuild_attributes - - -def _GetMSBuildConfigurationGlobalProperties(spec, configurations, build_file): - # TODO(jeanluc) We could optimize out the following and do it only if - # there are actions. - # TODO(jeanluc) Handle the equivalent of setting 'CYGWIN=nontsec'. - new_paths = [] - cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.'])[0] - if cygwin_dirs: - cyg_path = '$(MSBuildProjectDirectory)\\%s\\bin\\' % _FixPath(cygwin_dirs) - new_paths.append(cyg_path) - # TODO(jeanluc) Change the convention to have both a cygwin_dir and a - # python_dir. - python_path = cyg_path.replace('cygwin\\bin', 'python_26') - new_paths.append(python_path) - if new_paths: - new_paths = '$(ExecutablePath);' + ';'.join(new_paths) - - properties = {} - for (name, configuration) in sorted(configurations.iteritems()): - condition = _GetConfigurationCondition(name, configuration) - attributes = _GetMSBuildAttributes(spec, configuration, build_file) - msbuild_settings = configuration['finalized_msbuild_settings'] - _AddConditionalProperty(properties, condition, 'IntDir', - attributes['IntermediateDirectory']) - _AddConditionalProperty(properties, condition, 'OutDir', - attributes['OutputDirectory']) - _AddConditionalProperty(properties, condition, 'TargetName', - attributes['TargetName']) - if 'TargetExt' in attributes: - _AddConditionalProperty(properties, condition, 'TargetExt', - attributes['TargetExt']) - - if attributes.get('TargetPath'): - _AddConditionalProperty(properties, condition, 'TargetPath', - attributes['TargetPath']) - if attributes.get('TargetExt'): - _AddConditionalProperty(properties, condition, 'TargetExt', - attributes['TargetExt']) - - if new_paths: - _AddConditionalProperty(properties, condition, 'ExecutablePath', - new_paths) - tool_settings = msbuild_settings.get('', {}) - for name, value in sorted(tool_settings.iteritems()): - formatted_value = _GetValueFormattedForMSBuild('', name, value) - _AddConditionalProperty(properties, condition, name, formatted_value) - return _GetMSBuildPropertyGroup(spec, None, properties) - - -def _AddConditionalProperty(properties, condition, name, value): - """Adds a property / conditional value pair to a dictionary. - - Arguments: - properties: The dictionary to be modified. The key is the name of the - property. The value is itself a dictionary; its key is the value and - the value a list of condition for which this value is true. - condition: The condition under which the named property has the value. - name: The name of the property. - value: The value of the property. - """ - if name not in properties: - properties[name] = {} - values = properties[name] - if value not in values: - values[value] = [] - conditions = values[value] - conditions.append(condition) - - -# Regex for msvs variable references ( i.e. $(FOO) ). -MSVS_VARIABLE_REFERENCE = re.compile(r'\$\(([a-zA-Z_][a-zA-Z0-9_]*)\)') - - -def _GetMSBuildPropertyGroup(spec, label, properties): - """Returns a PropertyGroup definition for the specified properties. - - Arguments: - spec: The target project dict. - label: An optional label for the PropertyGroup. - properties: The dictionary to be converted. The key is the name of the - property. The value is itself a dictionary; its key is the value and - the value a list of condition for which this value is true. - """ - group = ['PropertyGroup'] - if label: - group.append({'Label': label}) - num_configurations = len(spec['configurations']) - def GetEdges(node): - # Use a definition of edges such that user_of_variable -> used_varible. - # This happens to be easier in this case, since a variable's - # definition contains all variables it references in a single string. - edges = set() - for value in sorted(properties[node].keys()): - # Add to edges all $(...) references to variables. - # - # Variable references that refer to names not in properties are excluded - # These can exist for instance to refer built in definitions like - # $(SolutionDir). - # - # Self references are ignored. Self reference is used in a few places to - # append to the default value. I.e. PATH=$(PATH);other_path - edges.update(set([v for v in MSVS_VARIABLE_REFERENCE.findall(value) - if v in properties and v != node])) - return edges - properties_ordered = gyp.common.TopologicallySorted( - properties.keys(), GetEdges) - # Walk properties in the reverse of a topological sort on - # user_of_variable -> used_variable as this ensures variables are - # defined before they are used. - # NOTE: reverse(topsort(DAG)) = topsort(reverse_edges(DAG)) - for name in reversed(properties_ordered): - values = properties[name] - for value, conditions in sorted(values.iteritems()): - if len(conditions) == num_configurations: - # If the value is the same all configurations, - # just add one unconditional entry. - group.append([name, value]) - else: - for condition in conditions: - group.append([name, {'Condition': condition}, value]) - return [group] - - -def _GetMSBuildToolSettingsSections(spec, configurations): - groups = [] - for (name, configuration) in sorted(configurations.iteritems()): - msbuild_settings = configuration['finalized_msbuild_settings'] - group = ['ItemDefinitionGroup', - {'Condition': _GetConfigurationCondition(name, configuration)} - ] - for tool_name, tool_settings in sorted(msbuild_settings.iteritems()): - # Skip the tool named '' which is a holder of global settings handled - # by _GetMSBuildConfigurationGlobalProperties. - if tool_name: - if tool_settings: - tool = [tool_name] - for name, value in sorted(tool_settings.iteritems()): - formatted_value = _GetValueFormattedForMSBuild(tool_name, name, - value) - tool.append([name, formatted_value]) - group.append(tool) - groups.append(group) - return groups - - -def _FinalizeMSBuildSettings(spec, configuration): - if 'msbuild_settings' in configuration: - converted = False - msbuild_settings = configuration['msbuild_settings'] - MSVSSettings.ValidateMSBuildSettings(msbuild_settings) - else: - converted = True - msvs_settings = configuration.get('msvs_settings', {}) - msbuild_settings = MSVSSettings.ConvertToMSBuildSettings(msvs_settings) - include_dirs, midl_include_dirs, resource_include_dirs = \ - _GetIncludeDirs(configuration) - libraries = _GetLibraries(spec) - library_dirs = _GetLibraryDirs(configuration) - out_file, _, msbuild_tool = _GetOutputFilePathAndTool(spec, msbuild=True) - target_ext = _GetOutputTargetExt(spec) - defines = _GetDefines(configuration) - if converted: - # Visual Studio 2010 has TR1 - defines = [d for d in defines if d != '_HAS_TR1=0'] - # Warn of ignored settings - ignored_settings = ['msvs_tool_files'] - for ignored_setting in ignored_settings: - value = configuration.get(ignored_setting) - if value: - print ('Warning: The automatic conversion to MSBuild does not handle ' - '%s. Ignoring setting of %s' % (ignored_setting, str(value))) - - defines = [_EscapeCppDefineForMSBuild(d) for d in defines] - disabled_warnings = _GetDisabledWarnings(configuration) - prebuild = configuration.get('msvs_prebuild') - postbuild = configuration.get('msvs_postbuild') - def_file = _GetModuleDefinition(spec) - precompiled_header = configuration.get('msvs_precompiled_header') - - # Add the information to the appropriate tool - # TODO(jeanluc) We could optimize and generate these settings only if - # the corresponding files are found, e.g. don't generate ResourceCompile - # if you don't have any resources. - _ToolAppend(msbuild_settings, 'ClCompile', - 'AdditionalIncludeDirectories', include_dirs) - _ToolAppend(msbuild_settings, 'Midl', - 'AdditionalIncludeDirectories', midl_include_dirs) - _ToolAppend(msbuild_settings, 'ResourceCompile', - 'AdditionalIncludeDirectories', resource_include_dirs) - # Add in libraries, note that even for empty libraries, we want this - # set, to prevent inheriting default libraries from the enviroment. - _ToolSetOrAppend(msbuild_settings, 'Link', 'AdditionalDependencies', - libraries) - _ToolAppend(msbuild_settings, 'Link', 'AdditionalLibraryDirectories', - library_dirs) - if out_file: - _ToolAppend(msbuild_settings, msbuild_tool, 'OutputFile', out_file, - only_if_unset=True) - if target_ext: - _ToolAppend(msbuild_settings, msbuild_tool, 'TargetExt', target_ext, - only_if_unset=True) - # Add defines. - _ToolAppend(msbuild_settings, 'ClCompile', - 'PreprocessorDefinitions', defines) - _ToolAppend(msbuild_settings, 'ResourceCompile', - 'PreprocessorDefinitions', defines) - # Add disabled warnings. - _ToolAppend(msbuild_settings, 'ClCompile', - 'DisableSpecificWarnings', disabled_warnings) - # Turn on precompiled headers if appropriate. - if precompiled_header: - precompiled_header = os.path.split(precompiled_header)[1] - _ToolAppend(msbuild_settings, 'ClCompile', 'PrecompiledHeader', 'Use') - _ToolAppend(msbuild_settings, 'ClCompile', - 'PrecompiledHeaderFile', precompiled_header) - _ToolAppend(msbuild_settings, 'ClCompile', - 'ForcedIncludeFiles', [precompiled_header]) - else: - _ToolAppend(msbuild_settings, 'ClCompile', 'PrecompiledHeader', 'NotUsing') - # Turn off WinRT compilation - _ToolAppend(msbuild_settings, 'ClCompile', 'CompileAsWinRT', 'false') - # Turn on import libraries if appropriate - if spec.get('msvs_requires_importlibrary'): - _ToolAppend(msbuild_settings, '', 'IgnoreImportLibrary', 'false') - # Loadable modules don't generate import libraries; - # tell dependent projects to not expect one. - if spec['type'] == 'loadable_module': - _ToolAppend(msbuild_settings, '', 'IgnoreImportLibrary', 'true') - # Set the module definition file if any. - if def_file: - _ToolAppend(msbuild_settings, 'Link', 'ModuleDefinitionFile', def_file) - configuration['finalized_msbuild_settings'] = msbuild_settings - if prebuild: - _ToolAppend(msbuild_settings, 'PreBuildEvent', 'Command', prebuild) - if postbuild: - _ToolAppend(msbuild_settings, 'PostBuildEvent', 'Command', postbuild) - - -def _GetValueFormattedForMSBuild(tool_name, name, value): - if type(value) == list: - # For some settings, VS2010 does not automatically extends the settings - # TODO(jeanluc) Is this what we want? - if name in ['AdditionalIncludeDirectories', - 'AdditionalLibraryDirectories', - 'AdditionalOptions', - 'DelayLoadDLLs', - 'DisableSpecificWarnings', - 'PreprocessorDefinitions']: - value.append('%%(%s)' % name) - # For most tools, entries in a list should be separated with ';' but some - # settings use a space. Check for those first. - exceptions = { - 'ClCompile': ['AdditionalOptions'], - 'Link': ['AdditionalOptions'], - 'Lib': ['AdditionalOptions']} - if tool_name in exceptions and name in exceptions[tool_name]: - char = ' ' - else: - char = ';' - formatted_value = char.join( - [MSVSSettings.ConvertVCMacrosToMSBuild(i) for i in value]) - else: - formatted_value = MSVSSettings.ConvertVCMacrosToMSBuild(value) - return formatted_value - - -def _VerifySourcesExist(sources, root_dir): - """Verifies that all source files exist on disk. - - Checks that all regular source files, i.e. not created at run time, - exist on disk. Missing files cause needless recompilation but no otherwise - visible errors. - - Arguments: - sources: A recursive list of Filter/file names. - root_dir: The root directory for the relative path names. - Returns: - A list of source files that cannot be found on disk. - """ - missing_sources = [] - for source in sources: - if isinstance(source, MSVSProject.Filter): - missing_sources.extend(_VerifySourcesExist(source.contents, root_dir)) - else: - if '$' not in source: - full_path = os.path.join(root_dir, source) - if not os.path.exists(full_path): - missing_sources.append(full_path) - return missing_sources - - -def _GetMSBuildSources(spec, sources, exclusions, rule_dependencies, - extension_to_rule_name, actions_spec, - sources_handled_by_action, list_excluded): - groups = ['none', 'masm', 'midl', 'include', 'compile', 'resource', 'rule', - 'rule_dependency'] - grouped_sources = {} - for g in groups: - grouped_sources[g] = [] - - _AddSources2(spec, sources, exclusions, grouped_sources, - rule_dependencies, extension_to_rule_name, - sources_handled_by_action, list_excluded) - sources = [] - for g in groups: - if grouped_sources[g]: - sources.append(['ItemGroup'] + grouped_sources[g]) - if actions_spec: - sources.append(['ItemGroup'] + actions_spec) - return sources - - -def _AddSources2(spec, sources, exclusions, grouped_sources, - rule_dependencies, extension_to_rule_name, - sources_handled_by_action, - list_excluded): - extensions_excluded_from_precompile = [] - for source in sources: - if isinstance(source, MSVSProject.Filter): - _AddSources2(spec, source.contents, exclusions, grouped_sources, - rule_dependencies, extension_to_rule_name, - sources_handled_by_action, - list_excluded) - else: - if not source in sources_handled_by_action: - detail = [] - excluded_configurations = exclusions.get(source, []) - if len(excluded_configurations) == len(spec['configurations']): - detail.append(['ExcludedFromBuild', 'true']) - else: - for config_name, configuration in sorted(excluded_configurations): - condition = _GetConfigurationCondition(config_name, configuration) - detail.append(['ExcludedFromBuild', - {'Condition': condition}, - 'true']) - # Add precompile if needed - for config_name, configuration in spec['configurations'].iteritems(): - precompiled_source = configuration.get('msvs_precompiled_source', '') - if precompiled_source != '': - precompiled_source = _FixPath(precompiled_source) - if not extensions_excluded_from_precompile: - # If the precompiled header is generated by a C source, we must - # not try to use it for C++ sources, and vice versa. - basename, extension = os.path.splitext(precompiled_source) - if extension == '.c': - extensions_excluded_from_precompile = ['.cc', '.cpp', '.cxx'] - else: - extensions_excluded_from_precompile = ['.c'] - - if precompiled_source == source: - condition = _GetConfigurationCondition(config_name, configuration) - detail.append(['PrecompiledHeader', - {'Condition': condition}, - 'Create' - ]) - else: - # Turn off precompiled header usage for source files of a - # different type than the file that generated the - # precompiled header. - for extension in extensions_excluded_from_precompile: - if source.endswith(extension): - detail.append(['PrecompiledHeader', '']) - detail.append(['ForcedIncludeFiles', '']) - - group, element = _MapFileToMsBuildSourceType(source, rule_dependencies, - extension_to_rule_name) - grouped_sources[group].append([element, {'Include': source}] + detail) - - -def _GetMSBuildProjectReferences(project): - references = [] - if project.dependencies: - group = ['ItemGroup'] - for dependency in project.dependencies: - guid = dependency.guid - project_dir = os.path.split(project.path)[0] - relative_path = gyp.common.RelativePath(dependency.path, project_dir) - project_ref = ['ProjectReference', - {'Include': relative_path}, - ['Project', guid], - ['ReferenceOutputAssembly', 'false'] - ] - for config in dependency.spec.get('configurations', {}).itervalues(): - if config.get('msvs_use_library_dependency_inputs', 0): - project_ref.append(['UseLibraryDependencyInputs', 'true']) - break - # If it's disabled in any config, turn it off in the reference. - if config.get('msvs_2010_disable_uldi_when_referenced', 0): - project_ref.append(['UseLibraryDependencyInputs', 'false']) - break - group.append(project_ref) - references.append(group) - return references - - -def _GenerateMSBuildProject(project, options, version, generator_flags): - spec = project.spec - configurations = spec['configurations'] - project_dir, project_file_name = os.path.split(project.path) - 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) - - gyp_file = os.path.split(project.build_file)[1] - sources, excluded_sources = _PrepareListOfSources(spec, generator_flags, - gyp_file) - # Add rules. - actions_to_add = {} - props_files_of_rules = set() - targets_files_of_rules = set() - rule_dependencies = set() - extension_to_rule_name = {} - list_excluded = generator_flags.get('msvs_list_excluded_files', True) - - # Don't generate rules if we are using an external builder like ninja. - if not spec.get('msvs_external_builder'): - _GenerateRulesForMSBuild(project_dir, options, spec, - sources, excluded_sources, - props_files_of_rules, targets_files_of_rules, - actions_to_add, rule_dependencies, - extension_to_rule_name) - else: - rules = spec.get('rules', []) - _AdjustSourcesForRules(rules, sources, excluded_sources, True) - - sources, excluded_sources, excluded_idl = ( - _AdjustSourcesAndConvertToFilterHierarchy(spec, options, - project_dir, sources, - excluded_sources, - list_excluded, version)) - - # Don't add actions if we are using an external builder like ninja. - if not spec.get('msvs_external_builder'): - _AddActions(actions_to_add, spec, project.build_file) - _AddCopies(actions_to_add, spec) - - # NOTE: this stanza must appear after all actions have been decided. - # Don't excluded sources with actions attached, or they won't run. - excluded_sources = _FilterActionsFromExcluded( - excluded_sources, actions_to_add) - - exclusions = _GetExcludedFilesFromBuild(spec, excluded_sources, excluded_idl) - actions_spec, sources_handled_by_action = _GenerateActionsForMSBuild( - spec, actions_to_add) - - _GenerateMSBuildFiltersFile(project.path + '.filters', sources, - rule_dependencies, - extension_to_rule_name) - missing_sources = _VerifySourcesExist(sources, project_dir) - - for configuration in configurations.itervalues(): - _FinalizeMSBuildSettings(spec, configuration) - - # Add attributes to root element - - import_default_section = [ - ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.Default.props'}]] - import_cpp_props_section = [ - ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.props'}]] - import_cpp_targets_section = [ - ['Import', {'Project': r'$(VCTargetsPath)\Microsoft.Cpp.targets'}]] - import_masm_props_section = [ - ['Import', - {'Project': r'$(VCTargetsPath)\BuildCustomizations\masm.props'}]] - import_masm_targets_section = [ - ['Import', - {'Project': r'$(VCTargetsPath)\BuildCustomizations\masm.targets'}]] - macro_section = [['PropertyGroup', {'Label': 'UserMacros'}]] - - content = [ - 'Project', - {'xmlns': 'http://schemas.microsoft.com/developer/msbuild/2003', - 'ToolsVersion': version.ProjectVersion(), - 'DefaultTargets': 'Build' - }] - - content += _GetMSBuildProjectConfigurations(configurations) - content += _GetMSBuildGlobalProperties(spec, project.guid, project_file_name) - content += import_default_section - content += _GetMSBuildConfigurationDetails(spec, project.build_file) - if spec.get('msvs_enable_winphone'): - content += _GetMSBuildLocalProperties('v120_wp81') - else: - content += _GetMSBuildLocalProperties(project.msbuild_toolset) - content += import_cpp_props_section - content += import_masm_props_section - content += _GetMSBuildExtensions(props_files_of_rules) - content += _GetMSBuildPropertySheets(configurations) - content += macro_section - content += _GetMSBuildConfigurationGlobalProperties(spec, configurations, - project.build_file) - content += _GetMSBuildToolSettingsSections(spec, configurations) - content += _GetMSBuildSources( - spec, sources, exclusions, rule_dependencies, extension_to_rule_name, - actions_spec, sources_handled_by_action, list_excluded) - content += _GetMSBuildProjectReferences(project) - content += import_cpp_targets_section - content += import_masm_targets_section - content += _GetMSBuildExtensionTargets(targets_files_of_rules) - - if spec.get('msvs_external_builder'): - content += _GetMSBuildExternalBuilderTargets(spec) - - # TODO(jeanluc) File a bug to get rid of runas. We had in MSVS: - # has_run_as = _WriteMSVSUserFile(project.path, version, spec) - - easy_xml.WriteXmlIfChanged(content, project.path, pretty=True, win32=True) - - return missing_sources - - -def _GetMSBuildExternalBuilderTargets(spec): - """Return a list of MSBuild targets for external builders. - - The "Build" and "Clean" targets are always generated. If the spec contains - 'msvs_external_builder_clcompile_cmd', then the "ClCompile" target will also - be generated, to support building selected C/C++ files. - - Arguments: - spec: The gyp target spec. - Returns: - List of MSBuild 'Target' specs. - """ - build_cmd = _BuildCommandLineForRuleRaw( - spec, spec['msvs_external_builder_build_cmd'], - False, False, False, False) - build_target = ['Target', {'Name': 'Build'}] - build_target.append(['Exec', {'Command': build_cmd}]) - - clean_cmd = _BuildCommandLineForRuleRaw( - spec, spec['msvs_external_builder_clean_cmd'], - False, False, False, False) - clean_target = ['Target', {'Name': 'Clean'}] - clean_target.append(['Exec', {'Command': clean_cmd}]) - - targets = [build_target, clean_target] - - if spec.get('msvs_external_builder_clcompile_cmd'): - clcompile_cmd = _BuildCommandLineForRuleRaw( - spec, spec['msvs_external_builder_clcompile_cmd'], - False, False, False, False) - clcompile_target = ['Target', {'Name': 'ClCompile'}] - clcompile_target.append(['Exec', {'Command': clcompile_cmd}]) - targets.append(clcompile_target) - - return targets - - -def _GetMSBuildExtensions(props_files_of_rules): - extensions = ['ImportGroup', {'Label': 'ExtensionSettings'}] - for props_file in props_files_of_rules: - extensions.append(['Import', {'Project': props_file}]) - return [extensions] - - -def _GetMSBuildExtensionTargets(targets_files_of_rules): - targets_node = ['ImportGroup', {'Label': 'ExtensionTargets'}] - for targets_file in sorted(targets_files_of_rules): - targets_node.append(['Import', {'Project': targets_file}]) - return [targets_node] - - -def _GenerateActionsForMSBuild(spec, actions_to_add): - """Add actions accumulated into an actions_to_add, merging as needed. - - Arguments: - spec: the target project dict - actions_to_add: dictionary keyed on input name, which maps to a list of - dicts describing the actions attached to that input file. - - Returns: - A pair of (action specification, the sources handled by this action). - """ - sources_handled_by_action = OrderedSet() - actions_spec = [] - for primary_input, actions in actions_to_add.iteritems(): - inputs = OrderedSet() - outputs = OrderedSet() - descriptions = [] - commands = [] - for action in actions: - 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 - # return and continue executing. msbuild_use_call provides a way to - # disable this but I have not seen any adverse effect from doing that - # for everything. - if action.get('msbuild_use_call', True): - cmd = 'call ' + cmd - commands.append(cmd) - # Add the custom build action for one input file. - description = ', and also '.join(descriptions) - - # We can't join the commands simply with && because the command line will - # get too long. See also _AddActions: cygwin's setup_env mustn't be called - # for every invocation or the command that sets the PATH will grow too - # long. - command = '\r\n'.join([c + '\r\nif %errorlevel% neq 0 exit /b %errorlevel%' - for c in commands]) - _AddMSBuildAction(spec, - primary_input, - inputs, - outputs, - command, - description, - sources_handled_by_action, - actions_spec) - return actions_spec, sources_handled_by_action - - -def _AddMSBuildAction(spec, primary_input, inputs, outputs, cmd, description, - sources_handled_by_action, actions_spec): - command = MSVSSettings.ConvertVCMacrosToMSBuild(cmd) - primary_input = _FixPath(primary_input) - inputs_array = _FixPaths(inputs) - outputs_array = _FixPaths(outputs) - additional_inputs = ';'.join([i for i in inputs_array - if i != primary_input]) - outputs = ';'.join(outputs_array) - sources_handled_by_action.add(primary_input) - action_spec = ['CustomBuild', {'Include': primary_input}] - action_spec.extend( - # TODO(jeanluc) 'Document' for all or just if as_sources? - [['FileType', 'Document'], - ['Command', command], - ['Message', description], - ['Outputs', outputs] - ]) - if additional_inputs: - action_spec.append(['AdditionalInputs', additional_inputs]) - actions_spec.append(action_spec) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py deleted file mode 100755 index c0b021df502bf..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/msvs_test.py +++ /dev/null @@ -1,37 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 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. - -""" Unit tests for the msvs.py file. """ - -import gyp.generator.msvs as msvs -import unittest -import StringIO - - -class TestSequenceFunctions(unittest.TestCase): - - def setUp(self): - self.stderr = StringIO.StringIO() - - def test_GetLibraries(self): - self.assertEqual( - msvs._GetLibraries({}), - []) - self.assertEqual( - msvs._GetLibraries({'libraries': []}), - []) - self.assertEqual( - msvs._GetLibraries({'other':'foo', 'libraries': ['a.lib']}), - ['a.lib']) - self.assertEqual( - msvs._GetLibraries({'libraries': ['-la']}), - ['a.lib']) - self.assertEqual( - msvs._GetLibraries({'libraries': ['a.lib', 'b.lib', 'c.lib', '-lb.lib', - '-lb.lib', 'd.lib', 'a.lib']}), - ['c.lib', 'b.lib', 'd.lib', 'a.lib']) - -if __name__ == '__main__': - unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py deleted file mode 100644 index a00573ebf2345..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja.py +++ /dev/null @@ -1,2422 +0,0 @@ -# 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. - -import collections -import copy -import hashlib -import json -import multiprocessing -import os.path -import re -import signal -import subprocess -import sys -import gyp -import gyp.common -from gyp.common import OrderedSet -import gyp.msvs_emulation -import gyp.MSVSUtil as MSVSUtil -import gyp.xcode_emulation -from cStringIO import StringIO - -from gyp.common import GetEnvironFallback -import gyp.ninja_syntax as ninja_syntax - -generator_default_variables = { - 'EXECUTABLE_PREFIX': '', - 'EXECUTABLE_SUFFIX': '', - 'STATIC_LIB_PREFIX': 'lib', - 'STATIC_LIB_SUFFIX': '.a', - 'SHARED_LIB_PREFIX': 'lib', - - # Gyp expects the following variables to be expandable by the build - # system to the appropriate locations. Ninja prefers paths to be - # known at gyp time. To resolve this, introduce special - # variables starting with $! and $| (which begin with a $ so gyp knows it - # should be treated specially, but is otherwise an invalid - # ninja/shell variable) that are passed to gyp here but expanded - # before writing out into the target .ninja files; see - # ExpandSpecial. - # $! is used for variables that represent a path and that can only appear at - # the start of a string, while $| is used for variables that can appear - # anywhere in a string. - 'INTERMEDIATE_DIR': '$!INTERMEDIATE_DIR', - 'SHARED_INTERMEDIATE_DIR': '$!PRODUCT_DIR/gen', - 'PRODUCT_DIR': '$!PRODUCT_DIR', - 'CONFIGURATION_NAME': '$|CONFIGURATION_NAME', - - # Special variables that may be used by gyp 'rule' targets. - # We generate definitions for these variables on the fly when processing a - # rule. - 'RULE_INPUT_ROOT': '${root}', - 'RULE_INPUT_DIRNAME': '${dirname}', - 'RULE_INPUT_PATH': '${source}', - 'RULE_INPUT_EXT': '${ext}', - 'RULE_INPUT_NAME': '${name}', -} - -# Placates pylint. -generator_additional_non_configuration_keys = [] -generator_additional_path_sections = [] -generator_extra_sources_for_rules = [] -generator_filelist_paths = None - -generator_supports_multiple_toolsets = gyp.common.CrossCompileRequested() - -def StripPrefix(arg, prefix): - if arg.startswith(prefix): - return arg[len(prefix):] - return arg - - -def QuoteShellArgument(arg, flavor): - """Quote a string such that it will be interpreted as a single argument - by the shell.""" - # Rather than attempting to enumerate the bad shell characters, just - # whitelist common OK ones and quote anything else. - if re.match(r'^[a-zA-Z0-9_=.\\/-]+$', arg): - return arg # No quoting necessary. - if flavor == 'win': - return gyp.msvs_emulation.QuoteForRspFile(arg) - return "'" + arg.replace("'", "'" + '"\'"' + "'") + "'" - - -def Define(d, flavor): - """Takes a preprocessor define and returns a -D parameter that's ninja- and - shell-escaped.""" - if flavor == 'win': - # cl.exe replaces literal # characters with = in preprocesor definitions for - # some reason. Octal-encode to work around that. - d = d.replace('#', '\\%03o' % ord('#')) - return QuoteShellArgument(ninja_syntax.escape('-D' + d), flavor) - - -def AddArch(output, arch): - """Adds an arch string to an output path.""" - output, extension = os.path.splitext(output) - return '%s.%s%s' % (output, arch, extension) - - -class Target(object): - """Target represents the paths used within a single gyp target. - - Conceptually, building a single target A is a series of steps: - - 1) actions/rules/copies generates source/resources/etc. - 2) compiles generates .o files - 3) link generates a binary (library/executable) - 4) bundle merges the above in a mac bundle - - (Any of these steps can be optional.) - - From a build ordering perspective, a dependent target B could just - depend on the last output of this series of steps. - - But some dependent commands sometimes need to reach inside the box. - For example, when linking B it needs to get the path to the static - library generated by A. - - This object stores those paths. To keep things simple, member - variables only store concrete paths to single files, while methods - compute derived values like "the last output of the target". - """ - def __init__(self, type): - # Gyp type ("static_library", etc.) of this target. - self.type = type - # File representing whether any input dependencies necessary for - # dependent actions have completed. - self.preaction_stamp = None - # File representing whether any input dependencies necessary for - # dependent compiles have completed. - self.precompile_stamp = None - # File representing the completion of actions/rules/copies, if any. - self.actions_stamp = None - # Path to the output of the link step, if any. - self.binary = None - # Path to the file representing the completion of building the bundle, - # if any. - self.bundle = None - # On Windows, incremental linking requires linking against all the .objs - # that compose a .lib (rather than the .lib itself). That list is stored - # here. In this case, we also need to save the compile_deps for the target, - # so that the target that directly depends on the .objs can also depend - # on those. - self.component_objs = None - self.compile_deps = None - # Windows only. The import .lib is the output of a build step, but - # because dependents only link against the lib (not both the lib and the - # dll) we keep track of the import library here. - self.import_lib = None - - def Linkable(self): - """Return true if this is a target that can be linked against.""" - return self.type in ('static_library', 'shared_library') - - def UsesToc(self, flavor): - """Return true if the target should produce a restat rule based on a TOC - file.""" - # For bundles, the .TOC should be produced for the binary, not for - # FinalOutput(). But the naive approach would put the TOC file into the - # bundle, so don't do this for bundles for now. - if flavor == 'win' or self.bundle: - return False - return self.type in ('shared_library', 'loadable_module') - - def PreActionInput(self, flavor): - """Return the path, if any, that should be used as a dependency of - any dependent action step.""" - if self.UsesToc(flavor): - return self.FinalOutput() + '.TOC' - return self.FinalOutput() or self.preaction_stamp - - def PreCompileInput(self): - """Return the path, if any, that should be used as a dependency of - any dependent compile step.""" - return self.actions_stamp or self.precompile_stamp - - def FinalOutput(self): - """Return the last output of the target, which depends on all prior - steps.""" - return self.bundle or self.binary or self.actions_stamp - - -# A small discourse on paths as used within the Ninja build: -# All files we produce (both at gyp and at build time) appear in the -# build directory (e.g. out/Debug). -# -# Paths within a given .gyp file are always relative to the directory -# containing the .gyp file. Call these "gyp paths". This includes -# sources as well as the starting directory a given gyp rule/action -# expects to be run from. We call the path from the source root to -# the gyp file the "base directory" within the per-.gyp-file -# NinjaWriter code. -# -# All paths as written into the .ninja files are relative to the build -# directory. Call these paths "ninja paths". -# -# We translate between these two notions of paths with two helper -# functions: -# -# - GypPathToNinja translates a gyp path (i.e. relative to the .gyp file) -# into the equivalent ninja path. -# -# - GypPathToUniqueOutput translates a gyp path into a ninja path to write -# an output file; the result can be namespaced such that it is unique -# to the input file name as well as the output target name. - -class NinjaWriter(object): - def __init__(self, hash_for_rules, target_outputs, base_dir, build_dir, - output_file, toplevel_build, output_file_name, flavor, - toplevel_dir=None): - """ - base_dir: path from source root to directory containing this gyp file, - by gyp semantics, all input paths are relative to this - build_dir: path from source root to build output - toplevel_dir: path to the toplevel directory - """ - - self.hash_for_rules = hash_for_rules - self.target_outputs = target_outputs - self.base_dir = base_dir - self.build_dir = build_dir - self.ninja = ninja_syntax.Writer(output_file) - self.toplevel_build = toplevel_build - self.output_file_name = output_file_name - - self.flavor = flavor - self.abs_build_dir = None - if toplevel_dir is not None: - self.abs_build_dir = os.path.abspath(os.path.join(toplevel_dir, - build_dir)) - self.obj_ext = '.obj' if flavor == 'win' else '.o' - if flavor == 'win': - # See docstring of msvs_emulation.GenerateEnvironmentFiles(). - self.win_env = {} - for arch in ('x86', 'x64'): - self.win_env[arch] = 'environment.' + arch - - # Relative path from build output dir to base dir. - build_to_top = gyp.common.InvertRelativePath(build_dir, toplevel_dir) - self.build_to_base = os.path.join(build_to_top, base_dir) - # Relative path from base dir to build dir. - base_to_top = gyp.common.InvertRelativePath(base_dir, toplevel_dir) - self.base_to_build = os.path.join(base_to_top, build_dir) - - def ExpandSpecial(self, path, product_dir=None): - """Expand specials like $!PRODUCT_DIR in |path|. - - If |product_dir| is None, assumes the cwd is already the product - dir. Otherwise, |product_dir| is the relative path to the product - dir. - """ - - PRODUCT_DIR = '$!PRODUCT_DIR' - if PRODUCT_DIR in path: - if product_dir: - path = path.replace(PRODUCT_DIR, product_dir) - else: - path = path.replace(PRODUCT_DIR + '/', '') - path = path.replace(PRODUCT_DIR + '\\', '') - path = path.replace(PRODUCT_DIR, '.') - - INTERMEDIATE_DIR = '$!INTERMEDIATE_DIR' - if INTERMEDIATE_DIR in path: - int_dir = self.GypPathToUniqueOutput('gen') - # GypPathToUniqueOutput generates a path relative to the product dir, - # so insert product_dir in front if it is provided. - path = path.replace(INTERMEDIATE_DIR, - os.path.join(product_dir or '', int_dir)) - - CONFIGURATION_NAME = '$|CONFIGURATION_NAME' - path = path.replace(CONFIGURATION_NAME, self.config_name) - - return path - - def ExpandRuleVariables(self, path, root, dirname, source, ext, name): - if self.flavor == 'win': - path = self.msvs_settings.ConvertVSMacros( - path, config=self.config_name) - path = path.replace(generator_default_variables['RULE_INPUT_ROOT'], root) - path = path.replace(generator_default_variables['RULE_INPUT_DIRNAME'], - dirname) - path = path.replace(generator_default_variables['RULE_INPUT_PATH'], source) - path = path.replace(generator_default_variables['RULE_INPUT_EXT'], ext) - path = path.replace(generator_default_variables['RULE_INPUT_NAME'], name) - return path - - def GypPathToNinja(self, path, env=None): - """Translate a gyp path to a ninja path, optionally expanding environment - variable references in |path| with |env|. - - See the above discourse on path conversions.""" - if env: - if self.flavor == 'mac': - path = gyp.xcode_emulation.ExpandEnvVars(path, env) - elif self.flavor == 'win': - path = gyp.msvs_emulation.ExpandMacros(path, env) - if path.startswith('$!'): - expanded = self.ExpandSpecial(path) - if self.flavor == 'win': - expanded = os.path.normpath(expanded) - return expanded - if '$|' in path: - path = self.ExpandSpecial(path) - assert '$' not in path, path - return os.path.normpath(os.path.join(self.build_to_base, path)) - - def GypPathToUniqueOutput(self, path, qualified=True): - """Translate a gyp path to a ninja path for writing output. - - If qualified is True, qualify the resulting filename with the name - of the target. This is necessary when e.g. compiling the same - path twice for two separate output targets. - - See the above discourse on path conversions.""" - - path = self.ExpandSpecial(path) - assert not path.startswith('$'), path - - # Translate the path following this scheme: - # Input: foo/bar.gyp, target targ, references baz/out.o - # Output: obj/foo/baz/targ.out.o (if qualified) - # obj/foo/baz/out.o (otherwise) - # (and obj.host instead of obj for cross-compiles) - # - # Why this scheme and not some other one? - # 1) for a given input, you can compute all derived outputs by matching - # its path, even if the input is brought via a gyp file with '..'. - # 2) simple files like libraries and stamps have a simple filename. - - obj = 'obj' - if self.toolset != 'target': - obj += '.' + self.toolset - - path_dir, path_basename = os.path.split(path) - assert not os.path.isabs(path_dir), ( - "'%s' can not be absolute path (see crbug.com/462153)." % path_dir) - - if qualified: - path_basename = self.name + '.' + path_basename - return os.path.normpath(os.path.join(obj, self.base_dir, path_dir, - path_basename)) - - def WriteCollapsedDependencies(self, name, targets, order_only=None): - """Given a list of targets, return a path for a single file - representing the result of building all the targets or None. - - Uses a stamp file if necessary.""" - - assert targets == filter(None, targets), targets - if len(targets) == 0: - assert not order_only - return None - if len(targets) > 1 or order_only: - stamp = self.GypPathToUniqueOutput(name + '.stamp') - targets = self.ninja.build(stamp, 'stamp', targets, order_only=order_only) - self.ninja.newline() - return targets[0] - - def _SubninjaNameForArch(self, arch): - output_file_base = os.path.splitext(self.output_file_name)[0] - return '%s.%s.ninja' % (output_file_base, arch) - - def WriteSpec(self, spec, config_name, generator_flags): - """The main entry point for NinjaWriter: write the build rules for a spec. - - Returns a Target object, which represents the output paths for this spec. - Returns None if there are no outputs (e.g. a settings-only 'none' type - target).""" - - self.config_name = config_name - self.name = spec['target_name'] - self.toolset = spec['toolset'] - config = spec['configurations'][config_name] - self.target = Target(spec['type']) - self.is_standalone_static_library = bool( - spec.get('standalone_static_library', 0)) - # Track if this target contains any C++ files, to decide if gcc or g++ - # should be used for linking. - self.uses_cpp = False - - self.is_mac_bundle = gyp.xcode_emulation.IsMacBundle(self.flavor, spec) - self.xcode_settings = self.msvs_settings = None - if self.flavor == 'mac': - self.xcode_settings = gyp.xcode_emulation.XcodeSettings(spec) - if self.flavor == 'win': - self.msvs_settings = gyp.msvs_emulation.MsvsSettings(spec, - generator_flags) - arch = self.msvs_settings.GetArch(config_name) - self.ninja.variable('arch', self.win_env[arch]) - self.ninja.variable('cc', '$cl_' + arch) - self.ninja.variable('cxx', '$cl_' + arch) - self.ninja.variable('cc_host', '$cl_' + arch) - self.ninja.variable('cxx_host', '$cl_' + arch) - self.ninja.variable('asm', '$ml_' + arch) - - if self.flavor == 'mac': - self.archs = self.xcode_settings.GetActiveArchs(config_name) - if len(self.archs) > 1: - self.arch_subninjas = dict( - (arch, ninja_syntax.Writer( - OpenOutput(os.path.join(self.toplevel_build, - self._SubninjaNameForArch(arch)), - 'w'))) - for arch in self.archs) - - # Compute predepends for all rules. - # actions_depends is the dependencies this target depends on before running - # any of its action/rule/copy steps. - # compile_depends is the dependencies this target depends on before running - # any of its compile steps. - actions_depends = [] - compile_depends = [] - # TODO(evan): it is rather confusing which things are lists and which - # are strings. Fix these. - if 'dependencies' in spec: - for dep in spec['dependencies']: - if dep in self.target_outputs: - target = self.target_outputs[dep] - actions_depends.append(target.PreActionInput(self.flavor)) - compile_depends.append(target.PreCompileInput()) - actions_depends = filter(None, actions_depends) - compile_depends = filter(None, compile_depends) - actions_depends = self.WriteCollapsedDependencies('actions_depends', - actions_depends) - compile_depends = self.WriteCollapsedDependencies('compile_depends', - compile_depends) - self.target.preaction_stamp = actions_depends - self.target.precompile_stamp = compile_depends - - # Write out actions, rules, and copies. These must happen before we - # compile any sources, so compute a list of predependencies for sources - # while we do it. - extra_sources = [] - mac_bundle_depends = [] - self.target.actions_stamp = self.WriteActionsRulesCopies( - spec, extra_sources, actions_depends, mac_bundle_depends) - - # If we have actions/rules/copies, we depend directly on those, but - # otherwise we depend on dependent target's actions/rules/copies etc. - # We never need to explicitly depend on previous target's link steps, - # because no compile ever depends on them. - compile_depends_stamp = (self.target.actions_stamp or compile_depends) - - # Write out the compilation steps, if any. - link_deps = [] - sources = extra_sources + spec.get('sources', []) - if sources: - if self.flavor == 'mac' and len(self.archs) > 1: - # Write subninja file containing compile and link commands scoped to - # a single arch if a fat binary is being built. - for arch in self.archs: - self.ninja.subninja(self._SubninjaNameForArch(arch)) - - pch = None - if self.flavor == 'win': - gyp.msvs_emulation.VerifyMissingSources( - sources, self.abs_build_dir, generator_flags, self.GypPathToNinja) - pch = gyp.msvs_emulation.PrecompiledHeader( - self.msvs_settings, config_name, self.GypPathToNinja, - self.GypPathToUniqueOutput, self.obj_ext) - else: - pch = gyp.xcode_emulation.MacPrefixHeader( - self.xcode_settings, self.GypPathToNinja, - lambda path, lang: self.GypPathToUniqueOutput(path + '-' + lang)) - link_deps = self.WriteSources( - self.ninja, config_name, config, sources, compile_depends_stamp, pch, - spec) - # Some actions/rules output 'sources' that are already object files. - obj_outputs = [f for f in sources if f.endswith(self.obj_ext)] - if obj_outputs: - if self.flavor != 'mac' or len(self.archs) == 1: - link_deps += [self.GypPathToNinja(o) for o in obj_outputs] - else: - print "Warning: Actions/rules writing object files don't work with " \ - "multiarch targets, dropping. (target %s)" % spec['target_name'] - elif self.flavor == 'mac' and len(self.archs) > 1: - link_deps = collections.defaultdict(list) - - compile_deps = self.target.actions_stamp or actions_depends - if self.flavor == 'win' and self.target.type == 'static_library': - self.target.component_objs = link_deps - self.target.compile_deps = compile_deps - - # Write out a link step, if needed. - output = None - is_empty_bundle = not link_deps and not mac_bundle_depends - if link_deps or self.target.actions_stamp or actions_depends: - output = self.WriteTarget(spec, config_name, config, link_deps, - compile_deps) - if self.is_mac_bundle: - mac_bundle_depends.append(output) - - # Bundle all of the above together, if needed. - if self.is_mac_bundle: - output = self.WriteMacBundle(spec, mac_bundle_depends, is_empty_bundle) - - if not output: - return None - - assert self.target.FinalOutput(), output - return self.target - - def _WinIdlRule(self, source, prebuild, outputs): - """Handle the implicit VS .idl rule for one source file. Fills |outputs| - with files that are generated.""" - outdir, output, vars, flags = self.msvs_settings.GetIdlBuildData( - source, self.config_name) - outdir = self.GypPathToNinja(outdir) - def fix_path(path, rel=None): - path = os.path.join(outdir, path) - dirname, basename = os.path.split(source) - root, ext = os.path.splitext(basename) - path = self.ExpandRuleVariables( - path, root, dirname, source, ext, basename) - if rel: - path = os.path.relpath(path, rel) - return path - vars = [(name, fix_path(value, outdir)) for name, value in vars] - output = [fix_path(p) for p in output] - vars.append(('outdir', outdir)) - vars.append(('idlflags', flags)) - input = self.GypPathToNinja(source) - self.ninja.build(output, 'idl', input, - variables=vars, order_only=prebuild) - outputs.extend(output) - - def WriteWinIdlFiles(self, spec, prebuild): - """Writes rules to match MSVS's implicit idl handling.""" - assert self.flavor == 'win' - if self.msvs_settings.HasExplicitIdlRulesOrActions(spec): - return [] - outputs = [] - for source in filter(lambda x: x.endswith('.idl'), spec['sources']): - self._WinIdlRule(source, prebuild, outputs) - return outputs - - def WriteActionsRulesCopies(self, spec, extra_sources, prebuild, - mac_bundle_depends): - """Write out the Actions, Rules, and Copies steps. Return a path - representing the outputs of these steps.""" - outputs = [] - if self.is_mac_bundle: - mac_bundle_resources = spec.get('mac_bundle_resources', [])[:] - else: - mac_bundle_resources = [] - extra_mac_bundle_resources = [] - - if 'actions' in spec: - outputs += self.WriteActions(spec['actions'], extra_sources, prebuild, - extra_mac_bundle_resources) - if 'rules' in spec: - outputs += self.WriteRules(spec['rules'], extra_sources, prebuild, - mac_bundle_resources, - extra_mac_bundle_resources) - if 'copies' in spec: - outputs += self.WriteCopies(spec['copies'], prebuild, mac_bundle_depends) - - if 'sources' in spec and self.flavor == 'win': - outputs += self.WriteWinIdlFiles(spec, prebuild) - - stamp = self.WriteCollapsedDependencies('actions_rules_copies', outputs) - - if self.is_mac_bundle: - xcassets = self.WriteMacBundleResources( - extra_mac_bundle_resources + mac_bundle_resources, mac_bundle_depends) - partial_info_plist = self.WriteMacXCassets(xcassets, mac_bundle_depends) - self.WriteMacInfoPlist(partial_info_plist, mac_bundle_depends) - - return stamp - - def GenerateDescription(self, verb, message, fallback): - """Generate and return a description of a build step. - - |verb| is the short summary, e.g. ACTION or RULE. - |message| is a hand-written description, or None if not available. - |fallback| is the gyp-level name of the step, usable as a fallback. - """ - if self.toolset != 'target': - verb += '(%s)' % self.toolset - if message: - return '%s %s' % (verb, self.ExpandSpecial(message)) - else: - return '%s %s: %s' % (verb, self.name, fallback) - - def WriteActions(self, actions, extra_sources, prebuild, - extra_mac_bundle_resources): - # Actions cd into the base directory. - env = self.GetToolchainEnv() - all_outputs = [] - for action in actions: - # First write out a rule for the action. - name = '%s_%s' % (action['action_name'], self.hash_for_rules) - description = self.GenerateDescription('ACTION', - action.get('message', None), - name) - is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(action) - if self.flavor == 'win' else False) - args = action['action'] - depfile = action.get('depfile', None) - if depfile: - depfile = self.ExpandSpecial(depfile, self.base_to_build) - pool = 'console' if int(action.get('ninja_use_console', 0)) else None - rule_name, _ = self.WriteNewNinjaRule(name, args, description, - is_cygwin, env, pool, - depfile=depfile) - - inputs = [self.GypPathToNinja(i, env) for i in action['inputs']] - if int(action.get('process_outputs_as_sources', False)): - extra_sources += action['outputs'] - if int(action.get('process_outputs_as_mac_bundle_resources', False)): - extra_mac_bundle_resources += action['outputs'] - outputs = [self.GypPathToNinja(o, env) for o in action['outputs']] - - # Then write out an edge using the rule. - self.ninja.build(outputs, rule_name, inputs, - order_only=prebuild) - all_outputs += outputs - - self.ninja.newline() - - return all_outputs - - def WriteRules(self, rules, extra_sources, prebuild, - mac_bundle_resources, extra_mac_bundle_resources): - env = self.GetToolchainEnv() - all_outputs = [] - for rule in rules: - # Skip a rule with no action and no inputs. - if 'action' not in rule and not rule.get('rule_sources', []): - continue - - # First write out a rule for the rule action. - name = '%s_%s' % (rule['rule_name'], self.hash_for_rules) - - args = rule['action'] - description = self.GenerateDescription( - 'RULE', - rule.get('message', None), - ('%s ' + generator_default_variables['RULE_INPUT_PATH']) % name) - is_cygwin = (self.msvs_settings.IsRuleRunUnderCygwin(rule) - if self.flavor == 'win' else False) - pool = 'console' if int(rule.get('ninja_use_console', 0)) else None - rule_name, args = self.WriteNewNinjaRule( - name, args, description, is_cygwin, env, pool) - - # TODO: if the command references the outputs directly, we should - # simplify it to just use $out. - - # Rules can potentially make use of some special variables which - # must vary per source file. - # Compute the list of variables we'll need to provide. - special_locals = ('source', 'root', 'dirname', 'ext', 'name') - needed_variables = set(['source']) - for argument in args: - for var in special_locals: - if '${%s}' % var in argument: - needed_variables.add(var) - - def cygwin_munge(path): - # pylint: disable=cell-var-from-loop - if is_cygwin: - return path.replace('\\', '/') - return path - - inputs = [self.GypPathToNinja(i, env) for i in rule.get('inputs', [])] - - # If there are n source files matching the rule, and m additional rule - # inputs, then adding 'inputs' to each build edge written below will - # write m * n inputs. Collapsing reduces this to m + n. - sources = rule.get('rule_sources', []) - num_inputs = len(inputs) - if prebuild: - num_inputs += 1 - if num_inputs > 2 and len(sources) > 2: - inputs = [self.WriteCollapsedDependencies( - rule['rule_name'], inputs, order_only=prebuild)] - prebuild = [] - - # For each source file, write an edge that generates all the outputs. - for source in sources: - source = os.path.normpath(source) - dirname, basename = os.path.split(source) - root, ext = os.path.splitext(basename) - - # Gather the list of inputs and outputs, expanding $vars if possible. - outputs = [self.ExpandRuleVariables(o, root, dirname, - source, ext, basename) - for o in rule['outputs']] - - if int(rule.get('process_outputs_as_sources', False)): - extra_sources += outputs - - was_mac_bundle_resource = source in mac_bundle_resources - if was_mac_bundle_resource or \ - int(rule.get('process_outputs_as_mac_bundle_resources', False)): - extra_mac_bundle_resources += outputs - # Note: This is n_resources * n_outputs_in_rule. Put to-be-removed - # items in a set and remove them all in a single pass if this becomes - # a performance issue. - if was_mac_bundle_resource: - mac_bundle_resources.remove(source) - - extra_bindings = [] - for var in needed_variables: - if var == 'root': - extra_bindings.append(('root', cygwin_munge(root))) - elif var == 'dirname': - # '$dirname' is a parameter to the rule action, which means - # it shouldn't be converted to a Ninja path. But we don't - # want $!PRODUCT_DIR in there either. - dirname_expanded = self.ExpandSpecial(dirname, self.base_to_build) - extra_bindings.append(('dirname', cygwin_munge(dirname_expanded))) - elif var == 'source': - # '$source' is a parameter to the rule action, which means - # it shouldn't be converted to a Ninja path. But we don't - # want $!PRODUCT_DIR in there either. - source_expanded = self.ExpandSpecial(source, self.base_to_build) - extra_bindings.append(('source', cygwin_munge(source_expanded))) - elif var == 'ext': - extra_bindings.append(('ext', ext)) - elif var == 'name': - extra_bindings.append(('name', cygwin_munge(basename))) - else: - assert var == None, repr(var) - - outputs = [self.GypPathToNinja(o, env) for o in outputs] - if self.flavor == 'win': - # WriteNewNinjaRule uses unique_name for creating an rsp file on win. - extra_bindings.append(('unique_name', - hashlib.md5(outputs[0]).hexdigest())) - self.ninja.build(outputs, rule_name, self.GypPathToNinja(source), - implicit=inputs, - order_only=prebuild, - variables=extra_bindings) - - all_outputs.extend(outputs) - - return all_outputs - - def WriteCopies(self, copies, prebuild, mac_bundle_depends): - outputs = [] - env = self.GetToolchainEnv() - for copy in copies: - for path in copy['files']: - # Normalize the path so trailing slashes don't confuse us. - path = os.path.normpath(path) - basename = os.path.split(path)[1] - src = self.GypPathToNinja(path, env) - dst = self.GypPathToNinja(os.path.join(copy['destination'], basename), - env) - outputs += self.ninja.build(dst, 'copy', src, order_only=prebuild) - if self.is_mac_bundle: - # gyp has mac_bundle_resources to copy things into a bundle's - # Resources folder, but there's no built-in way to copy files to other - # places in the bundle. Hence, some targets use copies for this. Check - # if this file is copied into the current bundle, and if so add it to - # the bundle depends so that dependent targets get rebuilt if the copy - # input changes. - if dst.startswith(self.xcode_settings.GetBundleContentsFolderPath()): - mac_bundle_depends.append(dst) - - return outputs - - def WriteMacBundleResources(self, resources, bundle_depends): - """Writes ninja edges for 'mac_bundle_resources'.""" - xcassets = [] - for output, res in gyp.xcode_emulation.GetMacBundleResources( - generator_default_variables['PRODUCT_DIR'], - self.xcode_settings, map(self.GypPathToNinja, resources)): - output = self.ExpandSpecial(output) - if os.path.splitext(output)[-1] != '.xcassets': - isBinary = self.xcode_settings.IsBinaryOutputFormat(self.config_name) - self.ninja.build(output, 'mac_tool', res, - variables=[('mactool_cmd', 'copy-bundle-resource'), \ - ('binary', isBinary)]) - bundle_depends.append(output) - else: - xcassets.append(res) - return xcassets - - def WriteMacXCassets(self, xcassets, bundle_depends): - """Writes ninja edges for 'mac_bundle_resources' .xcassets files. - - This add an invocation of 'actool' via the 'mac_tool.py' helper script. - It assumes that the assets catalogs define at least one imageset and - thus an Assets.car file will be generated in the application resources - directory. If this is not the case, then the build will probably be done - at each invocation of ninja.""" - if not xcassets: - return - - extra_arguments = {} - settings_to_arg = { - 'XCASSETS_APP_ICON': 'app-icon', - 'XCASSETS_LAUNCH_IMAGE': 'launch-image', - } - settings = self.xcode_settings.xcode_settings[self.config_name] - for settings_key, arg_name in settings_to_arg.iteritems(): - value = settings.get(settings_key) - if value: - extra_arguments[arg_name] = value - - partial_info_plist = None - if extra_arguments: - partial_info_plist = self.GypPathToUniqueOutput( - 'assetcatalog_generated_info.plist') - extra_arguments['output-partial-info-plist'] = partial_info_plist - - outputs = [] - outputs.append( - os.path.join( - self.xcode_settings.GetBundleResourceFolder(), - 'Assets.car')) - if partial_info_plist: - outputs.append(partial_info_plist) - - keys = QuoteShellArgument(json.dumps(extra_arguments), self.flavor) - extra_env = self.xcode_settings.GetPerTargetSettings() - env = self.GetSortedXcodeEnv(additional_settings=extra_env) - env = self.ComputeExportEnvString(env) - - bundle_depends.extend(self.ninja.build( - outputs, 'compile_xcassets', xcassets, - variables=[('env', env), ('keys', keys)])) - return partial_info_plist - - def WriteMacInfoPlist(self, partial_info_plist, bundle_depends): - """Write build rules for bundle Info.plist files.""" - info_plist, out, defines, extra_env = gyp.xcode_emulation.GetMacInfoPlist( - generator_default_variables['PRODUCT_DIR'], - self.xcode_settings, self.GypPathToNinja) - if not info_plist: - return - out = self.ExpandSpecial(out) - if defines: - # Create an intermediate file to store preprocessed results. - intermediate_plist = self.GypPathToUniqueOutput( - os.path.basename(info_plist)) - defines = ' '.join([Define(d, self.flavor) for d in defines]) - info_plist = self.ninja.build( - intermediate_plist, 'preprocess_infoplist', info_plist, - variables=[('defines',defines)]) - - env = self.GetSortedXcodeEnv(additional_settings=extra_env) - env = self.ComputeExportEnvString(env) - - if partial_info_plist: - intermediate_plist = self.GypPathToUniqueOutput('merged_info.plist') - info_plist = self.ninja.build( - intermediate_plist, 'merge_infoplist', - [partial_info_plist, info_plist]) - - keys = self.xcode_settings.GetExtraPlistItems(self.config_name) - keys = QuoteShellArgument(json.dumps(keys), self.flavor) - isBinary = self.xcode_settings.IsBinaryOutputFormat(self.config_name) - self.ninja.build(out, 'copy_infoplist', info_plist, - variables=[('env', env), ('keys', keys), - ('binary', isBinary)]) - bundle_depends.append(out) - - def WriteSources(self, ninja_file, config_name, config, sources, predepends, - precompiled_header, spec): - """Write build rules to compile all of |sources|.""" - if self.toolset == 'host': - self.ninja.variable('ar', '$ar_host') - self.ninja.variable('cc', '$cc_host') - self.ninja.variable('cxx', '$cxx_host') - self.ninja.variable('ld', '$ld_host') - self.ninja.variable('ldxx', '$ldxx_host') - self.ninja.variable('nm', '$nm_host') - self.ninja.variable('readelf', '$readelf_host') - - if self.flavor != 'mac' or len(self.archs) == 1: - return self.WriteSourcesForArch( - self.ninja, config_name, config, sources, predepends, - precompiled_header, spec) - else: - return dict((arch, self.WriteSourcesForArch( - self.arch_subninjas[arch], config_name, config, sources, predepends, - precompiled_header, spec, arch=arch)) - for arch in self.archs) - - def WriteSourcesForArch(self, ninja_file, config_name, config, sources, - predepends, precompiled_header, spec, arch=None): - """Write build rules to compile all of |sources|.""" - - extra_defines = [] - if self.flavor == 'mac': - cflags = self.xcode_settings.GetCflags(config_name, arch=arch) - cflags_c = self.xcode_settings.GetCflagsC(config_name) - cflags_cc = self.xcode_settings.GetCflagsCC(config_name) - cflags_objc = ['$cflags_c'] + \ - self.xcode_settings.GetCflagsObjC(config_name) - cflags_objcc = ['$cflags_cc'] + \ - self.xcode_settings.GetCflagsObjCC(config_name) - elif self.flavor == 'win': - asmflags = self.msvs_settings.GetAsmflags(config_name) - cflags = self.msvs_settings.GetCflags(config_name) - cflags_c = self.msvs_settings.GetCflagsC(config_name) - cflags_cc = self.msvs_settings.GetCflagsCC(config_name) - extra_defines = self.msvs_settings.GetComputedDefines(config_name) - # 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_c: - obj = 'obj' - if self.toolset != 'target': - obj += '.' + self.toolset - 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', []) - cflags_c = config.get('cflags_c', []) - cflags_cc = config.get('cflags_cc', []) - - # Respect environment variables related to build, but target-specific - # flags can still override them. - if self.toolset == 'target': - cflags_c = (os.environ.get('CPPFLAGS', '').split() + - os.environ.get('CFLAGS', '').split() + cflags_c) - cflags_cc = (os.environ.get('CPPFLAGS', '').split() + - os.environ.get('CXXFLAGS', '').split() + cflags_cc) - elif self.toolset == 'host': - cflags_c = (os.environ.get('CPPFLAGS_host', '').split() + - os.environ.get('CFLAGS_host', '').split() + cflags_c) - cflags_cc = (os.environ.get('CPPFLAGS_host', '').split() + - os.environ.get('CXXFLAGS_host', '').split() + cflags_cc) - - defines = config.get('defines', []) + extra_defines - self.WriteVariableList(ninja_file, 'defines', - [Define(d, self.flavor) for d in defines]) - if self.flavor == 'win': - self.WriteVariableList(ninja_file, 'asmflags', - map(self.ExpandSpecial, asmflags)) - self.WriteVariableList(ninja_file, 'rcflags', - [QuoteShellArgument(self.ExpandSpecial(f), self.flavor) - for f in self.msvs_settings.GetRcflags(config_name, - self.GypPathToNinja)]) - - include_dirs = config.get('include_dirs', []) - - env = self.GetToolchainEnv() - if self.flavor == 'win': - include_dirs = self.msvs_settings.AdjustIncludeDirs(include_dirs, - config_name) - self.WriteVariableList(ninja_file, 'includes', - [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor) - for i in include_dirs]) - - if self.flavor == 'win': - midl_include_dirs = config.get('midl_include_dirs', []) - midl_include_dirs = self.msvs_settings.AdjustMidlIncludeDirs( - midl_include_dirs, config_name) - self.WriteVariableList(ninja_file, 'midl_includes', - [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor) - for i in midl_include_dirs]) - - pch_commands = precompiled_header.GetPchBuildCommands(arch) - if self.flavor == 'mac': - # Most targets use no precompiled headers, so only write these if needed. - for ext, var in [('c', 'cflags_pch_c'), ('cc', 'cflags_pch_cc'), - ('m', 'cflags_pch_objc'), ('mm', 'cflags_pch_objcc')]: - include = precompiled_header.GetInclude(ext, arch) - if include: ninja_file.variable(var, include) - - arflags = config.get('arflags', []) - - self.WriteVariableList(ninja_file, 'cflags', - map(self.ExpandSpecial, cflags)) - self.WriteVariableList(ninja_file, 'cflags_c', - map(self.ExpandSpecial, cflags_c)) - self.WriteVariableList(ninja_file, 'cflags_cc', - map(self.ExpandSpecial, cflags_cc)) - if self.flavor == 'mac': - self.WriteVariableList(ninja_file, 'cflags_objc', - map(self.ExpandSpecial, cflags_objc)) - self.WriteVariableList(ninja_file, 'cflags_objcc', - map(self.ExpandSpecial, cflags_objcc)) - self.WriteVariableList(ninja_file, 'arflags', - map(self.ExpandSpecial, arflags)) - ninja_file.newline() - outputs = [] - has_rc_source = False - for source in sources: - filename, ext = os.path.splitext(source) - ext = ext[1:] - obj_ext = self.obj_ext - if ext in ('cc', 'cpp', 'cxx'): - command = 'cxx' - self.uses_cpp = True - elif ext == 'c' or (ext == 'S' and self.flavor != 'win'): - command = 'cc' - elif ext == 's' and self.flavor != 'win': # Doesn't generate .o.d files. - command = 'cc_s' - elif (self.flavor == 'win' and ext == 'asm' and - not self.msvs_settings.HasExplicitAsmRules(spec)): - command = 'asm' - # Add the _asm suffix as msvs is capable of handling .cc and - # .asm files of the same name without collision. - obj_ext = '_asm.obj' - elif self.flavor == 'mac' and ext == 'm': - command = 'objc' - elif self.flavor == 'mac' and ext == 'mm': - command = 'objcxx' - self.uses_cpp = True - elif self.flavor == 'win' and ext == 'rc': - command = 'rc' - obj_ext = '.res' - has_rc_source = True - else: - # Ignore unhandled extensions. - continue - input = self.GypPathToNinja(source) - output = self.GypPathToUniqueOutput(filename + obj_ext) - if arch is not None: - output = AddArch(output, arch) - implicit = precompiled_header.GetObjDependencies([input], [output], arch) - variables = [] - if self.flavor == 'win': - variables, output, implicit = precompiled_header.GetFlagsModifications( - input, output, implicit, command, cflags_c, cflags_cc, - self.ExpandSpecial) - ninja_file.build(output, command, input, - implicit=[gch for _, _, gch in implicit], - order_only=predepends, variables=variables) - outputs.append(output) - - if has_rc_source: - resource_include_dirs = config.get('resource_include_dirs', include_dirs) - self.WriteVariableList(ninja_file, 'resource_includes', - [QuoteShellArgument('-I' + self.GypPathToNinja(i, env), self.flavor) - for i in resource_include_dirs]) - - self.WritePchTargets(ninja_file, pch_commands) - - ninja_file.newline() - return outputs - - def WritePchTargets(self, ninja_file, pch_commands): - """Writes ninja rules to compile prefix headers.""" - if not pch_commands: - return - - for gch, lang_flag, lang, input in pch_commands: - var_name = { - 'c': 'cflags_pch_c', - 'cc': 'cflags_pch_cc', - 'm': 'cflags_pch_objc', - 'mm': 'cflags_pch_objcc', - }[lang] - - map = { 'c': 'cc', 'cc': 'cxx', 'm': 'objc', 'mm': 'objcxx', } - cmd = map.get(lang) - ninja_file.build(gch, cmd, input, variables=[(var_name, lang_flag)]) - - def WriteLink(self, spec, config_name, config, link_deps): - """Write out a link step. Fills out target.binary. """ - if self.flavor != 'mac' or len(self.archs) == 1: - return self.WriteLinkForArch( - self.ninja, spec, config_name, config, link_deps) - else: - output = self.ComputeOutput(spec) - inputs = [self.WriteLinkForArch(self.arch_subninjas[arch], spec, - config_name, config, link_deps[arch], - arch=arch) - for arch in self.archs] - extra_bindings = [] - build_output = output - if not self.is_mac_bundle: - self.AppendPostbuildVariable(extra_bindings, spec, output, output) - - # TODO(yyanagisawa): more work needed to fix: - # https://code.google.com/p/gyp/issues/detail?id=411 - if (spec['type'] in ('shared_library', 'loadable_module') and - not self.is_mac_bundle): - extra_bindings.append(('lib', output)) - self.ninja.build([output, output + '.TOC'], 'solipo', inputs, - variables=extra_bindings) - else: - self.ninja.build(build_output, 'lipo', inputs, variables=extra_bindings) - return output - - def WriteLinkForArch(self, ninja_file, spec, config_name, config, - link_deps, arch=None): - """Write out a link step. Fills out target.binary. """ - command = { - 'executable': 'link', - 'loadable_module': 'solink_module', - 'shared_library': 'solink', - }[spec['type']] - command_suffix = '' - - implicit_deps = set() - solibs = set() - order_deps = set() - - if 'dependencies' in spec: - # Two kinds of dependencies: - # - Linkable dependencies (like a .a or a .so): add them to the link line. - # - Non-linkable dependencies (like a rule that generates a file - # and writes a stamp file): add them to implicit_deps - extra_link_deps = set() - for dep in spec['dependencies']: - target = self.target_outputs.get(dep) - if not target: - continue - linkable = target.Linkable() - if linkable: - new_deps = [] - if (self.flavor == 'win' and - target.component_objs and - self.msvs_settings.IsUseLibraryDependencyInputs(config_name)): - new_deps = target.component_objs - if target.compile_deps: - order_deps.add(target.compile_deps) - elif self.flavor == 'win' and target.import_lib: - new_deps = [target.import_lib] - elif target.UsesToc(self.flavor): - solibs.add(target.binary) - implicit_deps.add(target.binary + '.TOC') - else: - new_deps = [target.binary] - for new_dep in new_deps: - if new_dep not in extra_link_deps: - extra_link_deps.add(new_dep) - link_deps.append(new_dep) - - final_output = target.FinalOutput() - if not linkable or final_output != target.binary: - implicit_deps.add(final_output) - - extra_bindings = [] - if self.uses_cpp and self.flavor != 'win': - extra_bindings.append(('ld', '$ldxx')) - - output = self.ComputeOutput(spec, arch) - if arch is None and not self.is_mac_bundle: - self.AppendPostbuildVariable(extra_bindings, spec, output, output) - - is_executable = spec['type'] == 'executable' - # The ldflags config key is not used on mac or win. On those platforms - # linker flags are set via xcode_settings and msvs_settings, respectively. - env_ldflags = os.environ.get('LDFLAGS', '').split() - if self.flavor == 'mac': - ldflags = self.xcode_settings.GetLdflags(config_name, - self.ExpandSpecial(generator_default_variables['PRODUCT_DIR']), - self.GypPathToNinja, arch) - ldflags = env_ldflags + ldflags - elif self.flavor == 'win': - manifest_base_name = self.GypPathToUniqueOutput( - self.ComputeOutputFileName(spec)) - 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)) - def_file = self.msvs_settings.GetDefFile(self.GypPathToNinja) - if def_file: - implicit_deps.add(def_file) - else: - # Respect environment variables related to build, but target-specific - # flags can still override them. - ldflags = env_ldflags + config.get('ldflags', []) - if is_executable and len(solibs): - rpath = 'lib/' - if self.toolset != 'target': - rpath += self.toolset - ldflags.append(r'-Wl,-rpath=\$$ORIGIN/%s' % rpath) - ldflags.append('-Wl,-rpath-link=%s' % rpath) - self.WriteVariableList(ninja_file, 'ldflags', - map(self.ExpandSpecial, ldflags)) - - library_dirs = config.get('library_dirs', []) - if self.flavor == 'win': - library_dirs = [self.msvs_settings.ConvertVSMacros(l, config_name) - for l in library_dirs] - library_dirs = ['/LIBPATH:' + QuoteShellArgument(self.GypPathToNinja(l), - self.flavor) - for l in library_dirs] - else: - library_dirs = [QuoteShellArgument('-L' + self.GypPathToNinja(l), - self.flavor) - for l in library_dirs] - - libraries = gyp.common.uniquer(map(self.ExpandSpecial, - spec.get('libraries', []))) - if self.flavor == 'mac': - libraries = self.xcode_settings.AdjustLibraries(libraries, config_name) - elif self.flavor == 'win': - libraries = self.msvs_settings.AdjustLibraries(libraries) - - self.WriteVariableList(ninja_file, 'libs', library_dirs + libraries) - - linked_binary = output - - if command in ('solink', 'solink_module'): - extra_bindings.append(('soname', os.path.split(output)[1])) - extra_bindings.append(('lib', - gyp.common.EncodePOSIXShellArgument(output))) - if self.flavor != 'win': - link_file_list = output - if self.is_mac_bundle: - # 'Dependency Framework.framework/Versions/A/Dependency Framework' -> - # 'Dependency Framework.framework.rsp' - link_file_list = self.xcode_settings.GetWrapperName() - if arch: - link_file_list += '.' + arch - link_file_list += '.rsp' - # If an rspfile contains spaces, ninja surrounds the filename with - # quotes around it and then passes it to open(), creating a file with - # quotes in its name (and when looking for the rsp file, the name - # makes it through bash which strips the quotes) :-/ - link_file_list = link_file_list.replace(' ', '_') - extra_bindings.append( - ('link_file_list', - gyp.common.EncodePOSIXShellArgument(link_file_list))) - if self.flavor == 'win': - extra_bindings.append(('binary', output)) - if ('/NOENTRY' not in ldflags and - not self.msvs_settings.GetNoImportLibrary(config_name)): - 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))) - - ninja_file.build(output, command + command_suffix, link_deps, - implicit=list(implicit_deps), - order_only=list(order_deps), - variables=extra_bindings) - return linked_binary - - def WriteTarget(self, spec, config_name, config, link_deps, compile_deps): - extra_link_deps = any(self.target_outputs.get(dep).Linkable() - for dep in spec.get('dependencies', []) - if dep in self.target_outputs) - if spec['type'] == 'none' or (not link_deps and not extra_link_deps): - # TODO(evan): don't call this function for 'none' target types, as - # it doesn't do anything, and we fake out a 'binary' with a stamp file. - self.target.binary = compile_deps - self.target.type = 'none' - elif spec['type'] == 'static_library': - self.target.binary = self.ComputeOutput(spec) - if (self.flavor not in ('mac', 'openbsd', 'netbsd', 'win') and not - self.is_standalone_static_library): - self.ninja.build(self.target.binary, 'alink_thin', link_deps, - order_only=compile_deps) - else: - variables = [] - if self.xcode_settings: - libtool_flags = self.xcode_settings.GetLibtoolflags(config_name) - if libtool_flags: - variables.append(('libtool_flags', libtool_flags)) - if self.msvs_settings: - libflags = self.msvs_settings.GetLibFlags(config_name, - self.GypPathToNinja) - variables.append(('libflags', libflags)) - - if self.flavor != 'mac' or len(self.archs) == 1: - self.AppendPostbuildVariable(variables, spec, - self.target.binary, self.target.binary) - self.ninja.build(self.target.binary, 'alink', link_deps, - order_only=compile_deps, variables=variables) - else: - inputs = [] - for arch in self.archs: - output = self.ComputeOutput(spec, arch) - self.arch_subninjas[arch].build(output, 'alink', link_deps[arch], - order_only=compile_deps, - variables=variables) - inputs.append(output) - # TODO: It's not clear if libtool_flags should be passed to the alink - # call that combines single-arch .a files into a fat .a file. - self.AppendPostbuildVariable(variables, spec, - self.target.binary, self.target.binary) - self.ninja.build(self.target.binary, 'alink', inputs, - # FIXME: test proving order_only=compile_deps isn't - # needed. - variables=variables) - else: - self.target.binary = self.WriteLink(spec, config_name, config, link_deps) - return self.target.binary - - def WriteMacBundle(self, spec, mac_bundle_depends, is_empty): - assert self.is_mac_bundle - package_framework = spec['type'] in ('shared_library', 'loadable_module') - output = self.ComputeMacBundleOutput() - if is_empty: - output += '.stamp' - variables = [] - self.AppendPostbuildVariable(variables, spec, output, self.target.binary, - is_command_start=not package_framework) - if package_framework and not is_empty: - variables.append(('version', self.xcode_settings.GetFrameworkVersion())) - self.ninja.build(output, 'package_framework', mac_bundle_depends, - variables=variables) - else: - self.ninja.build(output, 'stamp', mac_bundle_depends, - variables=variables) - self.target.bundle = output - return output - - def GetToolchainEnv(self, additional_settings=None): - """Returns the variables toolchain would set for build steps.""" - env = self.GetSortedXcodeEnv(additional_settings=additional_settings) - if self.flavor == 'win': - env = self.GetMsvsToolchainEnv( - additional_settings=additional_settings) - return env - - def GetMsvsToolchainEnv(self, additional_settings=None): - """Returns the variables Visual Studio would set for build steps.""" - return self.msvs_settings.GetVSMacroEnv('$!PRODUCT_DIR', - config=self.config_name) - - def GetSortedXcodeEnv(self, additional_settings=None): - """Returns the variables Xcode would set for build steps.""" - assert self.abs_build_dir - abs_build_dir = self.abs_build_dir - return gyp.xcode_emulation.GetSortedXcodeEnv( - self.xcode_settings, abs_build_dir, - os.path.join(abs_build_dir, self.build_to_base), self.config_name, - additional_settings) - - def GetSortedXcodePostbuildEnv(self): - """Returns the variables Xcode would set for postbuild steps.""" - postbuild_settings = {} - # CHROMIUM_STRIP_SAVE_FILE is a chromium-specific hack. - # TODO(thakis): It would be nice to have some general mechanism instead. - strip_save_file = self.xcode_settings.GetPerTargetSetting( - 'CHROMIUM_STRIP_SAVE_FILE') - if strip_save_file: - postbuild_settings['CHROMIUM_STRIP_SAVE_FILE'] = strip_save_file - return self.GetSortedXcodeEnv(additional_settings=postbuild_settings) - - def AppendPostbuildVariable(self, variables, spec, output, binary, - is_command_start=False): - """Adds a 'postbuild' variable if there is a postbuild for |output|.""" - postbuild = self.GetPostbuildCommand(spec, output, binary, is_command_start) - if postbuild: - variables.append(('postbuilds', postbuild)) - - def GetPostbuildCommand(self, spec, output, output_binary, is_command_start): - """Returns a shell command that runs all the postbuilds, and removes - |output| if any of them fails. If |is_command_start| is False, then the - returned string will start with ' && '.""" - if not self.xcode_settings or spec['type'] == 'none' or not output: - return '' - output = QuoteShellArgument(output, self.flavor) - postbuilds = gyp.xcode_emulation.GetSpecPostbuildCommands(spec, quiet=True) - if output_binary is not None: - postbuilds = self.xcode_settings.AddImplicitPostbuilds( - self.config_name, - os.path.normpath(os.path.join(self.base_to_build, output)), - QuoteShellArgument( - os.path.normpath(os.path.join(self.base_to_build, output_binary)), - self.flavor), - postbuilds, quiet=True) - - if not postbuilds: - return '' - # Postbuilds expect to be run in the gyp file's directory, so insert an - # implicit postbuild to cd to there. - postbuilds.insert(0, gyp.common.EncodePOSIXShellList( - ['cd', self.build_to_base])) - env = self.ComputeExportEnvString(self.GetSortedXcodePostbuildEnv()) - # G will be non-null if any postbuild fails. Run all postbuilds in a - # subshell. - commands = env + ' (' + \ - ' && '.join([ninja_syntax.escape(command) for command in postbuilds]) - command_string = (commands + '); G=$$?; ' - # Remove the final output if any postbuild failed. - '((exit $$G) || rm -rf %s) ' % output + '&& exit $$G)') - if is_command_start: - return '(' + command_string + ' && ' - else: - return '$ && (' + command_string - - def ComputeExportEnvString(self, env): - """Given an environment, returns a string looking like - 'export FOO=foo; export BAR="${FOO} bar;' - that exports |env| to the shell.""" - export_str = [] - for k, v in env: - export_str.append('export %s=%s;' % - (k, ninja_syntax.escape(gyp.common.EncodePOSIXShellArgument(v)))) - return ' '.join(export_str) - - def ComputeMacBundleOutput(self): - """Return the 'output' (full output path) to a bundle output directory.""" - assert self.is_mac_bundle - path = generator_default_variables['PRODUCT_DIR'] - return self.ExpandSpecial( - os.path.join(path, self.xcode_settings.GetWrapperName())) - - def ComputeOutputFileName(self, spec, type=None): - """Compute the filename of the final output for the current target.""" - if not type: - type = spec['type'] - - default_variables = copy.copy(generator_default_variables) - CalculateVariables(default_variables, {'flavor': self.flavor}) - - # Compute filename prefix: the product prefix, or a default for - # the product type. - DEFAULT_PREFIX = { - 'loadable_module': default_variables['SHARED_LIB_PREFIX'], - 'shared_library': default_variables['SHARED_LIB_PREFIX'], - 'static_library': default_variables['STATIC_LIB_PREFIX'], - 'executable': default_variables['EXECUTABLE_PREFIX'], - } - prefix = spec.get('product_prefix', DEFAULT_PREFIX.get(type, '')) - - # Compute filename extension: the product extension, or a default - # for the product type. - DEFAULT_EXTENSION = { - 'loadable_module': default_variables['SHARED_LIB_SUFFIX'], - 'shared_library': default_variables['SHARED_LIB_SUFFIX'], - 'static_library': default_variables['STATIC_LIB_SUFFIX'], - 'executable': default_variables['EXECUTABLE_SUFFIX'], - } - extension = spec.get('product_extension') - if extension: - extension = '.' + extension - else: - extension = DEFAULT_EXTENSION.get(type, '') - - if 'product_name' in spec: - # If we were given an explicit name, use that. - target = spec['product_name'] - else: - # Otherwise, derive a name from the target name. - target = spec['target_name'] - if prefix == 'lib': - # Snip out an extra 'lib' from libs if appropriate. - target = StripPrefix(target, 'lib') - - if type in ('static_library', 'loadable_module', 'shared_library', - 'executable'): - return '%s%s%s' % (prefix, target, extension) - elif type == 'none': - return '%s.stamp' % target - else: - raise Exception('Unhandled output type %s' % type) - - def ComputeOutput(self, spec, arch=None): - """Compute the path for the final output of the spec.""" - type = spec['type'] - - if self.flavor == 'win': - override = self.msvs_settings.GetOutputName(self.config_name, - self.ExpandSpecial) - if override: - return override - - if arch is None and self.flavor == 'mac' and type in ( - 'static_library', 'executable', 'shared_library', 'loadable_module'): - filename = self.xcode_settings.GetExecutablePath() - else: - filename = self.ComputeOutputFileName(spec, type) - - if arch is None and 'product_dir' in spec: - path = os.path.join(spec['product_dir'], filename) - return self.ExpandSpecial(path) - - # Some products go into the output root, libraries go into shared library - # dir, and everything else goes into the normal place. - type_in_output_root = ['executable', 'loadable_module'] - if self.flavor == 'mac' and self.toolset == 'target': - type_in_output_root += ['shared_library', 'static_library'] - elif self.flavor == 'win' and self.toolset == 'target': - type_in_output_root += ['shared_library'] - - if arch is not None: - # Make sure partial executables don't end up in a bundle or the regular - # output directory. - archdir = 'arch' - if self.toolset != 'target': - archdir = os.path.join('arch', '%s' % self.toolset) - return os.path.join(archdir, AddArch(filename, arch)) - elif type in type_in_output_root or self.is_standalone_static_library: - return filename - elif type == 'shared_library': - libdir = 'lib' - if self.toolset != 'target': - libdir = os.path.join('lib', '%s' % self.toolset) - return os.path.join(libdir, filename) - else: - return self.GypPathToUniqueOutput(filename, qualified=False) - - def WriteVariableList(self, ninja_file, var, values): - assert not isinstance(values, str) - if values is None: - values = [] - ninja_file.variable(var, ' '.join(values)) - - def WriteNewNinjaRule(self, name, args, description, is_cygwin, env, pool, - depfile=None): - """Write out a new ninja "rule" statement for a given command. - - Returns the name of the new rule, and a copy of |args| with variables - expanded.""" - - if self.flavor == 'win': - args = [self.msvs_settings.ConvertVSMacros( - arg, self.base_to_build, config=self.config_name) - for arg in args] - description = self.msvs_settings.ConvertVSMacros( - description, config=self.config_name) - elif self.flavor == 'mac': - # |env| is an empty list on non-mac. - args = [gyp.xcode_emulation.ExpandEnvVars(arg, env) for arg in args] - description = gyp.xcode_emulation.ExpandEnvVars(description, env) - - # TODO: we shouldn't need to qualify names; we do it because - # currently the ninja rule namespace is global, but it really - # should be scoped to the subninja. - rule_name = self.name - if self.toolset == 'target': - rule_name += '.' + self.toolset - rule_name += '.' + name - rule_name = re.sub('[^a-zA-Z0-9_]', '_', rule_name) - - # Remove variable references, but not if they refer to the magic rule - # variables. This is not quite right, as it also protects these for - # actions, not just for rules where they are valid. Good enough. - protect = [ '${root}', '${dirname}', '${source}', '${ext}', '${name}' ] - protect = '(?!' + '|'.join(map(re.escape, protect)) + ')' - description = re.sub(protect + r'\$', '_', description) - - # gyp dictates that commands are run from the base directory. - # cd into the directory before running, and adjust paths in - # the arguments to point to the proper locations. - rspfile = None - rspfile_content = None - args = [self.ExpandSpecial(arg, self.base_to_build) for arg in args] - if self.flavor == 'win': - rspfile = rule_name + '.$unique_name.rsp' - # The cygwin case handles this inside the bash sub-shell. - run_in = '' if is_cygwin else ' ' + self.build_to_base - if is_cygwin: - rspfile_content = self.msvs_settings.BuildCygwinBashCommandLine( - args, self.build_to_base) - else: - rspfile_content = gyp.msvs_emulation.EncodeRspFileList(args) - command = ('%s gyp-win-tool action-wrapper $arch ' % sys.executable + - rspfile + run_in) - else: - env = self.ComputeExportEnvString(env) - command = gyp.common.EncodePOSIXShellList(args) - command = 'cd %s; ' % self.build_to_base + env + command - - # GYP rules/actions express being no-ops by not touching their outputs. - # Avoid executing downstream dependencies in this case by specifying - # restat=1 to ninja. - self.ninja.rule(rule_name, command, description, depfile=depfile, - restat=True, pool=pool, - rspfile=rspfile, rspfile_content=rspfile_content) - self.ninja.newline() - - return rule_name, args - - -def CalculateVariables(default_variables, params): - """Calculate additional variables for use in the build (called by gyp).""" - global generator_additional_non_configuration_keys - global generator_additional_path_sections - flavor = gyp.common.GetFlavor(params) - if flavor == 'mac': - default_variables.setdefault('OS', 'mac') - default_variables.setdefault('SHARED_LIB_SUFFIX', '.dylib') - default_variables.setdefault('SHARED_LIB_DIR', - generator_default_variables['PRODUCT_DIR']) - default_variables.setdefault('LIB_DIR', - generator_default_variables['PRODUCT_DIR']) - - # Copy additional generator configuration data from Xcode, which is shared - # by the Mac Ninja generator. - import gyp.generator.xcode as xcode_generator - generator_additional_non_configuration_keys = getattr(xcode_generator, - 'generator_additional_non_configuration_keys', []) - generator_additional_path_sections = getattr(xcode_generator, - 'generator_additional_path_sections', []) - global generator_extra_sources_for_rules - generator_extra_sources_for_rules = getattr(xcode_generator, - 'generator_extra_sources_for_rules', []) - elif flavor == 'win': - exts = gyp.MSVSUtil.TARGET_TYPE_EXT - default_variables.setdefault('OS', 'win') - default_variables['EXECUTABLE_SUFFIX'] = '.' + exts['executable'] - default_variables['STATIC_LIB_PREFIX'] = '' - default_variables['STATIC_LIB_SUFFIX'] = '.' + exts['static_library'] - default_variables['SHARED_LIB_PREFIX'] = '' - default_variables['SHARED_LIB_SUFFIX'] = '.' + exts['shared_library'] - - # Copy additional generator configuration data from VS, which is shared - # by the Windows Ninja generator. - import gyp.generator.msvs as msvs_generator - generator_additional_non_configuration_keys = getattr(msvs_generator, - 'generator_additional_non_configuration_keys', []) - generator_additional_path_sections = getattr(msvs_generator, - 'generator_additional_path_sections', []) - - gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) - else: - operating_system = flavor - if flavor == 'android': - operating_system = 'linux' # Keep this legacy behavior for now. - default_variables.setdefault('OS', operating_system) - default_variables.setdefault('SHARED_LIB_SUFFIX', '.so') - default_variables.setdefault('SHARED_LIB_DIR', - os.path.join('$!PRODUCT_DIR', 'lib')) - default_variables.setdefault('LIB_DIR', - os.path.join('$!PRODUCT_DIR', 'obj')) - -def ComputeOutputDir(params): - """Returns the path from the toplevel_dir to the build output directory.""" - # generator_dir: relative path from pwd to where make puts build files. - # Makes migrating from make to ninja easier, ninja doesn't put anything here. - generator_dir = os.path.relpath(params['options'].generator_output or '.') - - # output_dir: relative path from generator_dir to the build directory. - output_dir = params.get('generator_flags', {}).get('output_dir', 'out') - - # Relative path from source root to our output files. e.g. "out" - return os.path.normpath(os.path.join(generator_dir, output_dir)) - - -def CalculateGeneratorInputInfo(params): - """Called by __init__ to initialize generator values based on params.""" - # E.g. "out/gypfiles" - toplevel = params['options'].toplevel_dir - qualified_out_dir = os.path.normpath(os.path.join( - toplevel, ComputeOutputDir(params), 'gypfiles')) - - global generator_filelist_paths - generator_filelist_paths = { - 'toplevel': toplevel, - 'qualified_out_dir': qualified_out_dir, - } - - -def OpenOutput(path, mode='w'): - """Open |path| for writing, creating directories if necessary.""" - gyp.common.EnsureDirExists(path) - return open(path, mode) - - -def CommandWithWrapper(cmd, wrappers, prog): - wrapper = wrappers.get(cmd, '') - if wrapper: - return wrapper + ' ' + prog - return prog - - -def GetDefaultConcurrentLinks(): - """Returns a best-guess for a number of concurrent links.""" - pool_size = int(os.environ.get('GYP_LINK_CONCURRENCY', 0)) - if pool_size: - return pool_size - - if sys.platform in ('win32', 'cygwin'): - import ctypes - - class MEMORYSTATUSEX(ctypes.Structure): - _fields_ = [ - ("dwLength", ctypes.c_ulong), - ("dwMemoryLoad", ctypes.c_ulong), - ("ullTotalPhys", ctypes.c_ulonglong), - ("ullAvailPhys", ctypes.c_ulonglong), - ("ullTotalPageFile", ctypes.c_ulonglong), - ("ullAvailPageFile", ctypes.c_ulonglong), - ("ullTotalVirtual", ctypes.c_ulonglong), - ("ullAvailVirtual", ctypes.c_ulonglong), - ("sullAvailExtendedVirtual", ctypes.c_ulonglong), - ] - - stat = MEMORYSTATUSEX() - stat.dwLength = ctypes.sizeof(stat) - ctypes.windll.kernel32.GlobalMemoryStatusEx(ctypes.byref(stat)) - - # VS 2015 uses 20% more working set than VS 2013 and can consume all RAM - # on a 64 GB machine. - mem_limit = max(1, stat.ullTotalPhys / (5 * (2 ** 30))) # total / 5GB - hard_cap = max(1, int(os.environ.get('GYP_LINK_CONCURRENCY_MAX', 2**32))) - return min(mem_limit, hard_cap) - elif sys.platform.startswith('linux'): - if os.path.exists("/proc/meminfo"): - with open("/proc/meminfo") as meminfo: - memtotal_re = re.compile(r'^MemTotal:\s*(\d*)\s*kB') - for line in meminfo: - match = memtotal_re.match(line) - if not match: - continue - # Allow 8Gb per link on Linux because Gold is quite memory hungry - return max(1, int(match.group(1)) / (8 * (2 ** 20))) - return 1 - elif sys.platform == 'darwin': - try: - avail_bytes = int(subprocess.check_output(['sysctl', '-n', 'hw.memsize'])) - # A static library debug build of Chromium's unit_tests takes ~2.7GB, so - # 4GB per ld process allows for some more bloat. - return max(1, avail_bytes / (4 * (2 ** 30))) # total / 4GB - except: - return 1 - else: - # TODO(scottmg): Implement this for other platforms. - return 1 - - -def _GetWinLinkRuleNameSuffix(embed_manifest): - """Returns the suffix used to select an appropriate linking rule depending on - whether the manifest embedding is enabled.""" - return '_embed' if embed_manifest else '' - - -def _AddWinLinkRules(master_ninja, embed_manifest): - """Adds link rules for Windows platform to |master_ninja|.""" - def FullLinkCommand(ldcmd, out, binary_type): - resource_name = { - 'exe': '1', - 'dll': '2', - }[binary_type] - 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='$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='$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 %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 $binary' % rule_name_suffix.upper(), - command=exe_cmd, - rspfile='$binary.rsp', - rspfile_content='$in_newline $libs $ldflags', - pool='link_pool') - - -def GenerateOutputForConfig(target_list, target_dicts, data, params, - config_name): - options = params['options'] - flavor = gyp.common.GetFlavor(params) - generator_flags = params.get('generator_flags', {}) - - # build_dir: relative path from source root to our output files. - # e.g. "out/Debug" - build_dir = os.path.normpath( - os.path.join(ComputeOutputDir(params), config_name)) - - toplevel_build = os.path.join(options.toplevel_dir, build_dir) - - 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) - - # Grab make settings for CC/CXX. - # The rules are - # - The priority from low to high is gcc/g++, the 'make_global_settings' in - # gyp, the environment variable. - # - If there is no 'make_global_settings' for CC.host/CXX.host or - # 'CC_host'/'CXX_host' enviroment variable, cc_host/cxx_host should be set - # to cc/cxx. - if flavor == 'win': - ar = 'lib.exe' - # cc and cxx must be set to the correct architecture by overriding with one - # of cl_x86 or cl_x64 below. - cc = 'UNSET' - cxx = 'UNSET' - ld = 'link.exe' - ld_host = '$ld' - else: - ar = 'ar' - cc = 'cc' - cxx = 'c++' - ld = '$cc' - ldxx = '$cxx' - ld_host = '$cc_host' - ldxx_host = '$cxx_host' - - ar_host = 'ar' - cc_host = None - cxx_host = None - cc_host_global_setting = None - cxx_host_global_setting = None - clang_cl = None - nm = 'nm' - nm_host = 'nm' - readelf = 'readelf' - readelf_host = 'readelf' - - build_file, _, _ = gyp.common.ParseQualifiedTarget(target_list[0]) - make_global_settings = data[build_file].get('make_global_settings', []) - build_to_root = gyp.common.InvertRelativePath(build_dir, - options.toplevel_dir) - wrappers = {} - for key, value in make_global_settings: - if key == 'AR': - ar = os.path.join(build_to_root, value) - if key == 'AR.host': - ar_host = os.path.join(build_to_root, value) - if key == 'CC': - cc = os.path.join(build_to_root, value) - if cc.endswith('clang-cl'): - clang_cl = cc - if key == 'CXX': - cxx = os.path.join(build_to_root, value) - if key == 'CC.host': - cc_host = os.path.join(build_to_root, value) - cc_host_global_setting = value - if key == 'CXX.host': - cxx_host = os.path.join(build_to_root, value) - cxx_host_global_setting = value - if key == 'LD': - ld = os.path.join(build_to_root, value) - if key == 'LD.host': - ld_host = os.path.join(build_to_root, value) - if key == 'LDXX': - ldxx = os.path.join(build_to_root, value) - if key == 'LDXX.host': - ldxx_host = os.path.join(build_to_root, value) - if key == 'NM': - nm = os.path.join(build_to_root, value) - if key == 'NM.host': - nm_host = os.path.join(build_to_root, value) - if key == 'READELF': - readelf = os.path.join(build_to_root, value) - if key == 'READELF.host': - readelf_host = os.path.join(build_to_root, value) - if key.endswith('_wrapper'): - wrappers[key[:-len('_wrapper')]] = os.path.join(build_to_root, value) - - # Support wrappers from environment variables too. - for key, value in os.environ.iteritems(): - if key.lower().endswith('_wrapper'): - key_prefix = key[:-len('_wrapper')] - key_prefix = re.sub(r'\.HOST$', '.host', key_prefix) - wrappers[key_prefix] = os.path.join(build_to_root, value) - - if flavor == 'win': - configs = [target_dicts[qualified_target]['configurations'][config_name] - for qualified_target in target_list] - shared_system_includes = None - if not generator_flags.get('ninja_use_custom_environment_files', 0): - shared_system_includes = \ - gyp.msvs_emulation.ExtractSharedMSVSSystemIncludes( - configs, generator_flags) - cl_paths = gyp.msvs_emulation.GenerateEnvironmentFiles( - toplevel_build, generator_flags, shared_system_includes, OpenOutput) - for arch, path in cl_paths.iteritems(): - if clang_cl: - # If we have selected clang-cl, use that instead. - path = clang_cl - command = CommandWithWrapper('CC', wrappers, - QuoteShellArgument(path, 'win')) - if clang_cl: - # Use clang-cl to cross-compile for x86 or x86_64. - command += (' -m32' if arch == 'x86' else ' -m64') - master_ninja.variable('cl_' + arch, command) - - cc = GetEnvironFallback(['CC_target', 'CC'], cc) - master_ninja.variable('cc', CommandWithWrapper('CC', wrappers, cc)) - cxx = GetEnvironFallback(['CXX_target', 'CXX'], cxx) - master_ninja.variable('cxx', CommandWithWrapper('CXX', wrappers, cxx)) - - if flavor == 'win': - master_ninja.variable('ld', ld) - master_ninja.variable('idl', 'midl.exe') - master_ninja.variable('ar', ar) - master_ninja.variable('rc', 'rc.exe') - master_ninja.variable('ml_x86', 'ml.exe') - master_ninja.variable('ml_x64', 'ml64.exe') - master_ninja.variable('mt', 'mt.exe') - else: - master_ninja.variable('ld', CommandWithWrapper('LINK', wrappers, ld)) - master_ninja.variable('ldxx', CommandWithWrapper('LINK', wrappers, ldxx)) - master_ninja.variable('ar', GetEnvironFallback(['AR_target', 'AR'], ar)) - if flavor != 'mac': - # Mac does not use readelf/nm for .TOC generation, so avoiding polluting - # the master ninja with extra unused variables. - master_ninja.variable( - 'nm', GetEnvironFallback(['NM_target', 'NM'], nm)) - master_ninja.variable( - 'readelf', GetEnvironFallback(['READELF_target', 'READELF'], readelf)) - - if generator_supports_multiple_toolsets: - if not cc_host: - cc_host = cc - if not cxx_host: - cxx_host = cxx - - master_ninja.variable('ar_host', GetEnvironFallback(['AR_host'], ar_host)) - master_ninja.variable('nm_host', GetEnvironFallback(['NM_host'], nm_host)) - master_ninja.variable('readelf_host', - GetEnvironFallback(['READELF_host'], readelf_host)) - cc_host = GetEnvironFallback(['CC_host'], cc_host) - cxx_host = GetEnvironFallback(['CXX_host'], cxx_host) - - # The environment variable could be used in 'make_global_settings', like - # ['CC.host', '$(CC)'] or ['CXX.host', '$(CXX)'], transform them here. - if '$(CC)' in cc_host and cc_host_global_setting: - cc_host = cc_host_global_setting.replace('$(CC)', cc) - if '$(CXX)' in cxx_host and cxx_host_global_setting: - cxx_host = cxx_host_global_setting.replace('$(CXX)', cxx) - master_ninja.variable('cc_host', - CommandWithWrapper('CC.host', wrappers, cc_host)) - master_ninja.variable('cxx_host', - CommandWithWrapper('CXX.host', wrappers, cxx_host)) - if flavor == 'win': - master_ninja.variable('ld_host', ld_host) - master_ninja.variable('ldxx_host', ldxx_host) - else: - master_ninja.variable('ld_host', CommandWithWrapper( - 'LINK', wrappers, ld_host)) - master_ninja.variable('ldxx_host', CommandWithWrapper( - 'LINK', wrappers, ldxx_host)) - - master_ninja.newline() - - master_ninja.pool('link_pool', depth=GetDefaultConcurrentLinks()) - master_ninja.newline() - - deps = 'msvc' if flavor == 'win' else 'gcc' - - if flavor != 'win': - master_ninja.rule( - 'cc', - description='CC $out', - command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_c ' - '$cflags_pch_c -c $in -o $out'), - depfile='$out.d', - deps=deps) - master_ninja.rule( - 'cc_s', - description='CC $out', - command=('$cc $defines $includes $cflags $cflags_c ' - '$cflags_pch_c -c $in -o $out')) - master_ninja.rule( - 'cxx', - description='CXX $out', - command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_cc ' - '$cflags_pch_cc -c $in -o $out'), - 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_c ') - cxx_command = ('ninja -t msvc -e $arch ' + - '-- ' - '$cxx /nologo /showIncludes /FC ' - '@$out.rsp /c $in /Fo$out /Fd$pdbname_cc ') - master_ninja.rule( - 'cc', - description='CC $out', - command=cc_command, - rspfile='$out.rsp', - rspfile_content='$defines $includes $cflags $cflags_c', - deps=deps) - master_ninja.rule( - 'cxx', - description='CXX $out', - command=cxx_command, - rspfile='$out.rsp', - rspfile_content='$defines $includes $cflags $cflags_cc', - deps=deps) - master_ninja.rule( - 'idl', - description='IDL $in', - command=('%s gyp-win-tool midl-wrapper $arch $outdir ' - '$tlb $h $dlldata $iid $proxy $in ' - '$midl_includes $idlflags' % sys.executable)) - master_ninja.rule( - 'rc', - description='RC $in', - # Note: $in must be last otherwise rc.exe complains. - command=('%s gyp-win-tool rc-wrapper ' - '$arch $rc $defines $resource_includes $rcflags /fo$out $in' % - sys.executable)) - master_ninja.rule( - 'asm', - description='ASM $out', - command=('%s gyp-win-tool asm-wrapper ' - '$arch $asm $defines $includes $asmflags /c /Fo $out $in' % - sys.executable)) - - if flavor != 'mac' and flavor != 'win': - master_ninja.rule( - 'alink', - description='AR $out', - command='rm -f $out && $ar rcs $arflags $out $in') - master_ninja.rule( - 'alink_thin', - description='AR $out', - command='rm -f $out && $ar rcsT $arflags $out $in') - - # This allows targets that only need to depend on $lib's API to declare an - # order-only dependency on $lib.TOC and avoid relinking such downstream - # dependencies when $lib changes only in non-public ways. - # The resulting string leaves an uninterpolated %{suffix} which - # is used in the final substitution below. - mtime_preserving_solink_base = ( - 'if [ ! -e $lib -o ! -e $lib.TOC ]; then ' - '%(solink)s && %(extract_toc)s > $lib.TOC; else ' - '%(solink)s && %(extract_toc)s > $lib.tmp && ' - 'if ! cmp -s $lib.tmp $lib.TOC; then mv $lib.tmp $lib.TOC ; ' - 'fi; fi' - % { 'solink': - '$ld -shared $ldflags -o $lib -Wl,-soname=$soname %(suffix)s', - 'extract_toc': - ('{ $readelf -d $lib | grep SONAME ; ' - '$nm -gD -f p $lib | cut -f1-2 -d\' \'; }')}) - - master_ninja.rule( - 'solink', - description='SOLINK $lib', - restat=True, - command=mtime_preserving_solink_base % {'suffix': '@$link_file_list'}, - rspfile='$link_file_list', - rspfile_content= - '-Wl,--whole-archive $in $solibs -Wl,--no-whole-archive $libs', - pool='link_pool') - master_ninja.rule( - 'solink_module', - description='SOLINK(module) $lib', - restat=True, - command=mtime_preserving_solink_base % {'suffix': '@$link_file_list'}, - rspfile='$link_file_list', - rspfile_content='-Wl,--start-group $in $solibs $libs -Wl,--end-group', - pool='link_pool') - master_ninja.rule( - 'link', - description='LINK $out', - command=('$ld $ldflags -o $out ' - '-Wl,--start-group $in $solibs $libs -Wl,--end-group'), - pool='link_pool') - elif flavor == 'win': - master_ninja.rule( - 'alink', - description='LIB $out', - 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) - _AddWinLinkRules(master_ninja, embed_manifest=False) - else: - master_ninja.rule( - 'objc', - description='OBJC $out', - command=('$cc -MMD -MF $out.d $defines $includes $cflags $cflags_objc ' - '$cflags_pch_objc -c $in -o $out'), - depfile='$out.d', - deps=deps) - master_ninja.rule( - 'objcxx', - description='OBJCXX $out', - command=('$cxx -MMD -MF $out.d $defines $includes $cflags $cflags_objcc ' - '$cflags_pch_objcc -c $in -o $out'), - depfile='$out.d', - deps=deps) - master_ninja.rule( - 'alink', - description='LIBTOOL-STATIC $out, POSTBUILDS', - command='rm -f $out && ' - './gyp-mac-tool filter-libtool libtool $libtool_flags ' - '-static -o $out $in' - '$postbuilds') - master_ninja.rule( - 'lipo', - description='LIPO $out, POSTBUILDS', - command='rm -f $out && lipo -create $in -output $out$postbuilds') - master_ninja.rule( - 'solipo', - description='SOLIPO $out, POSTBUILDS', - command=( - 'rm -f $lib $lib.TOC && lipo -create $in -output $lib$postbuilds &&' - '%(extract_toc)s > $lib.TOC' - % { 'extract_toc': - '{ otool -l $lib | grep LC_ID_DYLIB -A 5; ' - 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'})) - - - # Record the public interface of $lib in $lib.TOC. See the corresponding - # comment in the posix section above for details. - solink_base = '$ld %(type)s $ldflags -o $lib %(suffix)s' - mtime_preserving_solink_base = ( - 'if [ ! -e $lib -o ! -e $lib.TOC ] || ' - # Always force dependent targets to relink if this library - # reexports something. Handling this correctly would require - # recursive TOC dumping but this is rare in practice, so punt. - 'otool -l $lib | grep -q LC_REEXPORT_DYLIB ; then ' - '%(solink)s && %(extract_toc)s > $lib.TOC; ' - 'else ' - '%(solink)s && %(extract_toc)s > $lib.tmp && ' - 'if ! cmp -s $lib.tmp $lib.TOC; then ' - 'mv $lib.tmp $lib.TOC ; ' - 'fi; ' - 'fi' - % { 'solink': solink_base, - 'extract_toc': - '{ otool -l $lib | grep LC_ID_DYLIB -A 5; ' - 'nm -gP $lib | cut -f1-2 -d\' \' | grep -v U$$; true; }'}) - - - solink_suffix = '@$link_file_list$postbuilds' - master_ninja.rule( - 'solink', - description='SOLINK $lib, POSTBUILDS', - restat=True, - command=mtime_preserving_solink_base % {'suffix': solink_suffix, - 'type': '-shared'}, - rspfile='$link_file_list', - rspfile_content='$in $solibs $libs', - pool='link_pool') - master_ninja.rule( - 'solink_notoc', - description='SOLINK $lib, POSTBUILDS', - restat=True, - command=solink_base % {'suffix':solink_suffix, 'type': '-shared'}, - rspfile='$link_file_list', - rspfile_content='$in $solibs $libs', - pool='link_pool') - - master_ninja.rule( - 'solink_module', - description='SOLINK(module) $lib, POSTBUILDS', - restat=True, - command=mtime_preserving_solink_base % {'suffix': solink_suffix, - 'type': '-bundle'}, - rspfile='$link_file_list', - rspfile_content='$in $solibs $libs', - pool='link_pool') - master_ninja.rule( - 'solink_module_notoc', - description='SOLINK(module) $lib, POSTBUILDS', - restat=True, - command=solink_base % {'suffix': solink_suffix, 'type': '-bundle'}, - rspfile='$link_file_list', - rspfile_content='$in $solibs $libs', - pool='link_pool') - - master_ninja.rule( - 'link', - description='LINK $out, POSTBUILDS', - command=('$ld $ldflags -o $out ' - '$in $solibs $libs$postbuilds'), - pool='link_pool') - master_ninja.rule( - 'preprocess_infoplist', - description='PREPROCESS INFOPLIST $out', - command=('$cc -E -P -Wno-trigraphs -x c $defines $in -o $out && ' - 'plutil -convert xml1 $out $out')) - master_ninja.rule( - 'copy_infoplist', - description='COPY INFOPLIST $in', - command='$env ./gyp-mac-tool copy-info-plist $in $out $binary $keys') - master_ninja.rule( - 'merge_infoplist', - description='MERGE INFOPLISTS $in', - command='$env ./gyp-mac-tool merge-info-plist $out $in') - master_ninja.rule( - 'compile_xcassets', - description='COMPILE XCASSETS $in', - command='$env ./gyp-mac-tool compile-xcassets $keys $in') - master_ninja.rule( - 'mac_tool', - description='MACTOOL $mactool_cmd $in', - command='$env ./gyp-mac-tool $mactool_cmd $in $out $binary') - master_ninja.rule( - 'package_framework', - description='PACKAGE FRAMEWORK $out, POSTBUILDS', - command='./gyp-mac-tool package-framework $out $version$postbuilds ' - '&& touch $out') - if flavor == 'win': - master_ninja.rule( - 'stamp', - description='STAMP $out', - command='%s gyp-win-tool stamp $out' % sys.executable) - else: - master_ninja.rule( - 'stamp', - description='STAMP $out', - command='${postbuilds}touch $out') - if flavor == 'win': - master_ninja.rule( - 'copy', - description='COPY $in $out', - command='%s gyp-win-tool recursive-mirror $in $out' % sys.executable) - elif flavor == 'zos': - master_ninja.rule( - 'copy', - description='COPY $in $out', - command='rm -rf $out && cp -fRP $in $out') - else: - master_ninja.rule( - 'copy', - description='COPY $in $out', - command='rm -rf $out && cp -af $in $out') - master_ninja.newline() - - all_targets = set() - for build_file in params['build_files']: - for target in gyp.common.AllTargets(target_list, - target_dicts, - os.path.normpath(build_file)): - all_targets.add(target) - all_outputs = set() - - # target_outputs is a map from qualified target name to a Target object. - target_outputs = {} - # target_short_names is a map from target short name to a list of Target - # objects. - target_short_names = {} - - # short name of targets that were skipped because they didn't contain anything - # interesting. - # NOTE: there may be overlap between this an non_empty_target_names. - empty_target_names = set() - - # Set of non-empty short target names. - # NOTE: there may be overlap between this an empty_target_names. - non_empty_target_names = set() - - for qualified_target in target_list: - # qualified_target is like: third_party/icu/icu.gyp:icui18n#target - build_file, name, toolset = \ - gyp.common.ParseQualifiedTarget(qualified_target) - - 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. %s vs. %s" % - (this_make_global_settings, make_global_settings)) - - spec = target_dicts[qualified_target] - if flavor == 'mac': - gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(data[build_file], spec) - - # If build_file is a symlink, we must not follow it because there's a chance - # it could point to a path above toplevel_dir, and we cannot correctly deal - # with that case at the moment. - build_file = gyp.common.RelativePath(build_file, options.toplevel_dir, - False) - - qualified_target_for_hash = gyp.common.QualifiedTarget(build_file, name, - toolset) - hash_for_rules = hashlib.md5(qualified_target_for_hash).hexdigest() - - base_path = os.path.dirname(build_file) - obj = 'obj' - if toolset != 'target': - obj += '.' + toolset - output_file = os.path.join(obj, base_path, name + '.ninja') - - ninja_output = StringIO() - writer = NinjaWriter(hash_for_rules, target_outputs, base_path, build_dir, - ninja_output, - toplevel_build, output_file, - flavor, toplevel_dir=options.toplevel_dir) - - target = writer.WriteSpec(spec, config_name, generator_flags) - - if ninja_output.tell() > 0: - # Only create files for ninja files that actually have contents. - with OpenOutput(os.path.join(toplevel_build, output_file)) as ninja_file: - ninja_file.write(ninja_output.getvalue()) - ninja_output.close() - master_ninja.subninja(output_file) - - if target: - if name != target.FinalOutput() and spec['toolset'] == 'target': - target_short_names.setdefault(name, []).append(target) - target_outputs[qualified_target] = target - if qualified_target in all_targets: - all_outputs.add(target.FinalOutput()) - non_empty_target_names.add(name) - else: - empty_target_names.add(name) - - if target_short_names: - # Write a short name to build this target. This benefits both the - # "build chrome" case as well as the gyp tests, which expect to be - # able to run actions and build libraries by their short name. - master_ninja.newline() - master_ninja.comment('Short names for targets.') - for short_name in target_short_names: - master_ninja.build(short_name, 'phony', [x.FinalOutput() for x in - target_short_names[short_name]]) - - # Write phony targets for any empty targets that weren't written yet. As - # short names are not necessarily unique only do this for short names that - # haven't already been output for another target. - empty_target_names = empty_target_names - non_empty_target_names - if empty_target_names: - master_ninja.newline() - master_ninja.comment('Empty targets (output for completeness).') - for name in sorted(empty_target_names): - master_ninja.build(name, 'phony') - - if all_outputs: - master_ninja.newline() - 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'] - for config in configurations: - builddir = os.path.join(options.toplevel_dir, 'out', config) - arguments = ['ninja', '-C', builddir] - print 'Building [%s]: %s' % (config, 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): - # Update target_dicts for iOS device builds. - target_dicts = gyp.xcode_emulation.CloneConfigurationForDeviceAndEmulator( - target_dicts) - - user_config = params.get('generator_flags', {}).get('config', None) - if gyp.common.GetFlavor(params) == 'win': - target_list, target_dicts = MSVSUtil.ShardTargets(target_list, target_dicts) - target_list, target_dicts = MSVSUtil.InsertLargePdbShims( - target_list, target_dicts, generator_default_variables) - - 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/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py deleted file mode 100644 index 1767b2f45a04c..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/ninja_test.py +++ /dev/null @@ -1,47 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2012 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. - -""" Unit tests for the ninja.py file. """ - -import gyp.generator.ninja as ninja -import unittest -import StringIO -import sys -import TestCommon - - -class TestPrefixesAndSuffixes(unittest.TestCase): - def test_BinaryNamesWindows(self): - # These cannot run on non-Windows as they require a VS installation to - # correctly handle variable expansion. - if sys.platform.startswith('win'): - writer = ninja.NinjaWriter('foo', 'wee', '.', '.', 'build.ninja', '.', - 'build.ninja', 'win') - spec = { 'target_name': 'wee' } - self.assertTrue(writer.ComputeOutputFileName(spec, 'executable'). - endswith('.exe')) - self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). - endswith('.dll')) - self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). - endswith('.lib')) - - def test_BinaryNamesLinux(self): - writer = ninja.NinjaWriter('foo', 'wee', '.', '.', 'build.ninja', '.', - 'build.ninja', 'linux') - spec = { 'target_name': 'wee' } - self.assertTrue('.' not in writer.ComputeOutputFileName(spec, - 'executable')) - self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). - startswith('lib')) - self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). - startswith('lib')) - self.assertTrue(writer.ComputeOutputFileName(spec, 'shared_library'). - endswith('.so')) - self.assertTrue(writer.ComputeOutputFileName(spec, 'static_library'). - endswith('.a')) - -if __name__ == '__main__': - unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py deleted file mode 100644 index 0e3fb9301ecb9..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode.py +++ /dev/null @@ -1,1300 +0,0 @@ -# Copyright (c) 2012 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. - -import filecmp -import gyp.common -import gyp.xcodeproj_file -import gyp.xcode_ninja -import errno -import os -import sys -import posixpath -import re -import shutil -import subprocess -import tempfile - - -# Project files generated by this module will use _intermediate_var as a -# custom Xcode setting whose value is a DerivedSources-like directory that's -# project-specific and configuration-specific. The normal choice, -# DERIVED_FILE_DIR, is target-specific, which is thought to be too restrictive -# as it is likely that multiple targets within a single project file will want -# to access the same set of generated files. The other option, -# PROJECT_DERIVED_FILE_DIR, is unsuitable because while it is project-specific, -# it is not configuration-specific. INTERMEDIATE_DIR is defined as -# $(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION). -_intermediate_var = 'INTERMEDIATE_DIR' - -# SHARED_INTERMEDIATE_DIR is the same, except that it is shared among all -# targets that share the same BUILT_PRODUCTS_DIR. -_shared_intermediate_var = 'SHARED_INTERMEDIATE_DIR' - -_library_search_paths_var = 'LIBRARY_SEARCH_PATHS' - -generator_default_variables = { - 'EXECUTABLE_PREFIX': '', - 'EXECUTABLE_SUFFIX': '', - 'STATIC_LIB_PREFIX': 'lib', - 'SHARED_LIB_PREFIX': 'lib', - 'STATIC_LIB_SUFFIX': '.a', - 'SHARED_LIB_SUFFIX': '.dylib', - # INTERMEDIATE_DIR is a place for targets to build up intermediate products. - # It is specific to each build environment. It is only guaranteed to exist - # and be constant within the context of a project, corresponding to a single - # input file. Some build environments may allow their intermediate directory - # to be shared on a wider scale, but this is not guaranteed. - 'INTERMEDIATE_DIR': '$(%s)' % _intermediate_var, - 'OS': 'mac', - 'PRODUCT_DIR': '$(BUILT_PRODUCTS_DIR)', - 'LIB_DIR': '$(BUILT_PRODUCTS_DIR)', - 'RULE_INPUT_ROOT': '$(INPUT_FILE_BASE)', - 'RULE_INPUT_EXT': '$(INPUT_FILE_SUFFIX)', - 'RULE_INPUT_NAME': '$(INPUT_FILE_NAME)', - 'RULE_INPUT_PATH': '$(INPUT_FILE_PATH)', - 'RULE_INPUT_DIRNAME': '$(INPUT_FILE_DIRNAME)', - 'SHARED_INTERMEDIATE_DIR': '$(%s)' % _shared_intermediate_var, - 'CONFIGURATION_NAME': '$(CONFIGURATION)', -} - -# The Xcode-specific sections that hold paths. -generator_additional_path_sections = [ - 'mac_bundle_resources', - 'mac_framework_headers', - 'mac_framework_private_headers', - # 'mac_framework_dirs', input already handles _dirs endings. -] - -# The Xcode-specific keys that exist on targets and aren't moved down to -# configurations. -generator_additional_non_configuration_keys = [ - 'ios_app_extension', - 'ios_watch_app', - 'ios_watchkit_extension', - 'mac_bundle', - 'mac_bundle_resources', - 'mac_framework_headers', - 'mac_framework_private_headers', - 'mac_xctest_bundle', - 'xcode_create_dependents_test_runner', -] - -# We want to let any rules apply to files that are resources also. -generator_extra_sources_for_rules = [ - 'mac_bundle_resources', - 'mac_framework_headers', - 'mac_framework_private_headers', -] - -generator_filelist_paths = None - -# Xcode's standard set of library directories, which don't need to be duplicated -# in LIBRARY_SEARCH_PATHS. This list is not exhaustive, but that's okay. -xcode_standard_library_dirs = frozenset([ - '$(SDKROOT)/usr/lib', - '$(SDKROOT)/usr/local/lib', -]) - -def CreateXCConfigurationList(configuration_names): - xccl = gyp.xcodeproj_file.XCConfigurationList({'buildConfigurations': []}) - if len(configuration_names) == 0: - configuration_names = ['Default'] - for configuration_name in configuration_names: - xcbc = gyp.xcodeproj_file.XCBuildConfiguration({ - 'name': configuration_name}) - xccl.AppendProperty('buildConfigurations', xcbc) - xccl.SetProperty('defaultConfigurationName', configuration_names[0]) - return xccl - - -class XcodeProject(object): - def __init__(self, gyp_path, path, build_file_dict): - self.gyp_path = gyp_path - self.path = path - self.project = gyp.xcodeproj_file.PBXProject(path=path) - projectDirPath = gyp.common.RelativePath( - os.path.dirname(os.path.abspath(self.gyp_path)), - os.path.dirname(path) or '.') - self.project.SetProperty('projectDirPath', projectDirPath) - self.project_file = \ - gyp.xcodeproj_file.XCProjectFile({'rootObject': self.project}) - self.build_file_dict = build_file_dict - - # TODO(mark): add destructor that cleans up self.path if created_dir is - # True and things didn't complete successfully. Or do something even - # better with "try"? - self.created_dir = False - try: - os.makedirs(self.path) - self.created_dir = True - except OSError, e: - if e.errno != errno.EEXIST: - raise - - def Finalize1(self, xcode_targets, serialize_all_tests): - # Collect a list of all of the build configuration names used by the - # various targets in the file. It is very heavily advised to keep each - # target in an entire project (even across multiple project files) using - # the same set of configuration names. - configurations = [] - for xct in self.project.GetProperty('targets'): - xccl = xct.GetProperty('buildConfigurationList') - xcbcs = xccl.GetProperty('buildConfigurations') - for xcbc in xcbcs: - name = xcbc.GetProperty('name') - if name not in configurations: - configurations.append(name) - - # Replace the XCConfigurationList attached to the PBXProject object with - # a new one specifying all of the configuration names used by the various - # targets. - try: - xccl = CreateXCConfigurationList(configurations) - self.project.SetProperty('buildConfigurationList', xccl) - except: - sys.stderr.write("Problem with gyp file %s\n" % self.gyp_path) - raise - - # The need for this setting is explained above where _intermediate_var is - # defined. The comments below about wanting to avoid project-wide build - # settings apply here too, but this needs to be set on a project-wide basis - # so that files relative to the _intermediate_var setting can be displayed - # properly in the Xcode UI. - # - # Note that for configuration-relative files such as anything relative to - # _intermediate_var, for the purposes of UI tree view display, Xcode will - # only resolve the configuration name once, when the project file is - # opened. If the active build configuration is changed, the project file - # must be closed and reopened if it is desired for the tree view to update. - # This is filed as Apple radar 6588391. - xccl.SetBuildSetting(_intermediate_var, - '$(PROJECT_DERIVED_FILE_DIR)/$(CONFIGURATION)') - xccl.SetBuildSetting(_shared_intermediate_var, - '$(SYMROOT)/DerivedSources/$(CONFIGURATION)') - - # Set user-specified project-wide build settings and config files. This - # is intended to be used very sparingly. Really, almost everything should - # go into target-specific build settings sections. The project-wide - # settings are only intended to be used in cases where Xcode attempts to - # resolve variable references in a project context as opposed to a target - # context, such as when resolving sourceTree references while building up - # the tree tree view for UI display. - # Any values set globally are applied to all configurations, then any - # per-configuration values are applied. - for xck, xcv in self.build_file_dict.get('xcode_settings', {}).iteritems(): - xccl.SetBuildSetting(xck, xcv) - if 'xcode_config_file' in self.build_file_dict: - config_ref = self.project.AddOrGetFileInRootGroup( - self.build_file_dict['xcode_config_file']) - xccl.SetBaseConfiguration(config_ref) - build_file_configurations = self.build_file_dict.get('configurations', {}) - if build_file_configurations: - for config_name in configurations: - build_file_configuration_named = \ - build_file_configurations.get(config_name, {}) - if build_file_configuration_named: - xcc = xccl.ConfigurationNamed(config_name) - for xck, xcv in build_file_configuration_named.get('xcode_settings', - {}).iteritems(): - xcc.SetBuildSetting(xck, xcv) - if 'xcode_config_file' in build_file_configuration_named: - config_ref = self.project.AddOrGetFileInRootGroup( - build_file_configurations[config_name]['xcode_config_file']) - xcc.SetBaseConfiguration(config_ref) - - # Sort the targets based on how they appeared in the input. - # TODO(mark): Like a lot of other things here, this assumes internal - # knowledge of PBXProject - in this case, of its "targets" property. - - # ordinary_targets are ordinary targets that are already in the project - # file. run_test_targets are the targets that run unittests and should be - # used for the Run All Tests target. support_targets are the action/rule - # targets used by GYP file targets, just kept for the assert check. - ordinary_targets = [] - run_test_targets = [] - support_targets = [] - - # targets is full list of targets in the project. - targets = [] - - # does the it define it's own "all"? - has_custom_all = False - - # targets_for_all is the list of ordinary_targets that should be listed - # in this project's "All" target. It includes each non_runtest_target - # that does not have suppress_wildcard set. - targets_for_all = [] - - for target in self.build_file_dict['targets']: - target_name = target['target_name'] - toolset = target['toolset'] - qualified_target = gyp.common.QualifiedTarget(self.gyp_path, target_name, - toolset) - xcode_target = xcode_targets[qualified_target] - # Make sure that the target being added to the sorted list is already in - # the unsorted list. - assert xcode_target in self.project._properties['targets'] - targets.append(xcode_target) - ordinary_targets.append(xcode_target) - if xcode_target.support_target: - support_targets.append(xcode_target.support_target) - targets.append(xcode_target.support_target) - - if not int(target.get('suppress_wildcard', False)): - targets_for_all.append(xcode_target) - - if target_name.lower() == 'all': - has_custom_all = True; - - # If this target has a 'run_as' attribute, add its target to the - # targets, and add it to the test targets. - if target.get('run_as'): - # Make a target to run something. It should have one - # dependency, the parent xcode target. - xccl = CreateXCConfigurationList(configurations) - run_target = gyp.xcodeproj_file.PBXAggregateTarget({ - 'name': 'Run ' + target_name, - 'productName': xcode_target.GetProperty('productName'), - 'buildConfigurationList': xccl, - }, - parent=self.project) - run_target.AddDependency(xcode_target) - - command = target['run_as'] - script = '' - if command.get('working_directory'): - script = script + 'cd "%s"\n' % \ - gyp.xcodeproj_file.ConvertVariablesToShellSyntax( - command.get('working_directory')) - - if command.get('environment'): - script = script + "\n".join( - ['export %s="%s"' % - (key, gyp.xcodeproj_file.ConvertVariablesToShellSyntax(val)) - for (key, val) in command.get('environment').iteritems()]) + "\n" - - # Some test end up using sockets, files on disk, etc. and can get - # confused if more then one test runs at a time. The generator - # flag 'xcode_serialize_all_test_runs' controls the forcing of all - # tests serially. It defaults to True. To get serial runs this - # little bit of python does the same as the linux flock utility to - # make sure only one runs at a time. - command_prefix = '' - if serialize_all_tests: - command_prefix = \ -"""python -c "import fcntl, subprocess, sys -file = open('$TMPDIR/GYP_serialize_test_runs', 'a') -fcntl.flock(file.fileno(), fcntl.LOCK_EX) -sys.exit(subprocess.call(sys.argv[1:]))" """ - - # If we were unable to exec for some reason, we want to exit - # with an error, and fixup variable references to be shell - # syntax instead of xcode syntax. - script = script + 'exec ' + command_prefix + '%s\nexit 1\n' % \ - gyp.xcodeproj_file.ConvertVariablesToShellSyntax( - gyp.common.EncodePOSIXShellList(command.get('action'))) - - ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ - 'shellScript': script, - 'showEnvVarsInLog': 0, - }) - run_target.AppendProperty('buildPhases', ssbp) - - # Add the run target to the project file. - targets.append(run_target) - run_test_targets.append(run_target) - xcode_target.test_runner = run_target - - - # Make sure that the list of targets being replaced is the same length as - # the one replacing it, but allow for the added test runner targets. - assert len(self.project._properties['targets']) == \ - len(ordinary_targets) + len(support_targets) - - self.project._properties['targets'] = targets - - # Get rid of unnecessary levels of depth in groups like the Source group. - self.project.RootGroupsTakeOverOnlyChildren(True) - - # Sort the groups nicely. Do this after sorting the targets, because the - # Products group is sorted based on the order of the targets. - self.project.SortGroups() - - # Create an "All" target if there's more than one target in this project - # file and the project didn't define its own "All" target. Put a generated - # "All" target first so that people opening up the project for the first - # time will build everything by default. - if len(targets_for_all) > 1 and not has_custom_all: - xccl = CreateXCConfigurationList(configurations) - all_target = gyp.xcodeproj_file.PBXAggregateTarget( - { - 'buildConfigurationList': xccl, - 'name': 'All', - }, - parent=self.project) - - for target in targets_for_all: - all_target.AddDependency(target) - - # TODO(mark): This is evil because it relies on internal knowledge of - # PBXProject._properties. It's important to get the "All" target first, - # though. - self.project._properties['targets'].insert(0, all_target) - - # The same, but for run_test_targets. - if len(run_test_targets) > 1: - xccl = CreateXCConfigurationList(configurations) - run_all_tests_target = gyp.xcodeproj_file.PBXAggregateTarget( - { - 'buildConfigurationList': xccl, - 'name': 'Run All Tests', - }, - parent=self.project) - for run_test_target in run_test_targets: - run_all_tests_target.AddDependency(run_test_target) - - # Insert after the "All" target, which must exist if there is more than - # one run_test_target. - self.project._properties['targets'].insert(1, run_all_tests_target) - - def Finalize2(self, xcode_targets, xcode_target_to_target_dict): - # Finalize2 needs to happen in a separate step because the process of - # updating references to other projects depends on the ordering of targets - # within remote project files. Finalize1 is responsible for sorting duty, - # and once all project files are sorted, Finalize2 can come in and update - # these references. - - # To support making a "test runner" target that will run all the tests - # that are direct dependents of any given target, we look for - # xcode_create_dependents_test_runner being set on an Aggregate target, - # and generate a second target that will run the tests runners found under - # the marked target. - for bf_tgt in self.build_file_dict['targets']: - if int(bf_tgt.get('xcode_create_dependents_test_runner', 0)): - tgt_name = bf_tgt['target_name'] - toolset = bf_tgt['toolset'] - qualified_target = gyp.common.QualifiedTarget(self.gyp_path, - tgt_name, toolset) - xcode_target = xcode_targets[qualified_target] - if isinstance(xcode_target, gyp.xcodeproj_file.PBXAggregateTarget): - # Collect all the run test targets. - all_run_tests = [] - pbxtds = xcode_target.GetProperty('dependencies') - for pbxtd in pbxtds: - pbxcip = pbxtd.GetProperty('targetProxy') - dependency_xct = pbxcip.GetProperty('remoteGlobalIDString') - if hasattr(dependency_xct, 'test_runner'): - all_run_tests.append(dependency_xct.test_runner) - - # Directly depend on all the runners as they depend on the target - # that builds them. - if len(all_run_tests) > 0: - run_all_target = gyp.xcodeproj_file.PBXAggregateTarget({ - 'name': 'Run %s Tests' % tgt_name, - 'productName': tgt_name, - }, - parent=self.project) - for run_test_target in all_run_tests: - run_all_target.AddDependency(run_test_target) - - # Insert the test runner after the related target. - idx = self.project._properties['targets'].index(xcode_target) - self.project._properties['targets'].insert(idx + 1, run_all_target) - - # Update all references to other projects, to make sure that the lists of - # remote products are complete. Otherwise, Xcode will fill them in when - # it opens the project file, which will result in unnecessary diffs. - # TODO(mark): This is evil because it relies on internal knowledge of - # PBXProject._other_pbxprojects. - for other_pbxproject in self.project._other_pbxprojects.keys(): - self.project.AddOrGetProjectReference(other_pbxproject) - - self.project.SortRemoteProductReferences() - - # Give everything an ID. - self.project_file.ComputeIDs() - - # Make sure that no two objects in the project file have the same ID. If - # multiple objects wind up with the same ID, upon loading the file, Xcode - # will only recognize one object (the last one in the file?) and the - # results are unpredictable. - self.project_file.EnsureNoIDCollisions() - - def Write(self): - # Write the project file to a temporary location first. Xcode watches for - # changes to the project file and presents a UI sheet offering to reload - # the project when it does change. However, in some cases, especially when - # multiple projects are open or when Xcode is busy, things don't work so - # seamlessly. Sometimes, Xcode is able to detect that a project file has - # changed but can't unload it because something else is referencing it. - # To mitigate this problem, and to avoid even having Xcode present the UI - # sheet when an open project is rewritten for inconsequential changes, the - # project file is written to a temporary file in the xcodeproj directory - # first. The new temporary file is then compared to the existing project - # file, if any. If they differ, the new file replaces the old; otherwise, - # the new project file is simply deleted. Xcode properly detects a file - # being renamed over an open project file as a change and so it remains - # able to present the "project file changed" sheet under this system. - # Writing to a temporary file first also avoids the possible problem of - # Xcode rereading an incomplete project file. - (output_fd, new_pbxproj_path) = \ - tempfile.mkstemp(suffix='.tmp', prefix='project.pbxproj.gyp.', - dir=self.path) - - try: - output_file = os.fdopen(output_fd, 'wb') - - self.project_file.Print(output_file) - output_file.close() - - pbxproj_path = os.path.join(self.path, 'project.pbxproj') - - same = False - try: - same = filecmp.cmp(pbxproj_path, new_pbxproj_path, False) - except OSError, e: - if e.errno != errno.ENOENT: - raise - - if same: - # The new file is identical to the old one, just get rid of the new - # one. - os.unlink(new_pbxproj_path) - else: - # The new file is different from the old one, or there is no old one. - # Rename the new file to the permanent name. - # - # tempfile.mkstemp uses an overly restrictive mode, resulting in a - # file that can only be read by the owner, regardless of the umask. - # There's no reason to not respect the umask here, which means that - # an extra hoop is required to fetch it and reset the new file's mode. - # - # No way to get the umask without setting a new one? Set a safe one - # and then set it back to the old value. - umask = os.umask(077) - os.umask(umask) - - os.chmod(new_pbxproj_path, 0666 & ~umask) - os.rename(new_pbxproj_path, pbxproj_path) - - except Exception: - # Don't leave turds behind. In fact, if this code was responsible for - # creating the xcodeproj directory, get rid of that too. - os.unlink(new_pbxproj_path) - if self.created_dir: - shutil.rmtree(self.path, True) - raise - - -def AddSourceToTarget(source, type, pbxp, xct): - # TODO(mark): Perhaps source_extensions and library_extensions can be made a - # little bit fancier. - source_extensions = ['c', 'cc', 'cpp', 'cxx', 'm', 'mm', 's', 'swift'] - - # .o is conceptually more of a "source" than a "library," but Xcode thinks - # of "sources" as things to compile and "libraries" (or "frameworks") as - # things to link with. Adding an object file to an Xcode target's frameworks - # phase works properly. - library_extensions = ['a', 'dylib', 'framework', 'o'] - - basename = posixpath.basename(source) - (root, ext) = posixpath.splitext(basename) - if ext: - ext = ext[1:].lower() - - if ext in source_extensions and type != 'none': - xct.SourcesPhase().AddFile(source) - elif ext in library_extensions and type != 'none': - xct.FrameworksPhase().AddFile(source) - else: - # Files that aren't added to a sources or frameworks build phase can still - # go into the project file, just not as part of a build phase. - pbxp.AddOrGetFileInRootGroup(source) - - -def AddResourceToTarget(resource, pbxp, xct): - # TODO(mark): Combine with AddSourceToTarget above? Or just inline this call - # where it's used. - xct.ResourcesPhase().AddFile(resource) - - -def AddHeaderToTarget(header, pbxp, xct, is_public): - # TODO(mark): Combine with AddSourceToTarget above? Or just inline this call - # where it's used. - settings = '{ATTRIBUTES = (%s, ); }' % ('Private', 'Public')[is_public] - xct.HeadersPhase().AddFile(header, settings) - - -_xcode_variable_re = re.compile(r'(\$\((.*?)\))') -def ExpandXcodeVariables(string, expansions): - """Expands Xcode-style $(VARIABLES) in string per the expansions dict. - - In some rare cases, it is appropriate to expand Xcode variables when a - project file is generated. For any substring $(VAR) in string, if VAR is a - key in the expansions dict, $(VAR) will be replaced with expansions[VAR]. - Any $(VAR) substring in string for which VAR is not a key in the expansions - dict will remain in the returned string. - """ - - matches = _xcode_variable_re.findall(string) - if matches == None: - return string - - matches.reverse() - for match in matches: - (to_replace, variable) = match - if not variable in expansions: - continue - - replacement = expansions[variable] - string = re.sub(re.escape(to_replace), replacement, string) - - return string - - -_xcode_define_re = re.compile(r'([\\\"\' ])') -def EscapeXcodeDefine(s): - """We must escape the defines that we give to XCode so that it knows not to - split on spaces and to respect backslash and quote literals. However, we - must not quote the define, or Xcode will incorrectly intepret variables - especially $(inherited).""" - return re.sub(_xcode_define_re, r'\\\1', s) - - -def PerformBuild(data, configurations, params): - options = params['options'] - - for build_file, build_file_dict in data.iteritems(): - (build_file_root, build_file_ext) = os.path.splitext(build_file) - if build_file_ext != '.gyp': - continue - xcodeproj_path = build_file_root + options.suffix + '.xcodeproj' - if options.generator_output: - xcodeproj_path = os.path.join(options.generator_output, xcodeproj_path) - - for config in configurations: - arguments = ['xcodebuild', '-project', xcodeproj_path] - arguments += ['-configuration', config] - print "Building [%s]: %s" % (config, arguments) - subprocess.check_call(arguments) - - -def CalculateGeneratorInputInfo(params): - toplevel = params['options'].toplevel_dir - if params.get('flavor') == 'ninja': - generator_dir = os.path.relpath(params['options'].generator_output or '.') - output_dir = params.get('generator_flags', {}).get('output_dir', 'out') - output_dir = os.path.normpath(os.path.join(generator_dir, output_dir)) - qualified_out_dir = os.path.normpath(os.path.join( - toplevel, output_dir, 'gypfiles-xcode-ninja')) - else: - output_dir = os.path.normpath(os.path.join(toplevel, 'xcodebuild')) - qualified_out_dir = os.path.normpath(os.path.join( - toplevel, output_dir, 'gypfiles')) - - global generator_filelist_paths - generator_filelist_paths = { - 'toplevel': toplevel, - 'qualified_out_dir': qualified_out_dir, - } - - -def GenerateOutput(target_list, target_dicts, data, params): - # Optionally configure each spec to use ninja as the external builder. - ninja_wrapper = params.get('flavor') == 'ninja' - if ninja_wrapper: - (target_list, target_dicts, data) = \ - gyp.xcode_ninja.CreateWrapper(target_list, target_dicts, data, params) - - options = params['options'] - generator_flags = params.get('generator_flags', {}) - parallel_builds = generator_flags.get('xcode_parallel_builds', True) - serialize_all_tests = \ - generator_flags.get('xcode_serialize_all_test_runs', True) - upgrade_check_project_version = \ - generator_flags.get('xcode_upgrade_check_project_version', None) - - # Format upgrade_check_project_version with leading zeros as needed. - if upgrade_check_project_version: - upgrade_check_project_version = str(upgrade_check_project_version) - while len(upgrade_check_project_version) < 4: - upgrade_check_project_version = '0' + upgrade_check_project_version - - skip_excluded_files = \ - not generator_flags.get('xcode_list_excluded_files', True) - xcode_projects = {} - for build_file, build_file_dict in data.iteritems(): - (build_file_root, build_file_ext) = os.path.splitext(build_file) - if build_file_ext != '.gyp': - continue - xcodeproj_path = build_file_root + options.suffix + '.xcodeproj' - if options.generator_output: - xcodeproj_path = os.path.join(options.generator_output, xcodeproj_path) - xcp = XcodeProject(build_file, xcodeproj_path, build_file_dict) - xcode_projects[build_file] = xcp - pbxp = xcp.project - - # Set project-level attributes from multiple options - project_attributes = {}; - if parallel_builds: - project_attributes['BuildIndependentTargetsInParallel'] = 'YES' - if upgrade_check_project_version: - project_attributes['LastUpgradeCheck'] = upgrade_check_project_version - project_attributes['LastTestingUpgradeCheck'] = \ - upgrade_check_project_version - project_attributes['LastSwiftUpdateCheck'] = \ - upgrade_check_project_version - pbxp.SetProperty('attributes', project_attributes) - - # Add gyp/gypi files to project - if not generator_flags.get('standalone'): - main_group = pbxp.GetProperty('mainGroup') - build_group = gyp.xcodeproj_file.PBXGroup({'name': 'Build'}) - main_group.AppendChild(build_group) - for included_file in build_file_dict['included_files']: - build_group.AddOrGetFileByPath(included_file, False) - - xcode_targets = {} - xcode_target_to_target_dict = {} - for qualified_target in target_list: - [build_file, target_name, toolset] = \ - gyp.common.ParseQualifiedTarget(qualified_target) - - spec = target_dicts[qualified_target] - if spec['toolset'] != 'target': - raise Exception( - 'Multiple toolsets not supported in xcode build (target %s)' % - qualified_target) - configuration_names = [spec['default_configuration']] - for configuration_name in sorted(spec['configurations'].keys()): - if configuration_name not in configuration_names: - configuration_names.append(configuration_name) - xcp = xcode_projects[build_file] - pbxp = xcp.project - - # Set up the configurations for the target according to the list of names - # supplied. - xccl = CreateXCConfigurationList(configuration_names) - - # Create an XCTarget subclass object for the target. The type with - # "+bundle" appended will be used if the target has "mac_bundle" set. - # loadable_modules not in a mac_bundle are mapped to - # com.googlecode.gyp.xcode.bundle, a pseudo-type that xcode.py interprets - # to create a single-file mh_bundle. - _types = { - 'executable': 'com.apple.product-type.tool', - 'loadable_module': 'com.googlecode.gyp.xcode.bundle', - 'shared_library': 'com.apple.product-type.library.dynamic', - 'static_library': 'com.apple.product-type.library.static', - 'mac_kernel_extension': 'com.apple.product-type.kernel-extension', - 'executable+bundle': 'com.apple.product-type.application', - 'loadable_module+bundle': 'com.apple.product-type.bundle', - 'loadable_module+xctest': 'com.apple.product-type.bundle.unit-test', - 'shared_library+bundle': 'com.apple.product-type.framework', - 'executable+extension+bundle': 'com.apple.product-type.app-extension', - 'executable+watch+extension+bundle': - 'com.apple.product-type.watchkit-extension', - 'executable+watch+bundle': - 'com.apple.product-type.application.watchapp', - 'mac_kernel_extension+bundle': 'com.apple.product-type.kernel-extension', - } - - target_properties = { - 'buildConfigurationList': xccl, - 'name': target_name, - } - - type = spec['type'] - is_xctest = int(spec.get('mac_xctest_bundle', 0)) - is_bundle = int(spec.get('mac_bundle', 0)) or is_xctest - is_app_extension = int(spec.get('ios_app_extension', 0)) - is_watchkit_extension = int(spec.get('ios_watchkit_extension', 0)) - is_watch_app = int(spec.get('ios_watch_app', 0)) - if type != 'none': - type_bundle_key = type - if is_xctest: - type_bundle_key += '+xctest' - assert type == 'loadable_module', ( - 'mac_xctest_bundle targets must have type loadable_module ' - '(target %s)' % target_name) - elif is_app_extension: - assert is_bundle, ('ios_app_extension flag requires mac_bundle ' - '(target %s)' % target_name) - type_bundle_key += '+extension+bundle' - elif is_watchkit_extension: - assert is_bundle, ('ios_watchkit_extension flag requires mac_bundle ' - '(target %s)' % target_name) - type_bundle_key += '+watch+extension+bundle' - elif is_watch_app: - assert is_bundle, ('ios_watch_app flag requires mac_bundle ' - '(target %s)' % target_name) - type_bundle_key += '+watch+bundle' - elif is_bundle: - type_bundle_key += '+bundle' - - xctarget_type = gyp.xcodeproj_file.PBXNativeTarget - try: - target_properties['productType'] = _types[type_bundle_key] - except KeyError, e: - gyp.common.ExceptionAppend(e, "-- unknown product type while " - "writing target %s" % target_name) - raise - else: - xctarget_type = gyp.xcodeproj_file.PBXAggregateTarget - assert not is_bundle, ( - 'mac_bundle targets cannot have type none (target "%s")' % - target_name) - assert not is_xctest, ( - 'mac_xctest_bundle targets cannot have type none (target "%s")' % - target_name) - - target_product_name = spec.get('product_name') - if target_product_name is not None: - target_properties['productName'] = target_product_name - - xct = xctarget_type(target_properties, parent=pbxp, - force_outdir=spec.get('product_dir'), - force_prefix=spec.get('product_prefix'), - force_extension=spec.get('product_extension')) - pbxp.AppendProperty('targets', xct) - xcode_targets[qualified_target] = xct - xcode_target_to_target_dict[xct] = spec - - spec_actions = spec.get('actions', []) - spec_rules = spec.get('rules', []) - - # Xcode has some "issues" with checking dependencies for the "Compile - # sources" step with any source files/headers generated by actions/rules. - # To work around this, if a target is building anything directly (not - # type "none"), then a second target is used to run the GYP actions/rules - # and is made a dependency of this target. This way the work is done - # before the dependency checks for what should be recompiled. - support_xct = None - # The Xcode "issues" don't affect xcode-ninja builds, since the dependency - # logic all happens in ninja. Don't bother creating the extra targets in - # that case. - if type != 'none' and (spec_actions or spec_rules) and not ninja_wrapper: - support_xccl = CreateXCConfigurationList(configuration_names); - support_target_suffix = generator_flags.get( - 'support_target_suffix', ' Support') - support_target_properties = { - 'buildConfigurationList': support_xccl, - 'name': target_name + support_target_suffix, - } - if target_product_name: - support_target_properties['productName'] = \ - target_product_name + ' Support' - support_xct = \ - gyp.xcodeproj_file.PBXAggregateTarget(support_target_properties, - parent=pbxp) - pbxp.AppendProperty('targets', support_xct) - xct.AddDependency(support_xct) - # Hang the support target off the main target so it can be tested/found - # by the generator during Finalize. - xct.support_target = support_xct - - prebuild_index = 0 - - # Add custom shell script phases for "actions" sections. - for action in spec_actions: - # There's no need to write anything into the script to ensure that the - # output directories already exist, because Xcode will look at the - # declared outputs and automatically ensure that they exist for us. - - # Do we have a message to print when this action runs? - message = action.get('message') - if message: - message = 'echo note: ' + gyp.common.EncodePOSIXShellArgument(message) - else: - message = '' - - # Turn the list into a string that can be passed to a shell. - action_string = gyp.common.EncodePOSIXShellList(action['action']) - - # Convert Xcode-type variable references to sh-compatible environment - # variable references. - message_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax(message) - action_string_sh = gyp.xcodeproj_file.ConvertVariablesToShellSyntax( - action_string) - - script = '' - # Include the optional message - if message_sh: - script += message_sh + '\n' - # Be sure the script runs in exec, and that if exec fails, the script - # exits signalling an error. - script += 'exec ' + action_string_sh + '\nexit 1\n' - ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ - 'inputPaths': action['inputs'], - 'name': 'Action "' + action['action_name'] + '"', - 'outputPaths': action['outputs'], - 'shellScript': script, - 'showEnvVarsInLog': 0, - }) - - if support_xct: - support_xct.AppendProperty('buildPhases', ssbp) - else: - # TODO(mark): this assumes too much knowledge of the internals of - # xcodeproj_file; some of these smarts should move into xcodeproj_file - # itself. - xct._properties['buildPhases'].insert(prebuild_index, ssbp) - prebuild_index = prebuild_index + 1 - - # TODO(mark): Should verify that at most one of these is specified. - if int(action.get('process_outputs_as_sources', False)): - for output in action['outputs']: - AddSourceToTarget(output, type, pbxp, xct) - - if int(action.get('process_outputs_as_mac_bundle_resources', False)): - for output in action['outputs']: - AddResourceToTarget(output, pbxp, xct) - - # tgt_mac_bundle_resources holds the list of bundle resources so - # the rule processing can check against it. - if is_bundle: - tgt_mac_bundle_resources = spec.get('mac_bundle_resources', []) - else: - tgt_mac_bundle_resources = [] - - # Add custom shell script phases driving "make" for "rules" sections. - # - # Xcode's built-in rule support is almost powerful enough to use directly, - # but there are a few significant deficiencies that render them unusable. - # There are workarounds for some of its inadequacies, but in aggregate, - # the workarounds added complexity to the generator, and some workarounds - # actually require input files to be crafted more carefully than I'd like. - # Consequently, until Xcode rules are made more capable, "rules" input - # sections will be handled in Xcode output by shell script build phases - # performed prior to the compilation phase. - # - # The following problems with Xcode rules were found. The numbers are - # Apple radar IDs. I hope that these shortcomings are addressed, I really - # liked having the rules handled directly in Xcode during the period that - # I was prototyping this. - # - # 6588600 Xcode compiles custom script rule outputs too soon, compilation - # fails. This occurs when rule outputs from distinct inputs are - # interdependent. The only workaround is to put rules and their - # inputs in a separate target from the one that compiles the rule - # outputs. This requires input file cooperation and it means that - # process_outputs_as_sources is unusable. - # 6584932 Need to declare that custom rule outputs should be excluded from - # compilation. A possible workaround is to lie to Xcode about a - # rule's output, giving it a dummy file it doesn't know how to - # compile. The rule action script would need to touch the dummy. - # 6584839 I need a way to declare additional inputs to a custom rule. - # A possible workaround is a shell script phase prior to - # compilation that touches a rule's primary input files if any - # would-be additional inputs are newer than the output. Modifying - # the source tree - even just modification times - feels dirty. - # 6564240 Xcode "custom script" build rules always dump all environment - # variables. This is a low-prioroty problem and is not a - # show-stopper. - rules_by_ext = {} - for rule in spec_rules: - rules_by_ext[rule['extension']] = rule - - # First, some definitions: - # - # A "rule source" is a file that was listed in a target's "sources" - # list and will have a rule applied to it on the basis of matching the - # rule's "extensions" attribute. Rule sources are direct inputs to - # rules. - # - # Rule definitions may specify additional inputs in their "inputs" - # attribute. These additional inputs are used for dependency tracking - # purposes. - # - # A "concrete output" is a rule output with input-dependent variables - # resolved. For example, given a rule with: - # 'extension': 'ext', 'outputs': ['$(INPUT_FILE_BASE).cc'], - # if the target's "sources" list contained "one.ext" and "two.ext", - # the "concrete output" for rule input "two.ext" would be "two.cc". If - # a rule specifies multiple outputs, each input file that the rule is - # applied to will have the same number of concrete outputs. - # - # If any concrete outputs are outdated or missing relative to their - # corresponding rule_source or to any specified additional input, the - # rule action must be performed to generate the concrete outputs. - - # concrete_outputs_by_rule_source will have an item at the same index - # as the rule['rule_sources'] that it corresponds to. Each item is a - # list of all of the concrete outputs for the rule_source. - concrete_outputs_by_rule_source = [] - - # concrete_outputs_all is a flat list of all concrete outputs that this - # rule is able to produce, given the known set of input files - # (rule_sources) that apply to it. - concrete_outputs_all = [] - - # messages & actions are keyed by the same indices as rule['rule_sources'] - # and concrete_outputs_by_rule_source. They contain the message and - # action to perform after resolving input-dependent variables. The - # message is optional, in which case None is stored for each rule source. - messages = [] - actions = [] - - for rule_source in rule.get('rule_sources', []): - rule_source_dirname, rule_source_basename = \ - posixpath.split(rule_source) - (rule_source_root, rule_source_ext) = \ - posixpath.splitext(rule_source_basename) - - # These are the same variable names that Xcode uses for its own native - # rule support. Because Xcode's rule engine is not being used, they - # need to be expanded as they are written to the makefile. - rule_input_dict = { - 'INPUT_FILE_BASE': rule_source_root, - 'INPUT_FILE_SUFFIX': rule_source_ext, - 'INPUT_FILE_NAME': rule_source_basename, - 'INPUT_FILE_PATH': rule_source, - 'INPUT_FILE_DIRNAME': rule_source_dirname, - } - - concrete_outputs_for_this_rule_source = [] - for output in rule.get('outputs', []): - # Fortunately, Xcode and make both use $(VAR) format for their - # variables, so the expansion is the only transformation necessary. - # Any remaning $(VAR)-type variables in the string can be given - # directly to make, which will pick up the correct settings from - # what Xcode puts into the environment. - concrete_output = ExpandXcodeVariables(output, rule_input_dict) - concrete_outputs_for_this_rule_source.append(concrete_output) - - # Add all concrete outputs to the project. - pbxp.AddOrGetFileInRootGroup(concrete_output) - - concrete_outputs_by_rule_source.append( \ - concrete_outputs_for_this_rule_source) - concrete_outputs_all.extend(concrete_outputs_for_this_rule_source) - - # TODO(mark): Should verify that at most one of these is specified. - if int(rule.get('process_outputs_as_sources', False)): - for output in concrete_outputs_for_this_rule_source: - AddSourceToTarget(output, type, pbxp, xct) - - # If the file came from the mac_bundle_resources list or if the rule - # is marked to process outputs as bundle resource, do so. - was_mac_bundle_resource = rule_source in tgt_mac_bundle_resources - if was_mac_bundle_resource or \ - int(rule.get('process_outputs_as_mac_bundle_resources', False)): - for output in concrete_outputs_for_this_rule_source: - AddResourceToTarget(output, pbxp, xct) - - # Do we have a message to print when this rule runs? - message = rule.get('message') - if message: - message = gyp.common.EncodePOSIXShellArgument(message) - message = ExpandXcodeVariables(message, rule_input_dict) - messages.append(message) - - # Turn the list into a string that can be passed to a shell. - action_string = gyp.common.EncodePOSIXShellList(rule['action']) - - action = ExpandXcodeVariables(action_string, rule_input_dict) - actions.append(action) - - if len(concrete_outputs_all) > 0: - # TODO(mark): There's a possibilty for collision here. Consider - # target "t" rule "A_r" and target "t_A" rule "r". - makefile_name = '%s.make' % re.sub( - '[^a-zA-Z0-9_]', '_' , '%s_%s' % (target_name, rule['rule_name'])) - makefile_path = os.path.join(xcode_projects[build_file].path, - makefile_name) - # TODO(mark): try/close? Write to a temporary file and swap it only - # if it's got changes? - makefile = open(makefile_path, 'wb') - - # make will build the first target in the makefile by default. By - # convention, it's called "all". List all (or at least one) - # concrete output for each rule source as a prerequisite of the "all" - # target. - makefile.write('all: \\\n') - for concrete_output_index in \ - xrange(0, len(concrete_outputs_by_rule_source)): - # Only list the first (index [0]) concrete output of each input - # in the "all" target. Otherwise, a parallel make (-j > 1) would - # attempt to process each input multiple times simultaneously. - # Otherwise, "all" could just contain the entire list of - # concrete_outputs_all. - concrete_output = \ - concrete_outputs_by_rule_source[concrete_output_index][0] - if concrete_output_index == len(concrete_outputs_by_rule_source) - 1: - eol = '' - else: - eol = ' \\' - makefile.write(' %s%s\n' % (concrete_output, eol)) - - for (rule_source, concrete_outputs, message, action) in \ - zip(rule['rule_sources'], concrete_outputs_by_rule_source, - messages, actions): - makefile.write('\n') - - # Add a rule that declares it can build each concrete output of a - # rule source. Collect the names of the directories that are - # required. - concrete_output_dirs = [] - for concrete_output_index in xrange(0, len(concrete_outputs)): - concrete_output = concrete_outputs[concrete_output_index] - if concrete_output_index == 0: - bol = '' - else: - bol = ' ' - makefile.write('%s%s \\\n' % (bol, concrete_output)) - - concrete_output_dir = posixpath.dirname(concrete_output) - if (concrete_output_dir and - concrete_output_dir not in concrete_output_dirs): - concrete_output_dirs.append(concrete_output_dir) - - makefile.write(' : \\\n') - - # The prerequisites for this rule are the rule source itself and - # the set of additional rule inputs, if any. - prerequisites = [rule_source] - prerequisites.extend(rule.get('inputs', [])) - for prerequisite_index in xrange(0, len(prerequisites)): - prerequisite = prerequisites[prerequisite_index] - if prerequisite_index == len(prerequisites) - 1: - eol = '' - else: - eol = ' \\' - makefile.write(' %s%s\n' % (prerequisite, eol)) - - # Make sure that output directories exist before executing the rule - # action. - if len(concrete_output_dirs) > 0: - makefile.write('\t@mkdir -p "%s"\n' % - '" "'.join(concrete_output_dirs)) - - # The rule message and action have already had the necessary variable - # substitutions performed. - if message: - # Mark it with note: so Xcode picks it up in build output. - makefile.write('\t@echo note: %s\n' % message) - makefile.write('\t%s\n' % action) - - makefile.close() - - # It might be nice to ensure that needed output directories exist - # here rather than in each target in the Makefile, but that wouldn't - # work if there ever was a concrete output that had an input-dependent - # variable anywhere other than in the leaf position. - - # Don't declare any inputPaths or outputPaths. If they're present, - # Xcode will provide a slight optimization by only running the script - # phase if any output is missing or outdated relative to any input. - # Unfortunately, it will also assume that all outputs are touched by - # the script, and if the outputs serve as files in a compilation - # phase, they will be unconditionally rebuilt. Since make might not - # rebuild everything that could be declared here as an output, this - # extra compilation activity is unnecessary. With inputPaths and - # outputPaths not supplied, make will always be called, but it knows - # enough to not do anything when everything is up-to-date. - - # To help speed things up, pass -j COUNT to make so it does some work - # in parallel. Don't use ncpus because Xcode will build ncpus targets - # in parallel and if each target happens to have a rules step, there - # would be ncpus^2 things going. With a machine that has 2 quad-core - # Xeons, a build can quickly run out of processes based on - # scheduling/other tasks, and randomly failing builds are no good. - script = \ -"""JOB_COUNT="$(/usr/sbin/sysctl -n hw.ncpu)" -if [ "${JOB_COUNT}" -gt 4 ]; then - JOB_COUNT=4 -fi -exec xcrun make -f "${PROJECT_FILE_PATH}/%s" -j "${JOB_COUNT}" -exit 1 -""" % makefile_name - ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ - 'name': 'Rule "' + rule['rule_name'] + '"', - 'shellScript': script, - 'showEnvVarsInLog': 0, - }) - - if support_xct: - support_xct.AppendProperty('buildPhases', ssbp) - else: - # TODO(mark): this assumes too much knowledge of the internals of - # xcodeproj_file; some of these smarts should move into xcodeproj_file - # itself. - xct._properties['buildPhases'].insert(prebuild_index, ssbp) - prebuild_index = prebuild_index + 1 - - # Extra rule inputs also go into the project file. Concrete outputs were - # already added when they were computed. - groups = ['inputs', 'inputs_excluded'] - if skip_excluded_files: - groups = [x for x in groups if not x.endswith('_excluded')] - for group in groups: - for item in rule.get(group, []): - pbxp.AddOrGetFileInRootGroup(item) - - # Add "sources". - for source in spec.get('sources', []): - (source_root, source_extension) = posixpath.splitext(source) - if source_extension[1:] not in rules_by_ext: - # AddSourceToTarget will add the file to a root group if it's not - # already there. - AddSourceToTarget(source, type, pbxp, xct) - else: - pbxp.AddOrGetFileInRootGroup(source) - - # Add "mac_bundle_resources" and "mac_framework_private_headers" if - # it's a bundle of any type. - if is_bundle: - for resource in tgt_mac_bundle_resources: - (resource_root, resource_extension) = posixpath.splitext(resource) - if resource_extension[1:] not in rules_by_ext: - AddResourceToTarget(resource, pbxp, xct) - else: - pbxp.AddOrGetFileInRootGroup(resource) - - for header in spec.get('mac_framework_private_headers', []): - AddHeaderToTarget(header, pbxp, xct, False) - - # Add "mac_framework_headers". These can be valid for both frameworks - # and static libraries. - if is_bundle or type == 'static_library': - for header in spec.get('mac_framework_headers', []): - AddHeaderToTarget(header, pbxp, xct, True) - - # Add "copies". - pbxcp_dict = {} - for copy_group in spec.get('copies', []): - dest = copy_group['destination'] - if dest[0] not in ('/', '$'): - # Relative paths are relative to $(SRCROOT). - dest = '$(SRCROOT)/' + dest - - code_sign = int(copy_group.get('xcode_code_sign', 0)) - settings = (None, '{ATTRIBUTES = (CodeSignOnCopy, ); }')[code_sign]; - - # Coalesce multiple "copies" sections in the same target with the same - # "destination" property into the same PBXCopyFilesBuildPhase, otherwise - # they'll wind up with ID collisions. - pbxcp = pbxcp_dict.get(dest, None) - if pbxcp is None: - pbxcp = gyp.xcodeproj_file.PBXCopyFilesBuildPhase({ - 'name': 'Copy to ' + copy_group['destination'] - }, - parent=xct) - pbxcp.SetDestination(dest) - - # TODO(mark): The usual comment about this knowing too much about - # gyp.xcodeproj_file internals applies. - xct._properties['buildPhases'].insert(prebuild_index, pbxcp) - - pbxcp_dict[dest] = pbxcp - - for file in copy_group['files']: - pbxcp.AddFile(file, settings) - - # Excluded files can also go into the project file. - if not skip_excluded_files: - for key in ['sources', 'mac_bundle_resources', 'mac_framework_headers', - 'mac_framework_private_headers']: - excluded_key = key + '_excluded' - for item in spec.get(excluded_key, []): - pbxp.AddOrGetFileInRootGroup(item) - - # So can "inputs" and "outputs" sections of "actions" groups. - groups = ['inputs', 'inputs_excluded', 'outputs', 'outputs_excluded'] - if skip_excluded_files: - groups = [x for x in groups if not x.endswith('_excluded')] - for action in spec.get('actions', []): - for group in groups: - for item in action.get(group, []): - # Exclude anything in BUILT_PRODUCTS_DIR. They're products, not - # sources. - if not item.startswith('$(BUILT_PRODUCTS_DIR)/'): - pbxp.AddOrGetFileInRootGroup(item) - - for postbuild in spec.get('postbuilds', []): - action_string_sh = gyp.common.EncodePOSIXShellList(postbuild['action']) - script = 'exec ' + action_string_sh + '\nexit 1\n' - - # Make the postbuild step depend on the output of ld or ar from this - # target. Apparently putting the script step after the link step isn't - # sufficient to ensure proper ordering in all cases. With an input - # declared but no outputs, the script step should run every time, as - # desired. - ssbp = gyp.xcodeproj_file.PBXShellScriptBuildPhase({ - 'inputPaths': ['$(BUILT_PRODUCTS_DIR)/$(EXECUTABLE_PATH)'], - 'name': 'Postbuild "' + postbuild['postbuild_name'] + '"', - 'shellScript': script, - 'showEnvVarsInLog': 0, - }) - xct.AppendProperty('buildPhases', ssbp) - - # Add dependencies before libraries, because adding a dependency may imply - # adding a library. It's preferable to keep dependencies listed first - # during a link phase so that they can override symbols that would - # otherwise be provided by libraries, which will usually include system - # libraries. On some systems, ld is finicky and even requires the - # libraries to be ordered in such a way that unresolved symbols in - # earlier-listed libraries may only be resolved by later-listed libraries. - # The Mac linker doesn't work that way, but other platforms do, and so - # their linker invocations need to be constructed in this way. There's - # no compelling reason for Xcode's linker invocations to differ. - - if 'dependencies' in spec: - for dependency in spec['dependencies']: - xct.AddDependency(xcode_targets[dependency]) - # The support project also gets the dependencies (in case they are - # needed for the actions/rules to work). - if support_xct: - support_xct.AddDependency(xcode_targets[dependency]) - - if 'libraries' in spec: - for library in spec['libraries']: - xct.FrameworksPhase().AddFile(library) - # Add the library's directory to LIBRARY_SEARCH_PATHS if necessary. - # I wish Xcode handled this automatically. - library_dir = posixpath.dirname(library) - if library_dir not in xcode_standard_library_dirs and ( - not xct.HasBuildSetting(_library_search_paths_var) or - library_dir not in xct.GetBuildSetting(_library_search_paths_var)): - xct.AppendBuildSetting(_library_search_paths_var, library_dir) - - for configuration_name in configuration_names: - configuration = spec['configurations'][configuration_name] - xcbc = xct.ConfigurationNamed(configuration_name) - for include_dir in configuration.get('mac_framework_dirs', []): - xcbc.AppendBuildSetting('FRAMEWORK_SEARCH_PATHS', include_dir) - for include_dir in configuration.get('include_dirs', []): - xcbc.AppendBuildSetting('HEADER_SEARCH_PATHS', include_dir) - for library_dir in configuration.get('library_dirs', []): - if library_dir not in xcode_standard_library_dirs and ( - not xcbc.HasBuildSetting(_library_search_paths_var) or - library_dir not in xcbc.GetBuildSetting(_library_search_paths_var)): - xcbc.AppendBuildSetting(_library_search_paths_var, library_dir) - - if 'defines' in configuration: - for define in configuration['defines']: - set_define = EscapeXcodeDefine(define) - xcbc.AppendBuildSetting('GCC_PREPROCESSOR_DEFINITIONS', set_define) - if 'xcode_settings' in configuration: - for xck, xcv in configuration['xcode_settings'].iteritems(): - xcbc.SetBuildSetting(xck, xcv) - if 'xcode_config_file' in configuration: - config_ref = pbxp.AddOrGetFileInRootGroup( - configuration['xcode_config_file']) - xcbc.SetBaseConfiguration(config_ref) - - build_files = [] - for build_file, build_file_dict in data.iteritems(): - if build_file.endswith('.gyp'): - build_files.append(build_file) - - for build_file in build_files: - xcode_projects[build_file].Finalize1(xcode_targets, serialize_all_tests) - - for build_file in build_files: - xcode_projects[build_file].Finalize2(xcode_targets, - xcode_target_to_target_dict) - - for build_file in build_files: - xcode_projects[build_file].Write() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py deleted file mode 100644 index 260324a43f3e2..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/generator/xcode_test.py +++ /dev/null @@ -1,23 +0,0 @@ -#!/usr/bin/env python - -# 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. - -""" Unit tests for the xcode.py file. """ - -import gyp.generator.xcode as xcode -import unittest -import sys - - -class TestEscapeXcodeDefine(unittest.TestCase): - if sys.platform == 'darwin': - def test_InheritedRemainsUnescaped(self): - self.assertEqual(xcode.EscapeXcodeDefine('$(inherited)'), '$(inherited)') - - def test_Escaping(self): - self.assertEqual(xcode.EscapeXcodeDefine('a b"c\\'), 'a\\ b\\"c\\\\') - -if __name__ == '__main__': - unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input.py deleted file mode 100644 index 10f6e0dba16de..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input.py +++ /dev/null @@ -1,2902 +0,0 @@ -# Copyright (c) 2012 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. - -from compiler.ast import Const -from compiler.ast import Dict -from compiler.ast import Discard -from compiler.ast import List -from compiler.ast import Module -from compiler.ast import Node -from compiler.ast import Stmt -import compiler -import gyp.common -import gyp.simple_copy -import multiprocessing -import optparse -import os.path -import re -import shlex -import signal -import subprocess -import sys -import threading -import time -import traceback -from gyp.common import GypError -from gyp.common import OrderedSet - - -# A list of types that are treated as linkable. -linkable_types = [ - 'executable', - 'shared_library', - 'loadable_module', - 'mac_kernel_extension', -] - -# A list of sections that contain links to other targets. -dependency_sections = ['dependencies', 'export_dependent_settings'] - -# base_path_sections is a list of sections defined by GYP that contain -# pathnames. The generators can provide more keys, the two lists are merged -# into path_sections, but you should call IsPathSection instead of using either -# list directly. -base_path_sections = [ - 'destination', - 'files', - 'include_dirs', - 'inputs', - 'libraries', - 'outputs', - 'sources', -] -path_sections = set() - -# These per-process dictionaries are used to cache build file data when loading -# in parallel mode. -per_process_data = {} -per_process_aux_data = {} - -def IsPathSection(section): - # If section ends in one of the '=+?!' characters, it's applied to a section - # without the trailing characters. '/' is notably absent from this list, - # because there's no way for a regular expression to be treated as a path. - while section and section[-1:] in '=+?!': - section = section[:-1] - - if section in path_sections: - return True - - # Sections mathing the regexp '_(dir|file|path)s?$' are also - # considered PathSections. Using manual string matching since that - # is much faster than the regexp and this can be called hundreds of - # thousands of times so micro performance matters. - if "_" in section: - tail = section[-6:] - if tail[-1] == 's': - tail = tail[:-1] - if tail[-5:] in ('_file', '_path'): - return True - return tail[-4:] == '_dir' - - return False - -# base_non_configuration_keys is a list of key names that belong in the target -# itself and should not be propagated into its configurations. It is merged -# with a list that can come from the generator to -# create non_configuration_keys. -base_non_configuration_keys = [ - # Sections that must exist inside targets and not configurations. - 'actions', - 'configurations', - 'copies', - 'default_configuration', - 'dependencies', - 'dependencies_original', - 'libraries', - 'postbuilds', - 'product_dir', - 'product_extension', - 'product_name', - 'product_prefix', - 'rules', - 'run_as', - 'sources', - 'standalone_static_library', - 'suppress_wildcard', - 'target_name', - 'toolset', - 'toolsets', - 'type', - - # Sections that can be found inside targets or configurations, but that - # should not be propagated from targets into their configurations. - 'variables', -] -non_configuration_keys = [] - -# Keys that do not belong inside a configuration dictionary. -invalid_configuration_keys = [ - 'actions', - 'all_dependent_settings', - 'configurations', - 'dependencies', - 'direct_dependent_settings', - 'libraries', - 'link_settings', - 'sources', - 'standalone_static_library', - 'target_name', - 'type', -] - -# Controls whether or not the generator supports multiple toolsets. -multiple_toolsets = False - -# Paths for converting filelist paths to output paths: { -# toplevel, -# qualified_output_dir, -# } -generator_filelist_paths = None - -def GetIncludedBuildFiles(build_file_path, aux_data, included=None): - """Return a list of all build files included into build_file_path. - - The returned list will contain build_file_path as well as all other files - that it included, either directly or indirectly. Note that the list may - contain files that were included into a conditional section that evaluated - to false and was not merged into build_file_path's dict. - - aux_data is a dict containing a key for each build file or included build - file. Those keys provide access to dicts whose "included" keys contain - lists of all other files included by the build file. - - included should be left at its default None value by external callers. It - is used for recursion. - - The returned list will not contain any duplicate entries. Each build file - in the list will be relative to the current directory. - """ - - if included == None: - included = [] - - if build_file_path in included: - return included - - included.append(build_file_path) - - for included_build_file in aux_data[build_file_path].get('included', []): - GetIncludedBuildFiles(included_build_file, aux_data, included) - - return included - - -def CheckedEval(file_contents): - """Return the eval of a gyp file. - - The gyp file is restricted to dictionaries and lists only, and - repeated keys are not allowed. - - Note that this is slower than eval() is. - """ - - ast = compiler.parse(file_contents) - assert isinstance(ast, Module) - c1 = ast.getChildren() - assert c1[0] is None - assert isinstance(c1[1], Stmt) - c2 = c1[1].getChildren() - assert isinstance(c2[0], Discard) - c3 = c2[0].getChildren() - assert len(c3) == 1 - return CheckNode(c3[0], []) - - -def CheckNode(node, keypath): - if isinstance(node, Dict): - c = node.getChildren() - dict = {} - for n in range(0, len(c), 2): - assert isinstance(c[n], Const) - key = c[n].getChildren()[0] - if key in dict: - raise GypError("Key '" + key + "' repeated at level " + - repr(len(keypath) + 1) + " with key path '" + - '.'.join(keypath) + "'") - kp = list(keypath) # Make a copy of the list for descending this node. - kp.append(key) - dict[key] = CheckNode(c[n + 1], kp) - return dict - elif isinstance(node, List): - c = node.getChildren() - children = [] - for index, child in enumerate(c): - kp = list(keypath) # Copy list. - kp.append(repr(index)) - children.append(CheckNode(child, kp)) - return children - elif isinstance(node, Const): - return node.getChildren()[0] - else: - raise TypeError("Unknown AST node at key path '" + '.'.join(keypath) + - "': " + repr(node)) - - -def LoadOneBuildFile(build_file_path, data, aux_data, includes, - is_target, check): - if build_file_path in data: - return data[build_file_path] - - if os.path.exists(build_file_path): - # Open the build file for read ('r') with universal-newlines mode ('U') - # to make sure platform specific newlines ('\r\n' or '\r') are converted to '\n' - # which otherwise will fail eval() - if sys.platform == 'zos': - # On z/OS, universal-newlines mode treats the file as an ascii file. But since - # node-gyp produces ebcdic files, do not use that mode. - build_file_contents = open(build_file_path, 'r').read() - else: - build_file_contents = open(build_file_path, 'rU').read() - else: - raise GypError("%s not found (cwd: %s)" % (build_file_path, os.getcwd())) - - build_file_data = None - try: - if check: - build_file_data = CheckedEval(build_file_contents) - else: - build_file_data = eval(build_file_contents, {'__builtins__': None}, - None) - except SyntaxError, e: - e.filename = build_file_path - raise - except Exception, e: - gyp.common.ExceptionAppend(e, 'while reading ' + build_file_path) - raise - - if type(build_file_data) is not dict: - raise GypError("%s does not evaluate to a dictionary." % build_file_path) - - data[build_file_path] = build_file_data - aux_data[build_file_path] = {} - - # Scan for includes and merge them in. - if ('skip_includes' not in build_file_data or - not build_file_data['skip_includes']): - try: - if is_target: - LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data, - aux_data, includes, check) - else: - LoadBuildFileIncludesIntoDict(build_file_data, build_file_path, data, - aux_data, None, check) - except Exception, e: - gyp.common.ExceptionAppend(e, - 'while reading includes of ' + build_file_path) - raise - - return build_file_data - - -def LoadBuildFileIncludesIntoDict(subdict, subdict_path, data, aux_data, - includes, check): - includes_list = [] - if includes != None: - includes_list.extend(includes) - if 'includes' in subdict: - for include in subdict['includes']: - # "include" is specified relative to subdict_path, so compute the real - # path to include by appending the provided "include" to the directory - # in which subdict_path resides. - relative_include = \ - os.path.normpath(os.path.join(os.path.dirname(subdict_path), include)) - includes_list.append(relative_include) - # Unhook the includes list, it's no longer needed. - del subdict['includes'] - - # Merge in the included files. - for include in includes_list: - if not 'included' in aux_data[subdict_path]: - aux_data[subdict_path]['included'] = [] - aux_data[subdict_path]['included'].append(include) - - gyp.DebugOutput(gyp.DEBUG_INCLUDES, "Loading Included File: '%s'", include) - - MergeDicts(subdict, - LoadOneBuildFile(include, data, aux_data, None, False, check), - subdict_path, include) - - # Recurse into subdictionaries. - for k, v in subdict.iteritems(): - if type(v) is dict: - LoadBuildFileIncludesIntoDict(v, subdict_path, data, aux_data, - None, check) - elif type(v) is list: - LoadBuildFileIncludesIntoList(v, subdict_path, data, aux_data, - check) - - -# This recurses into lists so that it can look for dicts. -def LoadBuildFileIncludesIntoList(sublist, sublist_path, data, aux_data, check): - for item in sublist: - if type(item) is dict: - LoadBuildFileIncludesIntoDict(item, sublist_path, data, aux_data, - None, check) - elif type(item) is list: - LoadBuildFileIncludesIntoList(item, sublist_path, data, aux_data, check) - -# Processes toolsets in all the targets. This recurses into condition entries -# since they can contain toolsets as well. -def ProcessToolsetsInDict(data): - if 'targets' in data: - target_list = data['targets'] - new_target_list = [] - for target in target_list: - # If this target already has an explicit 'toolset', and no 'toolsets' - # list, don't modify it further. - if 'toolset' in target and 'toolsets' not in target: - new_target_list.append(target) - continue - if multiple_toolsets: - toolsets = target.get('toolsets', ['target']) - else: - toolsets = ['target'] - # Make sure this 'toolsets' definition is only processed once. - if 'toolsets' in target: - del target['toolsets'] - if len(toolsets) > 0: - # Optimization: only do copies if more than one toolset is specified. - for build in toolsets[1:]: - new_target = gyp.simple_copy.deepcopy(target) - new_target['toolset'] = build - new_target_list.append(new_target) - target['toolset'] = toolsets[0] - new_target_list.append(target) - data['targets'] = new_target_list - if 'conditions' in data: - for condition in data['conditions']: - if type(condition) is list: - for condition_dict in condition[1:]: - if type(condition_dict) is dict: - ProcessToolsetsInDict(condition_dict) - - -# TODO(mark): I don't love this name. It just means that it's going to load -# a build file that contains targets and is expected to provide a targets dict -# that contains the targets... -def LoadTargetBuildFile(build_file_path, data, aux_data, variables, includes, - depth, check, load_dependencies): - # If depth is set, predefine the DEPTH variable to be a relative path from - # this build file's directory to the directory identified by depth. - if depth: - # TODO(dglazkov) The backslash/forward-slash replacement at the end is a - # temporary measure. This should really be addressed by keeping all paths - # in POSIX until actual project generation. - d = gyp.common.RelativePath(depth, os.path.dirname(build_file_path)) - if d == '': - variables['DEPTH'] = '.' - else: - variables['DEPTH'] = d.replace('\\', '/') - - # The 'target_build_files' key is only set when loading target build files in - # the non-parallel code path, where LoadTargetBuildFile is called - # recursively. In the parallel code path, we don't need to check whether the - # |build_file_path| has already been loaded, because the 'scheduled' set in - # ParallelState guarantees that we never load the same |build_file_path| - # twice. - if 'target_build_files' in data: - if build_file_path in data['target_build_files']: - # Already loaded. - return False - data['target_build_files'].add(build_file_path) - - gyp.DebugOutput(gyp.DEBUG_INCLUDES, - "Loading Target Build File '%s'", build_file_path) - - build_file_data = LoadOneBuildFile(build_file_path, data, aux_data, - includes, True, check) - - # Store DEPTH for later use in generators. - build_file_data['_DEPTH'] = depth - - # Set up the included_files key indicating which .gyp files contributed to - # this target dict. - if 'included_files' in build_file_data: - raise GypError(build_file_path + ' must not contain included_files key') - - included = GetIncludedBuildFiles(build_file_path, aux_data) - build_file_data['included_files'] = [] - for included_file in included: - # included_file is relative to the current directory, but it needs to - # be made relative to build_file_path's directory. - included_relative = \ - gyp.common.RelativePath(included_file, - os.path.dirname(build_file_path)) - build_file_data['included_files'].append(included_relative) - - # Do a first round of toolsets expansion so that conditions can be defined - # per toolset. - ProcessToolsetsInDict(build_file_data) - - # Apply "pre"/"early" variable expansions and condition evaluations. - ProcessVariablesAndConditionsInDict( - build_file_data, PHASE_EARLY, variables, build_file_path) - - # Since some toolsets might have been defined conditionally, perform - # a second round of toolsets expansion now. - ProcessToolsetsInDict(build_file_data) - - # Look at each project's target_defaults dict, and merge settings into - # targets. - if 'target_defaults' in build_file_data: - if 'targets' not in build_file_data: - raise GypError("Unable to find targets in build file %s" % - build_file_path) - - index = 0 - while index < len(build_file_data['targets']): - # This procedure needs to give the impression that target_defaults is - # used as defaults, and the individual targets inherit from that. - # The individual targets need to be merged into the defaults. Make - # a deep copy of the defaults for each target, merge the target dict - # as found in the input file into that copy, and then hook up the - # copy with the target-specific data merged into it as the replacement - # target dict. - old_target_dict = build_file_data['targets'][index] - new_target_dict = gyp.simple_copy.deepcopy( - build_file_data['target_defaults']) - MergeDicts(new_target_dict, old_target_dict, - build_file_path, build_file_path) - build_file_data['targets'][index] = new_target_dict - index += 1 - - # No longer needed. - del build_file_data['target_defaults'] - - # Look for dependencies. This means that dependency resolution occurs - # after "pre" conditionals and variable expansion, but before "post" - - # in other words, you can't put a "dependencies" section inside a "post" - # conditional within a target. - - dependencies = [] - if 'targets' in build_file_data: - for target_dict in build_file_data['targets']: - if 'dependencies' not in target_dict: - continue - for dependency in target_dict['dependencies']: - dependencies.append( - gyp.common.ResolveTarget(build_file_path, dependency, None)[0]) - - if load_dependencies: - for dependency in dependencies: - try: - LoadTargetBuildFile(dependency, data, aux_data, variables, - includes, depth, check, load_dependencies) - except Exception, e: - gyp.common.ExceptionAppend( - e, 'while loading dependencies of %s' % build_file_path) - raise - else: - return (build_file_path, dependencies) - -def CallLoadTargetBuildFile(global_flags, - build_file_path, variables, - includes, depth, check, - generator_input_info): - """Wrapper around LoadTargetBuildFile for parallel processing. - - This wrapper is used when LoadTargetBuildFile is executed in - a worker process. - """ - - try: - signal.signal(signal.SIGINT, signal.SIG_IGN) - - # Apply globals so that the worker process behaves the same. - for key, value in global_flags.iteritems(): - globals()[key] = value - - SetGeneratorGlobals(generator_input_info) - result = LoadTargetBuildFile(build_file_path, per_process_data, - per_process_aux_data, variables, - includes, depth, check, False) - if not result: - return result - - (build_file_path, dependencies) = result - - # We can safely pop the build_file_data from per_process_data because it - # will never be referenced by this process again, so we don't need to keep - # it in the cache. - build_file_data = per_process_data.pop(build_file_path) - - # This gets serialized and sent back to the main process via a pipe. - # It's handled in LoadTargetBuildFileCallback. - return (build_file_path, - build_file_data, - dependencies) - except GypError, e: - sys.stderr.write("gyp: %s\n" % e) - return None - except Exception, e: - print >>sys.stderr, 'Exception:', e - print >>sys.stderr, traceback.format_exc() - return None - - -class ParallelProcessingError(Exception): - pass - - -class ParallelState(object): - """Class to keep track of state when processing input files in parallel. - - If build files are loaded in parallel, use this to keep track of - state during farming out and processing parallel jobs. It's stored - in a global so that the callback function can have access to it. - """ - - def __init__(self): - # The multiprocessing pool. - self.pool = None - # The condition variable used to protect this object and notify - # the main loop when there might be more data to process. - self.condition = None - # The "data" dict that was passed to LoadTargetBuildFileParallel - self.data = None - # The number of parallel calls outstanding; decremented when a response - # was received. - self.pending = 0 - # The set of all build files that have been scheduled, so we don't - # schedule the same one twice. - self.scheduled = set() - # A list of dependency build file paths that haven't been scheduled yet. - self.dependencies = [] - # Flag to indicate if there was an error in a child process. - self.error = False - - def LoadTargetBuildFileCallback(self, result): - """Handle the results of running LoadTargetBuildFile in another process. - """ - self.condition.acquire() - if not result: - self.error = True - self.condition.notify() - self.condition.release() - return - (build_file_path0, build_file_data0, dependencies0) = result - self.data[build_file_path0] = build_file_data0 - self.data['target_build_files'].add(build_file_path0) - for new_dependency in dependencies0: - if new_dependency not in self.scheduled: - self.scheduled.add(new_dependency) - self.dependencies.append(new_dependency) - self.pending -= 1 - self.condition.notify() - self.condition.release() - - -def LoadTargetBuildFilesParallel(build_files, data, variables, includes, depth, - check, generator_input_info): - parallel_state = ParallelState() - parallel_state.condition = threading.Condition() - # Make copies of the build_files argument that we can modify while working. - parallel_state.dependencies = list(build_files) - parallel_state.scheduled = set(build_files) - parallel_state.pending = 0 - parallel_state.data = data - - try: - parallel_state.condition.acquire() - while parallel_state.dependencies or parallel_state.pending: - if parallel_state.error: - break - if not parallel_state.dependencies: - parallel_state.condition.wait() - continue - - dependency = parallel_state.dependencies.pop() - - parallel_state.pending += 1 - global_flags = { - 'path_sections': globals()['path_sections'], - 'non_configuration_keys': globals()['non_configuration_keys'], - 'multiple_toolsets': globals()['multiple_toolsets']} - - if not parallel_state.pool: - parallel_state.pool = multiprocessing.Pool(multiprocessing.cpu_count()) - parallel_state.pool.apply_async( - CallLoadTargetBuildFile, - args = (global_flags, dependency, - variables, includes, depth, check, generator_input_info), - callback = parallel_state.LoadTargetBuildFileCallback) - except KeyboardInterrupt, e: - parallel_state.pool.terminate() - raise e - - parallel_state.condition.release() - - parallel_state.pool.close() - parallel_state.pool.join() - parallel_state.pool = None - - if parallel_state.error: - sys.exit(1) - -# Look for the bracket that matches the first bracket seen in a -# string, and return the start and end as a tuple. For example, if -# the input is something like "<(foo <(bar)) blah", then it would -# return (1, 13), indicating the entire string except for the leading -# "<" and trailing " blah". -LBRACKETS= set('{[(') -BRACKETS = {'}': '{', ']': '[', ')': '('} -def FindEnclosingBracketGroup(input_str): - stack = [] - start = -1 - for index, char in enumerate(input_str): - if char in LBRACKETS: - stack.append(char) - if start == -1: - start = index - elif char in BRACKETS: - if not stack: - return (-1, -1) - if stack.pop() != BRACKETS[char]: - return (-1, -1) - if not stack: - return (start, index + 1) - return (-1, -1) - - -def IsStrCanonicalInt(string): - """Returns True if |string| is in its canonical integer form. - - The canonical form is such that str(int(string)) == string. - """ - if type(string) is str: - # This function is called a lot so for maximum performance, avoid - # involving regexps which would otherwise make the code much - # shorter. Regexps would need twice the time of this function. - if string: - if string == "0": - return True - if string[0] == "-": - string = string[1:] - if not string: - return False - if '1' <= string[0] <= '9': - return string.isdigit() - - return False - - -# This matches things like "<(asdf)", "(?P<(?:(?:!?@?)|\|)?)' - r'(?P[-a-zA-Z0-9_.]+)?' - r'\((?P\s*\[?)' - r'(?P.*?)(\]?)\))') - -# This matches the same as early_variable_re, but with '>' instead of '<'. -late_variable_re = re.compile( - r'(?P(?P>(?:(?:!?@?)|\|)?)' - r'(?P[-a-zA-Z0-9_.]+)?' - r'\((?P\s*\[?)' - r'(?P.*?)(\]?)\))') - -# This matches the same as early_variable_re, but with '^' instead of '<'. -latelate_variable_re = re.compile( - r'(?P(?P[\^](?:(?:!?@?)|\|)?)' - r'(?P[-a-zA-Z0-9_.]+)?' - r'\((?P\s*\[?)' - r'(?P.*?)(\]?)\))') - -# Global cache of results from running commands so they don't have to be run -# more then once. -cached_command_results = {} - - -def FixupPlatformCommand(cmd): - if sys.platform == 'win32': - if type(cmd) is list: - cmd = [re.sub('^cat ', 'type ', cmd[0])] + cmd[1:] - else: - cmd = re.sub('^cat ', 'type ', cmd) - return cmd - - -PHASE_EARLY = 0 -PHASE_LATE = 1 -PHASE_LATELATE = 2 - - -def ExpandVariables(input, phase, variables, build_file): - # Look for the pattern that gets expanded into variables - if phase == PHASE_EARLY: - variable_re = early_variable_re - expansion_symbol = '<' - elif phase == PHASE_LATE: - variable_re = late_variable_re - expansion_symbol = '>' - elif phase == PHASE_LATELATE: - variable_re = latelate_variable_re - expansion_symbol = '^' - else: - assert False - - input_str = str(input) - if IsStrCanonicalInt(input_str): - return int(input_str) - - # Do a quick scan to determine if an expensive regex search is warranted. - if expansion_symbol not in input_str: - return input_str - - # Get the entire list of matches as a list of MatchObject instances. - # (using findall here would return strings instead of MatchObjects). - matches = list(variable_re.finditer(input_str)) - if not matches: - return input_str - - output = input_str - # Reverse the list of matches so that replacements are done right-to-left. - # That ensures that earlier replacements won't mess up the string in a - # way that causes later calls to find the earlier substituted text instead - # of what's intended for replacement. - matches.reverse() - for match_group in matches: - match = match_group.groupdict() - gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Matches: %r", match) - # match['replace'] is the substring to look for, match['type'] - # is the character code for the replacement type (< > ! <| >| <@ - # >@ !@), match['is_array'] contains a '[' for command - # arrays, and match['content'] is the name of the variable (< >) - # or command to run (!). match['command_string'] is an optional - # command string. Currently, only 'pymod_do_main' is supported. - - # run_command is true if a ! variant is used. - run_command = '!' in match['type'] - command_string = match['command_string'] - - # file_list is true if a | variant is used. - file_list = '|' in match['type'] - - # Capture these now so we can adjust them later. - replace_start = match_group.start('replace') - replace_end = match_group.end('replace') - - # Find the ending paren, and re-evaluate the contained string. - (c_start, c_end) = FindEnclosingBracketGroup(input_str[replace_start:]) - - # Adjust the replacement range to match the entire command - # found by FindEnclosingBracketGroup (since the variable_re - # probably doesn't match the entire command if it contained - # nested variables). - replace_end = replace_start + c_end - - # Find the "real" replacement, matching the appropriate closing - # paren, and adjust the replacement start and end. - replacement = input_str[replace_start:replace_end] - - # Figure out what the contents of the variable parens are. - contents_start = replace_start + c_start + 1 - contents_end = replace_end - 1 - contents = input_str[contents_start:contents_end] - - # Do filter substitution now for <|(). - # Admittedly, this is different than the evaluation order in other - # contexts. However, since filtration has no chance to run on <|(), - # this seems like the only obvious way to give them access to filters. - if file_list: - processed_variables = gyp.simple_copy.deepcopy(variables) - ProcessListFiltersInDict(contents, processed_variables) - # Recurse to expand variables in the contents - contents = ExpandVariables(contents, phase, - processed_variables, build_file) - else: - # Recurse to expand variables in the contents - contents = ExpandVariables(contents, phase, variables, build_file) - - # Strip off leading/trailing whitespace so that variable matches are - # simpler below (and because they are rarely needed). - contents = contents.strip() - - # expand_to_list is true if an @ variant is used. In that case, - # the expansion should result in a list. Note that the caller - # is to be expecting a list in return, and not all callers do - # because not all are working in list context. Also, for list - # expansions, there can be no other text besides the variable - # expansion in the input string. - expand_to_list = '@' in match['type'] and input_str == replacement - - if run_command or file_list: - # Find the build file's directory, so commands can be run or file lists - # generated relative to it. - build_file_dir = os.path.dirname(build_file) - if build_file_dir == '' and not file_list: - # If build_file is just a leaf filename indicating a file in the - # current directory, build_file_dir might be an empty string. Set - # it to None to signal to subprocess.Popen that it should run the - # command in the current directory. - build_file_dir = None - - # Support <|(listfile.txt ...) which generates a file - # containing items from a gyp list, generated at gyp time. - # This works around actions/rules which have more inputs than will - # fit on the command line. - if file_list: - if type(contents) is list: - contents_list = contents - else: - contents_list = contents.split(' ') - replacement = contents_list[0] - if os.path.isabs(replacement): - raise GypError('| cannot handle absolute paths, got "%s"' % replacement) - - if not generator_filelist_paths: - path = os.path.join(build_file_dir, replacement) - else: - if os.path.isabs(build_file_dir): - toplevel = generator_filelist_paths['toplevel'] - rel_build_file_dir = gyp.common.RelativePath(build_file_dir, toplevel) - else: - 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) - gyp.common.EnsureDirExists(path) - - replacement = gyp.common.RelativePath(path, build_file_dir) - f = gyp.common.WriteOnDiff(path) - for i in contents_list[1:]: - f.write('%s\n' % i) - f.close() - - elif run_command: - use_shell = True - if match['is_array']: - contents = eval(contents) - use_shell = False - - # Check for a cached value to avoid executing commands, or generating - # file lists more than once. The cache key contains the command to be - # run as well as the directory to run it from, to account for commands - # that depend on their current directory. - # TODO(http://code.google.com/p/gyp/issues/detail?id=111): In theory, - # someone could author a set of GYP files where each time the command - # is invoked it produces different output by design. When the need - # arises, the syntax should be extended to support no caching off a - # command's output so it is run every time. - cache_key = (str(contents), build_file_dir) - cached_value = cached_command_results.get(cache_key, None) - if cached_value is None: - gyp.DebugOutput(gyp.DEBUG_VARIABLES, - "Executing command '%s' in directory '%s'", - contents, build_file_dir) - - replacement = '' - - if command_string == 'pymod_do_main': - # (sources/) etc. to resolve to - # and empty list if undefined. This allows actions to: - # 'action!': [ - # '>@(_sources!)', - # ], - # 'action/': [ - # '>@(_sources/)', - # ], - replacement = [] - else: - raise GypError('Undefined variable ' + contents + - ' in ' + build_file) - else: - replacement = variables[contents] - - if type(replacement) is list: - for item in replacement: - if not contents[-1] == '/' and type(item) not in (str, int): - raise GypError('Variable ' + contents + - ' must expand to a string or list of strings; ' + - 'list contains a ' + - item.__class__.__name__) - # Run through the list and handle variable expansions in it. Since - # the list is guaranteed not to contain dicts, this won't do anything - # with conditions sections. - ProcessVariablesAndConditionsInList(replacement, phase, variables, - build_file) - elif type(replacement) not in (str, int): - raise GypError('Variable ' + contents + - ' must expand to a string or list of strings; ' + - 'found a ' + replacement.__class__.__name__) - - if expand_to_list: - # Expanding in list context. It's guaranteed that there's only one - # replacement to do in |input_str| and that it's this replacement. See - # above. - if type(replacement) is list: - # If it's already a list, make a copy. - output = replacement[:] - else: - # Split it the same way sh would split arguments. - output = shlex.split(str(replacement)) - else: - # Expanding in string context. - encoded_replacement = '' - if type(replacement) is list: - # When expanding a list into string context, turn the list items - # into a string in a way that will work with a subprocess call. - # - # TODO(mark): This isn't completely correct. This should - # call a generator-provided function that observes the - # proper list-to-argument quoting rules on a specific - # platform instead of just calling the POSIX encoding - # routine. - encoded_replacement = gyp.common.EncodePOSIXShellList(replacement) - else: - encoded_replacement = replacement - - output = output[:replace_start] + str(encoded_replacement) + \ - output[replace_end:] - # Prepare for the next match iteration. - input_str = output - - if output == input: - gyp.DebugOutput(gyp.DEBUG_VARIABLES, - "Found only identity matches on %r, avoiding infinite " - "recursion.", - output) - else: - # Look for more matches now that we've replaced some, to deal with - # expanding local variables (variables defined in the same - # variables block as this one). - gyp.DebugOutput(gyp.DEBUG_VARIABLES, "Found output %r, recursing.", output) - if type(output) is list: - if output and type(output[0]) is list: - # Leave output alone if it's a list of lists. - # We don't want such lists to be stringified. - pass - else: - new_output = [] - for item in output: - new_output.append( - ExpandVariables(item, phase, variables, build_file)) - output = new_output - else: - output = ExpandVariables(output, phase, variables, build_file) - - # Convert all strings that are canonically-represented integers into integers. - if type(output) is list: - for index in xrange(0, len(output)): - if IsStrCanonicalInt(output[index]): - output[index] = int(output[index]) - elif IsStrCanonicalInt(output): - output = int(output) - - return output - -# The same condition is often evaluated over and over again so it -# makes sense to cache as much as possible between evaluations. -cached_conditions_asts = {} - -def EvalCondition(condition, conditions_key, phase, variables, build_file): - """Returns the dict that should be used or None if the result was - that nothing should be used.""" - if type(condition) is not list: - raise GypError(conditions_key + ' must be a list') - if len(condition) < 2: - # It's possible that condition[0] won't work in which case this - # attempt will raise its own IndexError. That's probably fine. - raise GypError(conditions_key + ' ' + condition[0] + - ' must be at least length 2, not ' + str(len(condition))) - - i = 0 - result = None - while i < len(condition): - cond_expr = condition[i] - true_dict = condition[i + 1] - if type(true_dict) is not dict: - raise GypError('{} {} must be followed by a dictionary, not {}'.format( - conditions_key, cond_expr, type(true_dict))) - if len(condition) > i + 2 and type(condition[i + 2]) is dict: - false_dict = condition[i + 2] - i = i + 3 - if i != len(condition): - raise GypError('{} {} has {} unexpected trailing items'.format( - conditions_key, cond_expr, len(condition) - i)) - else: - false_dict = None - i = i + 2 - if result == None: - result = EvalSingleCondition( - cond_expr, true_dict, false_dict, phase, variables, build_file) - - return result - - -def EvalSingleCondition( - cond_expr, true_dict, false_dict, phase, variables, build_file): - """Returns true_dict if cond_expr evaluates to true, and false_dict - otherwise.""" - # Do expansions on the condition itself. Since the conditon can naturally - # contain variable references without needing to resort to GYP expansion - # syntax, this is of dubious value for variables, but someone might want to - # use a command expansion directly inside a condition. - cond_expr_expanded = ExpandVariables(cond_expr, phase, variables, - build_file) - if type(cond_expr_expanded) not in (str, int): - raise ValueError( - 'Variable expansion in this context permits str and int ' + \ - 'only, found ' + cond_expr_expanded.__class__.__name__) - - try: - if cond_expr_expanded in cached_conditions_asts: - ast_code = cached_conditions_asts[cond_expr_expanded] - else: - ast_code = compile(cond_expr_expanded, '', 'eval') - cached_conditions_asts[cond_expr_expanded] = ast_code - if eval(ast_code, {'__builtins__': None}, variables): - return true_dict - return false_dict - except SyntaxError, e: - syntax_error = SyntaxError('%s while evaluating condition \'%s\' in %s ' - 'at character %d.' % - (str(e.args[0]), e.text, build_file, e.offset), - e.filename, e.lineno, e.offset, e.text) - raise syntax_error - except NameError, e: - gyp.common.ExceptionAppend(e, 'while evaluating condition \'%s\' in %s' % - (cond_expr_expanded, build_file)) - raise GypError(e) - - -def ProcessConditionsInDict(the_dict, phase, variables, build_file): - # Process a 'conditions' or 'target_conditions' section in the_dict, - # depending on phase. - # early -> conditions - # late -> target_conditions - # latelate -> no conditions - # - # Each item in a conditions list consists of cond_expr, a string expression - # evaluated as the condition, and true_dict, a dict that will be merged into - # the_dict if cond_expr evaluates to true. Optionally, a third item, - # false_dict, may be present. false_dict is merged into the_dict if - # cond_expr evaluates to false. - # - # Any dict merged into the_dict will be recursively processed for nested - # conditionals and other expansions, also according to phase, immediately - # prior to being merged. - - if phase == PHASE_EARLY: - conditions_key = 'conditions' - elif phase == PHASE_LATE: - conditions_key = 'target_conditions' - elif phase == PHASE_LATELATE: - return - else: - assert False - - if not conditions_key in the_dict: - return - - conditions_list = the_dict[conditions_key] - # Unhook the conditions list, it's no longer needed. - del the_dict[conditions_key] - - for condition in conditions_list: - merge_dict = EvalCondition(condition, conditions_key, phase, variables, - build_file) - - if merge_dict != None: - # Expand variables and nested conditinals in the merge_dict before - # merging it. - ProcessVariablesAndConditionsInDict(merge_dict, phase, - variables, build_file) - - MergeDicts(the_dict, merge_dict, build_file, build_file) - - -def LoadAutomaticVariablesFromDict(variables, the_dict): - # Any keys with plain string values in the_dict become automatic variables. - # The variable name is the key name with a "_" character prepended. - for key, value in the_dict.iteritems(): - if type(value) in (str, int, list): - variables['_' + key] = value - - -def LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key): - # Any keys in the_dict's "variables" dict, if it has one, becomes a - # variable. The variable name is the key name in the "variables" dict. - # Variables that end with the % character are set only if they are unset in - # the variables dict. the_dict_key is the name of the key that accesses - # the_dict in the_dict's parent dict. If the_dict's parent is not a dict - # (it could be a list or it could be parentless because it is a root dict), - # the_dict_key will be None. - for key, value in the_dict.get('variables', {}).iteritems(): - if type(value) not in (str, int, list): - continue - - if key.endswith('%'): - variable_name = key[:-1] - if variable_name in variables: - # If the variable is already set, don't set it. - continue - if the_dict_key is 'variables' and variable_name in the_dict: - # If the variable is set without a % in the_dict, and the_dict is a - # variables dict (making |variables| a varaibles sub-dict of a - # variables dict), use the_dict's definition. - value = the_dict[variable_name] - else: - variable_name = key - - variables[variable_name] = value - - -def ProcessVariablesAndConditionsInDict(the_dict, phase, variables_in, - build_file, the_dict_key=None): - """Handle all variable and command expansion and conditional evaluation. - - This function is the public entry point for all variable expansions and - conditional evaluations. The variables_in dictionary will not be modified - by this function. - """ - - # Make a copy of the variables_in dict that can be modified during the - # loading of automatics and the loading of the variables dict. - variables = variables_in.copy() - LoadAutomaticVariablesFromDict(variables, the_dict) - - if 'variables' in the_dict: - # Make sure all the local variables are added to the variables - # list before we process them so that you can reference one - # variable from another. They will be fully expanded by recursion - # in ExpandVariables. - for key, value in the_dict['variables'].iteritems(): - variables[key] = value - - # Handle the associated variables dict first, so that any variable - # references within can be resolved prior to using them as variables. - # Pass a copy of the variables dict to avoid having it be tainted. - # Otherwise, it would have extra automatics added for everything that - # should just be an ordinary variable in this scope. - ProcessVariablesAndConditionsInDict(the_dict['variables'], phase, - variables, build_file, 'variables') - - LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key) - - for key, value in the_dict.iteritems(): - # Skip "variables", which was already processed if present. - if key != 'variables' and type(value) is str: - expanded = ExpandVariables(value, phase, variables, build_file) - if type(expanded) not in (str, int): - raise ValueError( - 'Variable expansion in this context permits str and int ' + \ - 'only, found ' + expanded.__class__.__name__ + ' for ' + key) - the_dict[key] = expanded - - # Variable expansion may have resulted in changes to automatics. Reload. - # TODO(mark): Optimization: only reload if no changes were made. - variables = variables_in.copy() - LoadAutomaticVariablesFromDict(variables, the_dict) - LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key) - - # Process conditions in this dict. This is done after variable expansion - # so that conditions may take advantage of expanded variables. For example, - # if the_dict contains: - # {'type': '<(library_type)', - # 'conditions': [['_type=="static_library"', { ... }]]}, - # _type, as used in the condition, will only be set to the value of - # library_type if variable expansion is performed before condition - # processing. However, condition processing should occur prior to recursion - # so that variables (both automatic and "variables" dict type) may be - # adjusted by conditions sections, merged into the_dict, and have the - # intended impact on contained dicts. - # - # This arrangement means that a "conditions" section containing a "variables" - # section will only have those variables effective in subdicts, not in - # the_dict. The workaround is to put a "conditions" section within a - # "variables" section. For example: - # {'conditions': [['os=="mac"', {'variables': {'define': 'IS_MAC'}}]], - # 'defines': ['<(define)'], - # 'my_subdict': {'defines': ['<(define)']}}, - # will not result in "IS_MAC" being appended to the "defines" list in the - # current scope but would result in it being appended to the "defines" list - # within "my_subdict". By comparison: - # {'variables': {'conditions': [['os=="mac"', {'define': 'IS_MAC'}]]}, - # 'defines': ['<(define)'], - # 'my_subdict': {'defines': ['<(define)']}}, - # will append "IS_MAC" to both "defines" lists. - - # Evaluate conditions sections, allowing variable expansions within them - # as well as nested conditionals. This will process a 'conditions' or - # 'target_conditions' section, perform appropriate merging and recursive - # conditional and variable processing, and then remove the conditions section - # from the_dict if it is present. - ProcessConditionsInDict(the_dict, phase, variables, build_file) - - # Conditional processing may have resulted in changes to automatics or the - # variables dict. Reload. - variables = variables_in.copy() - LoadAutomaticVariablesFromDict(variables, the_dict) - LoadVariablesFromVariablesDict(variables, the_dict, the_dict_key) - - # Recurse into child dicts, or process child lists which may result in - # further recursion into descendant dicts. - for key, value in the_dict.iteritems(): - # Skip "variables" and string values, which were already processed if - # present. - if key == 'variables' or type(value) is str: - continue - if type(value) is dict: - # Pass a copy of the variables dict so that subdicts can't influence - # parents. - ProcessVariablesAndConditionsInDict(value, phase, variables, - build_file, key) - elif type(value) is list: - # The list itself can't influence the variables dict, and - # ProcessVariablesAndConditionsInList will make copies of the variables - # dict if it needs to pass it to something that can influence it. No - # copy is necessary here. - ProcessVariablesAndConditionsInList(value, phase, variables, - build_file) - elif type(value) is not int: - raise TypeError('Unknown type ' + value.__class__.__name__ + \ - ' for ' + key) - - -def ProcessVariablesAndConditionsInList(the_list, phase, variables, - build_file): - # Iterate using an index so that new values can be assigned into the_list. - index = 0 - while index < len(the_list): - item = the_list[index] - if type(item) is dict: - # Make a copy of the variables dict so that it won't influence anything - # outside of its own scope. - ProcessVariablesAndConditionsInDict(item, phase, variables, build_file) - elif type(item) is list: - ProcessVariablesAndConditionsInList(item, phase, variables, build_file) - elif type(item) is str: - expanded = ExpandVariables(item, phase, variables, build_file) - if type(expanded) in (str, int): - the_list[index] = expanded - elif type(expanded) is list: - the_list[index:index+1] = expanded - index += len(expanded) - - # index now identifies the next item to examine. Continue right now - # without falling into the index increment below. - continue - else: - raise ValueError( - 'Variable expansion in this context permits strings and ' + \ - 'lists only, found ' + expanded.__class__.__name__ + ' at ' + \ - index) - elif type(item) is not int: - raise TypeError('Unknown type ' + item.__class__.__name__ + \ - ' at index ' + index) - index = index + 1 - - -def BuildTargetsDict(data): - """Builds a dict mapping fully-qualified target names to their target dicts. - - |data| is a dict mapping loaded build files by pathname relative to the - current directory. Values in |data| are build file contents. For each - |data| value with a "targets" key, the value of the "targets" key is taken - as a list containing target dicts. Each target's fully-qualified name is - constructed from the pathname of the build file (|data| key) and its - "target_name" property. These fully-qualified names are used as the keys - in the returned dict. These keys provide access to the target dicts, - the dicts in the "targets" lists. - """ - - targets = {} - for build_file in data['target_build_files']: - for target in data[build_file].get('targets', []): - target_name = gyp.common.QualifiedTarget(build_file, - target['target_name'], - target['toolset']) - if target_name in targets: - raise GypError('Duplicate target definitions for ' + target_name) - targets[target_name] = target - - return targets - - -def QualifyDependencies(targets): - """Make dependency links fully-qualified relative to the current directory. - - |targets| is a dict mapping fully-qualified target names to their target - dicts. For each target in this dict, keys known to contain dependency - links are examined, and any dependencies referenced will be rewritten - so that they are fully-qualified and relative to the current directory. - All rewritten dependencies are suitable for use as keys to |targets| or a - similar dict. - """ - - all_dependency_sections = [dep + op - for dep in dependency_sections - for op in ('', '!', '/')] - - for target, target_dict in targets.iteritems(): - target_build_file = gyp.common.BuildFile(target) - toolset = target_dict['toolset'] - for dependency_key in all_dependency_sections: - dependencies = target_dict.get(dependency_key, []) - for index in xrange(0, len(dependencies)): - dep_file, dep_target, dep_toolset = gyp.common.ResolveTarget( - target_build_file, dependencies[index], toolset) - if not multiple_toolsets: - # Ignore toolset specification in the dependency if it is specified. - dep_toolset = toolset - dependency = gyp.common.QualifiedTarget(dep_file, - dep_target, - dep_toolset) - dependencies[index] = dependency - - # Make sure anything appearing in a list other than "dependencies" also - # appears in the "dependencies" list. - if dependency_key != 'dependencies' and \ - dependency not in target_dict['dependencies']: - raise GypError('Found ' + dependency + ' in ' + dependency_key + - ' of ' + target + ', but not in dependencies') - - -def ExpandWildcardDependencies(targets, data): - """Expands dependencies specified as build_file:*. - - For each target in |targets|, examines sections containing links to other - targets. If any such section contains a link of the form build_file:*, it - is taken as a wildcard link, and is expanded to list each target in - build_file. The |data| dict provides access to build file dicts. - - Any target that does not wish to be included by wildcard can provide an - optional "suppress_wildcard" key in its target dict. When present and - true, a wildcard dependency link will not include such targets. - - All dependency names, including the keys to |targets| and the values in each - dependency list, must be qualified when this function is called. - """ - - for target, target_dict in targets.iteritems(): - toolset = target_dict['toolset'] - target_build_file = gyp.common.BuildFile(target) - for dependency_key in dependency_sections: - dependencies = target_dict.get(dependency_key, []) - - # Loop this way instead of "for dependency in" or "for index in xrange" - # because the dependencies list will be modified within the loop body. - index = 0 - while index < len(dependencies): - (dependency_build_file, dependency_target, dependency_toolset) = \ - gyp.common.ParseQualifiedTarget(dependencies[index]) - if dependency_target != '*' and dependency_toolset != '*': - # Not a wildcard. Keep it moving. - index = index + 1 - continue - - if dependency_build_file == target_build_file: - # It's an error for a target to depend on all other targets in - # the same file, because a target cannot depend on itself. - raise GypError('Found wildcard in ' + dependency_key + ' of ' + - target + ' referring to same build file') - - # Take the wildcard out and adjust the index so that the next - # dependency in the list will be processed the next time through the - # loop. - del dependencies[index] - index = index - 1 - - # Loop through the targets in the other build file, adding them to - # this target's list of dependencies in place of the removed - # wildcard. - dependency_target_dicts = data[dependency_build_file]['targets'] - for dependency_target_dict in dependency_target_dicts: - if int(dependency_target_dict.get('suppress_wildcard', False)): - continue - dependency_target_name = dependency_target_dict['target_name'] - if (dependency_target != '*' and - dependency_target != dependency_target_name): - continue - dependency_target_toolset = dependency_target_dict['toolset'] - if (dependency_toolset != '*' and - dependency_toolset != dependency_target_toolset): - continue - dependency = gyp.common.QualifiedTarget(dependency_build_file, - dependency_target_name, - dependency_target_toolset) - index = index + 1 - dependencies.insert(index, dependency) - - index = index + 1 - - -def Unify(l): - """Removes duplicate elements from l, keeping the first element.""" - seen = {} - return [seen.setdefault(e, e) for e in l if e not in seen] - - -def RemoveDuplicateDependencies(targets): - """Makes sure every dependency appears only once in all targets's dependency - lists.""" - for target_name, target_dict in targets.iteritems(): - for dependency_key in dependency_sections: - dependencies = target_dict.get(dependency_key, []) - if dependencies: - target_dict[dependency_key] = Unify(dependencies) - - -def Filter(l, item): - """Removes item from l.""" - res = {} - return [res.setdefault(e, e) for e in l if e != item] - - -def RemoveSelfDependencies(targets): - """Remove self dependencies from targets that have the prune_self_dependency - variable set.""" - for target_name, target_dict in targets.iteritems(): - for dependency_key in dependency_sections: - dependencies = target_dict.get(dependency_key, []) - if dependencies: - for t in dependencies: - if t == target_name: - if targets[t].get('variables', {}).get('prune_self_dependency', 0): - target_dict[dependency_key] = Filter(dependencies, target_name) - - -def RemoveLinkDependenciesFromNoneTargets(targets): - """Remove dependencies having the 'link_dependency' attribute from the 'none' - targets.""" - for target_name, target_dict in targets.iteritems(): - for dependency_key in dependency_sections: - dependencies = target_dict.get(dependency_key, []) - if dependencies: - for t in dependencies: - if target_dict.get('type', None) == 'none': - if targets[t].get('variables', {}).get('link_dependency', 0): - target_dict[dependency_key] = \ - Filter(target_dict[dependency_key], t) - - -class DependencyGraphNode(object): - """ - - Attributes: - ref: A reference to an object that this DependencyGraphNode represents. - dependencies: List of DependencyGraphNodes on which this one depends. - dependents: List of DependencyGraphNodes that depend on this one. - """ - - class CircularException(GypError): - pass - - def __init__(self, ref): - self.ref = ref - self.dependencies = [] - self.dependents = [] - - def __repr__(self): - return '' % self.ref - - def FlattenToList(self): - # flat_list is the sorted list of dependencies - actually, the list items - # are the "ref" attributes of DependencyGraphNodes. Every target will - # appear in flat_list after all of its dependencies, and before all of its - # dependents. - flat_list = OrderedSet() - - # in_degree_zeros is the list of DependencyGraphNodes that have no - # dependencies not in flat_list. Initially, it is a copy of the children - # of this node, because when the graph was built, nodes with no - # dependencies were made implicit dependents of the root node. - in_degree_zeros = set(self.dependents[:]) - - while in_degree_zeros: - # Nodes in in_degree_zeros have no dependencies not in flat_list, so they - # can be appended to flat_list. Take these nodes out of in_degree_zeros - # as work progresses, so that the next node to process from the list can - # always be accessed at a consistent position. - node = in_degree_zeros.pop() - flat_list.add(node.ref) - - # Look at dependents of the node just added to flat_list. Some of them - # may now belong in in_degree_zeros. - for node_dependent in node.dependents: - is_in_degree_zero = True - # TODO: We want to check through the - # node_dependent.dependencies list but if it's long and we - # always start at the beginning, then we get O(n^2) behaviour. - for node_dependent_dependency in node_dependent.dependencies: - if not node_dependent_dependency.ref in flat_list: - # The dependent one or more dependencies not in flat_list. There - # will be more chances to add it to flat_list when examining - # it again as a dependent of those other dependencies, provided - # that there are no cycles. - is_in_degree_zero = False - break - - if is_in_degree_zero: - # All of the dependent's dependencies are already in flat_list. Add - # it to in_degree_zeros where it will be processed in a future - # iteration of the outer loop. - in_degree_zeros.add(node_dependent) - - return list(flat_list) - - def FindCycles(self): - """ - Returns a list of cycles in the graph, where each cycle is its own list. - """ - results = [] - visited = set() - - def Visit(node, path): - for child in node.dependents: - if child in path: - results.append([child] + path[:path.index(child) + 1]) - elif not child in visited: - visited.add(child) - Visit(child, [child] + path) - - visited.add(self) - Visit(self, [self]) - - return results - - def DirectDependencies(self, dependencies=None): - """Returns a list of just direct dependencies.""" - if dependencies == None: - dependencies = [] - - for dependency in self.dependencies: - # Check for None, corresponding to the root node. - if dependency.ref != None and dependency.ref not in dependencies: - dependencies.append(dependency.ref) - - return dependencies - - def _AddImportedDependencies(self, targets, dependencies=None): - """Given a list of direct dependencies, adds indirect dependencies that - other dependencies have declared to export their settings. - - This method does not operate on self. Rather, it operates on the list - of dependencies in the |dependencies| argument. For each dependency in - that list, if any declares that it exports the settings of one of its - own dependencies, those dependencies whose settings are "passed through" - are added to the list. As new items are added to the list, they too will - be processed, so it is possible to import settings through multiple levels - of dependencies. - - This method is not terribly useful on its own, it depends on being - "primed" with a list of direct dependencies such as one provided by - DirectDependencies. DirectAndImportedDependencies is intended to be the - public entry point. - """ - - if dependencies == None: - dependencies = [] - - index = 0 - while index < len(dependencies): - dependency = dependencies[index] - dependency_dict = targets[dependency] - # Add any dependencies whose settings should be imported to the list - # if not already present. Newly-added items will be checked for - # their own imports when the list iteration reaches them. - # Rather than simply appending new items, insert them after the - # dependency that exported them. This is done to more closely match - # the depth-first method used by DeepDependencies. - add_index = 1 - for imported_dependency in \ - dependency_dict.get('export_dependent_settings', []): - if imported_dependency not in dependencies: - dependencies.insert(index + add_index, imported_dependency) - add_index = add_index + 1 - index = index + 1 - - return dependencies - - def DirectAndImportedDependencies(self, targets, dependencies=None): - """Returns a list of a target's direct dependencies and all indirect - dependencies that a dependency has advertised settings should be exported - through the dependency for. - """ - - dependencies = self.DirectDependencies(dependencies) - return self._AddImportedDependencies(targets, dependencies) - - def DeepDependencies(self, dependencies=None): - """Returns an OrderedSet of all of a target's dependencies, recursively.""" - if dependencies is None: - # Using a list to get ordered output and a set to do fast "is it - # already added" checks. - dependencies = OrderedSet() - - for dependency in self.dependencies: - # Check for None, corresponding to the root node. - if dependency.ref is None: - continue - if dependency.ref not in dependencies: - dependency.DeepDependencies(dependencies) - dependencies.add(dependency.ref) - - return dependencies - - def _LinkDependenciesInternal(self, targets, include_shared_libraries, - dependencies=None, initial=True): - """Returns an OrderedSet of dependency targets that are linked - into this target. - - This function has a split personality, depending on the setting of - |initial|. Outside callers should always leave |initial| at its default - setting. - - When adding a target to the list of dependencies, this function will - recurse into itself with |initial| set to False, to collect dependencies - that are linked into the linkable target for which the list is being built. - - If |include_shared_libraries| is False, the resulting dependencies will not - include shared_library targets that are linked into this target. - """ - if dependencies is None: - # Using a list to get ordered output and a set to do fast "is it - # already added" checks. - dependencies = OrderedSet() - - # Check for None, corresponding to the root node. - if self.ref is None: - return dependencies - - # It's kind of sucky that |targets| has to be passed into this function, - # but that's presently the easiest way to access the target dicts so that - # this function can find target types. - - if 'target_name' not in targets[self.ref]: - raise GypError("Missing 'target_name' field in target.") - - if 'type' not in targets[self.ref]: - raise GypError("Missing 'type' field in target %s" % - targets[self.ref]['target_name']) - - target_type = targets[self.ref]['type'] - - is_linkable = target_type in linkable_types - - if initial and not is_linkable: - # If this is the first target being examined and it's not linkable, - # return an empty list of link dependencies, because the link - # dependencies are intended to apply to the target itself (initial is - # True) and this target won't be linked. - return dependencies - - # Don't traverse 'none' targets if explicitly excluded. - if (target_type == 'none' and - not targets[self.ref].get('dependencies_traverse', True)): - dependencies.add(self.ref) - return dependencies - - # Executables, mac kernel extensions and loadable modules are already fully - # and finally linked. Nothing else can be a link dependency of them, there - # can only be dependencies in the sense that a dependent target might run - # an executable or load the loadable_module. - if not initial and target_type in ('executable', 'loadable_module', - 'mac_kernel_extension'): - return dependencies - - # Shared libraries are already fully linked. They should only be included - # in |dependencies| when adjusting static library dependencies (in order to - # link against the shared_library's import lib), but should not be included - # in |dependencies| when propagating link_settings. - # The |include_shared_libraries| flag controls which of these two cases we - # are handling. - if (not initial and target_type == 'shared_library' and - not include_shared_libraries): - return dependencies - - # The target is linkable, add it to the list of link dependencies. - if self.ref not in dependencies: - dependencies.add(self.ref) - if initial or not is_linkable: - # If this is a subsequent target and it's linkable, don't look any - # further for linkable dependencies, as they'll already be linked into - # this target linkable. Always look at dependencies of the initial - # target, and always look at dependencies of non-linkables. - for dependency in self.dependencies: - dependency._LinkDependenciesInternal(targets, - include_shared_libraries, - dependencies, False) - - return dependencies - - def DependenciesForLinkSettings(self, targets): - """ - Returns a list of dependency targets whose link_settings should be merged - into this target. - """ - - # TODO(sbaig) Currently, chrome depends on the bug that shared libraries' - # link_settings are propagated. So for now, we will allow it, unless the - # 'allow_sharedlib_linksettings_propagation' flag is explicitly set to - # False. Once chrome is fixed, we can remove this flag. - include_shared_libraries = \ - targets[self.ref].get('allow_sharedlib_linksettings_propagation', True) - return self._LinkDependenciesInternal(targets, include_shared_libraries) - - def DependenciesToLinkAgainst(self, targets): - """ - Returns a list of dependency targets that are linked into this target. - """ - return self._LinkDependenciesInternal(targets, True) - - -def BuildDependencyList(targets): - # Create a DependencyGraphNode for each target. Put it into a dict for easy - # access. - dependency_nodes = {} - for target, spec in targets.iteritems(): - if target not in dependency_nodes: - dependency_nodes[target] = DependencyGraphNode(target) - - # Set up the dependency links. Targets that have no dependencies are treated - # as dependent on root_node. - root_node = DependencyGraphNode(None) - for target, spec in targets.iteritems(): - target_node = dependency_nodes[target] - target_build_file = gyp.common.BuildFile(target) - dependencies = spec.get('dependencies') - if not dependencies: - target_node.dependencies = [root_node] - root_node.dependents.append(target_node) - else: - for dependency in dependencies: - dependency_node = dependency_nodes.get(dependency) - if not dependency_node: - raise GypError("Dependency '%s' not found while " - "trying to load target %s" % (dependency, target)) - target_node.dependencies.append(dependency_node) - dependency_node.dependents.append(target_node) - - flat_list = root_node.FlattenToList() - - # If there's anything left unvisited, there must be a circular dependency - # (cycle). - if len(flat_list) != len(targets): - if not root_node.dependents: - # If all targets have dependencies, add the first target as a dependent - # of root_node so that the cycle can be discovered from root_node. - target = targets.keys()[0] - target_node = dependency_nodes[target] - target_node.dependencies.append(root_node) - root_node.dependents.append(target_node) - - cycles = [] - for cycle in root_node.FindCycles(): - paths = [node.ref for node in cycle] - cycles.append('Cycle: %s' % ' -> '.join(paths)) - raise DependencyGraphNode.CircularException( - 'Cycles in dependency graph detected:\n' + '\n'.join(cycles)) - - return [dependency_nodes, flat_list] - - -def VerifyNoGYPFileCircularDependencies(targets): - # Create a DependencyGraphNode for each gyp file containing a target. Put - # it into a dict for easy access. - dependency_nodes = {} - for target in targets.iterkeys(): - build_file = gyp.common.BuildFile(target) - if not build_file in dependency_nodes: - dependency_nodes[build_file] = DependencyGraphNode(build_file) - - # Set up the dependency links. - for target, spec in targets.iteritems(): - build_file = gyp.common.BuildFile(target) - build_file_node = dependency_nodes[build_file] - target_dependencies = spec.get('dependencies', []) - for dependency in target_dependencies: - try: - dependency_build_file = gyp.common.BuildFile(dependency) - except GypError, e: - gyp.common.ExceptionAppend( - e, 'while computing dependencies of .gyp file %s' % build_file) - raise - - if dependency_build_file == build_file: - # A .gyp file is allowed to refer back to itself. - continue - dependency_node = dependency_nodes.get(dependency_build_file) - if not dependency_node: - raise GypError("Dependancy '%s' not found" % dependency_build_file) - if dependency_node not in build_file_node.dependencies: - build_file_node.dependencies.append(dependency_node) - dependency_node.dependents.append(build_file_node) - - - # Files that have no dependencies are treated as dependent on root_node. - root_node = DependencyGraphNode(None) - for build_file_node in dependency_nodes.itervalues(): - if len(build_file_node.dependencies) == 0: - build_file_node.dependencies.append(root_node) - root_node.dependents.append(build_file_node) - - flat_list = root_node.FlattenToList() - - # If there's anything left unvisited, there must be a circular dependency - # (cycle). - if len(flat_list) != len(dependency_nodes): - if not root_node.dependents: - # If all files have dependencies, add the first file as a dependent - # of root_node so that the cycle can be discovered from root_node. - file_node = dependency_nodes.values()[0] - file_node.dependencies.append(root_node) - root_node.dependents.append(file_node) - cycles = [] - for cycle in root_node.FindCycles(): - paths = [node.ref for node in cycle] - cycles.append('Cycle: %s' % ' -> '.join(paths)) - raise DependencyGraphNode.CircularException( - 'Cycles in .gyp file dependency graph detected:\n' + '\n'.join(cycles)) - - -def DoDependentSettings(key, flat_list, targets, dependency_nodes): - # key should be one of all_dependent_settings, direct_dependent_settings, - # or link_settings. - - for target in flat_list: - target_dict = targets[target] - build_file = gyp.common.BuildFile(target) - - if key == 'all_dependent_settings': - dependencies = dependency_nodes[target].DeepDependencies() - elif key == 'direct_dependent_settings': - dependencies = \ - dependency_nodes[target].DirectAndImportedDependencies(targets) - elif key == 'link_settings': - dependencies = \ - dependency_nodes[target].DependenciesForLinkSettings(targets) - else: - raise GypError("DoDependentSettings doesn't know how to determine " - 'dependencies for ' + key) - - for dependency in dependencies: - dependency_dict = targets[dependency] - if not key in dependency_dict: - continue - dependency_build_file = gyp.common.BuildFile(dependency) - MergeDicts(target_dict, dependency_dict[key], - build_file, dependency_build_file) - - -def AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, - sort_dependencies): - # Recompute target "dependencies" properties. For each static library - # target, remove "dependencies" entries referring to other static libraries, - # unless the dependency has the "hard_dependency" attribute set. For each - # linkable target, add a "dependencies" entry referring to all of the - # target's computed list of link dependencies (including static libraries - # if no such entry is already present. - for target in flat_list: - target_dict = targets[target] - target_type = target_dict['type'] - - if target_type == 'static_library': - if not 'dependencies' in target_dict: - continue - - target_dict['dependencies_original'] = target_dict.get( - 'dependencies', [])[:] - - # A static library should not depend on another static library unless - # the dependency relationship is "hard," which should only be done when - # a dependent relies on some side effect other than just the build - # product, like a rule or action output. Further, if a target has a - # non-hard dependency, but that dependency exports a hard dependency, - # the non-hard dependency can safely be removed, but the exported hard - # dependency must be added to the target to keep the same dependency - # ordering. - dependencies = \ - dependency_nodes[target].DirectAndImportedDependencies(targets) - index = 0 - while index < len(dependencies): - dependency = dependencies[index] - dependency_dict = targets[dependency] - - # Remove every non-hard static library dependency and remove every - # non-static library dependency that isn't a direct dependency. - if (dependency_dict['type'] == 'static_library' and \ - not dependency_dict.get('hard_dependency', False)) or \ - (dependency_dict['type'] != 'static_library' and \ - not dependency in target_dict['dependencies']): - # Take the dependency out of the list, and don't increment index - # because the next dependency to analyze will shift into the index - # formerly occupied by the one being removed. - del dependencies[index] - else: - index = index + 1 - - # Update the dependencies. If the dependencies list is empty, it's not - # needed, so unhook it. - if len(dependencies) > 0: - target_dict['dependencies'] = dependencies - else: - del target_dict['dependencies'] - - elif target_type in linkable_types: - # Get a list of dependency targets that should be linked into this - # target. Add them to the dependencies list if they're not already - # present. - - link_dependencies = \ - dependency_nodes[target].DependenciesToLinkAgainst(targets) - for dependency in link_dependencies: - if dependency == target: - continue - if not 'dependencies' in target_dict: - target_dict['dependencies'] = [] - if not dependency in target_dict['dependencies']: - target_dict['dependencies'].append(dependency) - # Sort the dependencies list in the order from dependents to dependencies. - # e.g. If A and B depend on C and C depends on D, sort them in A, B, C, D. - # Note: flat_list is already sorted in the order from dependencies to - # dependents. - if sort_dependencies and 'dependencies' in target_dict: - target_dict['dependencies'] = [dep for dep in reversed(flat_list) - if dep in target_dict['dependencies']] - - -# Initialize this here to speed up MakePathRelative. -exception_re = re.compile(r'''["']?[-/$<>^]''') - - -def MakePathRelative(to_file, fro_file, item): - # If item is a relative path, it's relative to the build file dict that it's - # coming from. Fix it up to make it relative to the build file dict that - # it's going into. - # Exception: any |item| that begins with these special characters is - # returned without modification. - # / Used when a path is already absolute (shortcut optimization; - # such paths would be returned as absolute anyway) - # $ Used for build environment variables - # - Used for some build environment flags (such as -lapr-1 in a - # "libraries" section) - # < Used for our own variable and command expansions (see ExpandVariables) - # > Used for our own variable and command expansions (see ExpandVariables) - # ^ Used for our own variable and command expansions (see ExpandVariables) - # - # "/' Used when a value is quoted. If these are present, then we - # check the second character instead. - # - if to_file == fro_file or exception_re.match(item): - return item - else: - # TODO(dglazkov) The backslash/forward-slash replacement at the end is a - # temporary measure. This should really be addressed by keeping all paths - # in POSIX until actual project generation. - ret = os.path.normpath(os.path.join( - gyp.common.RelativePath(os.path.dirname(fro_file), - os.path.dirname(to_file)), - item)).replace('\\', '/') - if item[-1:] == '/': - ret += '/' - return ret - -def MergeLists(to, fro, to_file, fro_file, is_paths=False, append=True): - # Python documentation recommends objects which do not support hash - # set this value to None. Python library objects follow this rule. - is_hashable = lambda val: val.__hash__ - - # If x is hashable, returns whether x is in s. Else returns whether x is in l. - def is_in_set_or_list(x, s, l): - if is_hashable(x): - return x in s - return x in l - - prepend_index = 0 - - # Make membership testing of hashables in |to| (in particular, strings) - # faster. - hashable_to_set = set(x for x in to if is_hashable(x)) - for item in fro: - singleton = False - if type(item) in (str, int): - # The cheap and easy case. - if is_paths: - to_item = MakePathRelative(to_file, fro_file, item) - else: - to_item = item - - if not (type(item) is str and item.startswith('-')): - # Any string that doesn't begin with a "-" is a singleton - it can - # only appear once in a list, to be enforced by the list merge append - # or prepend. - singleton = True - elif type(item) is dict: - # Make a copy of the dictionary, continuing to look for paths to fix. - # The other intelligent aspects of merge processing won't apply because - # item is being merged into an empty dict. - to_item = {} - MergeDicts(to_item, item, to_file, fro_file) - elif type(item) is list: - # Recurse, making a copy of the list. If the list contains any - # descendant dicts, path fixing will occur. Note that here, custom - # values for is_paths and append are dropped; those are only to be - # applied to |to| and |fro|, not sublists of |fro|. append shouldn't - # matter anyway because the new |to_item| list is empty. - to_item = [] - MergeLists(to_item, item, to_file, fro_file) - else: - raise TypeError( - 'Attempt to merge list item of unsupported type ' + \ - item.__class__.__name__) - - if append: - # If appending a singleton that's already in the list, don't append. - # This ensures that the earliest occurrence of the item will stay put. - if not singleton or not is_in_set_or_list(to_item, hashable_to_set, to): - to.append(to_item) - if is_hashable(to_item): - hashable_to_set.add(to_item) - else: - # If prepending a singleton that's already in the list, remove the - # existing instance and proceed with the prepend. This ensures that the - # item appears at the earliest possible position in the list. - while singleton and to_item in to: - to.remove(to_item) - - # Don't just insert everything at index 0. That would prepend the new - # items to the list in reverse order, which would be an unwelcome - # surprise. - to.insert(prepend_index, to_item) - if is_hashable(to_item): - hashable_to_set.add(to_item) - prepend_index = prepend_index + 1 - - -def MergeDicts(to, fro, to_file, fro_file): - # I wanted to name the parameter "from" but it's a Python keyword... - for k, v in fro.iteritems(): - # It would be nice to do "if not k in to: to[k] = v" but that wouldn't give - # copy semantics. Something else may want to merge from the |fro| dict - # later, and having the same dict ref pointed to twice in the tree isn't - # what anyone wants considering that the dicts may subsequently be - # modified. - if k in to: - bad_merge = False - if type(v) in (str, int): - if type(to[k]) not in (str, int): - bad_merge = True - elif type(v) is not type(to[k]): - bad_merge = True - - if bad_merge: - raise TypeError( - 'Attempt to merge dict value of type ' + v.__class__.__name__ + \ - ' into incompatible type ' + to[k].__class__.__name__ + \ - ' for key ' + k) - if type(v) in (str, int): - # Overwrite the existing value, if any. Cheap and easy. - is_path = IsPathSection(k) - if is_path: - to[k] = MakePathRelative(to_file, fro_file, v) - else: - to[k] = v - elif type(v) is dict: - # Recurse, guaranteeing copies will be made of objects that require it. - if not k in to: - to[k] = {} - MergeDicts(to[k], v, to_file, fro_file) - elif type(v) is list: - # Lists in dicts can be merged with different policies, depending on - # how the key in the "from" dict (k, the from-key) is written. - # - # If the from-key has ...the to-list will have this action - # this character appended:... applied when receiving the from-list: - # = replace - # + prepend - # ? set, only if to-list does not yet exist - # (none) append - # - # This logic is list-specific, but since it relies on the associated - # dict key, it's checked in this dict-oriented function. - ext = k[-1] - append = True - if ext == '=': - list_base = k[:-1] - lists_incompatible = [list_base, list_base + '?'] - to[list_base] = [] - elif ext == '+': - list_base = k[:-1] - lists_incompatible = [list_base + '=', list_base + '?'] - append = False - elif ext == '?': - list_base = k[:-1] - lists_incompatible = [list_base, list_base + '=', list_base + '+'] - else: - list_base = k - lists_incompatible = [list_base + '=', list_base + '?'] - - # Some combinations of merge policies appearing together are meaningless. - # It's stupid to replace and append simultaneously, for example. Append - # and prepend are the only policies that can coexist. - for list_incompatible in lists_incompatible: - if list_incompatible in fro: - raise GypError('Incompatible list policies ' + k + ' and ' + - list_incompatible) - - if list_base in to: - if ext == '?': - # If the key ends in "?", the list will only be merged if it doesn't - # already exist. - continue - elif type(to[list_base]) is not list: - # This may not have been checked above if merging in a list with an - # extension character. - raise TypeError( - 'Attempt to merge dict value of type ' + v.__class__.__name__ + \ - ' into incompatible type ' + to[list_base].__class__.__name__ + \ - ' for key ' + list_base + '(' + k + ')') - else: - to[list_base] = [] - - # Call MergeLists, which will make copies of objects that require it. - # MergeLists can recurse back into MergeDicts, although this will be - # to make copies of dicts (with paths fixed), there will be no - # subsequent dict "merging" once entering a list because lists are - # always replaced, appended to, or prepended to. - is_paths = IsPathSection(list_base) - MergeLists(to[list_base], v, to_file, fro_file, is_paths, append) - else: - raise TypeError( - 'Attempt to merge dict value of unsupported type ' + \ - v.__class__.__name__ + ' for key ' + k) - - -def MergeConfigWithInheritance(new_configuration_dict, build_file, - target_dict, configuration, visited): - # Skip if previously visted. - if configuration in visited: - return - - # Look at this configuration. - configuration_dict = target_dict['configurations'][configuration] - - # Merge in parents. - for parent in configuration_dict.get('inherit_from', []): - MergeConfigWithInheritance(new_configuration_dict, build_file, - target_dict, parent, visited + [configuration]) - - # Merge it into the new config. - MergeDicts(new_configuration_dict, configuration_dict, - build_file, build_file) - - # Drop abstract. - if 'abstract' in new_configuration_dict: - del new_configuration_dict['abstract'] - - -def SetUpConfigurations(target, target_dict): - # key_suffixes is a list of key suffixes that might appear on key names. - # These suffixes are handled in conditional evaluations (for =, +, and ?) - # and rules/exclude processing (for ! and /). Keys with these suffixes - # should be treated the same as keys without. - key_suffixes = ['=', '+', '?', '!', '/'] - - build_file = gyp.common.BuildFile(target) - - # Provide a single configuration by default if none exists. - # TODO(mark): Signal an error if default_configurations exists but - # configurations does not. - if not 'configurations' in target_dict: - target_dict['configurations'] = {'Default': {}} - if not 'default_configuration' in target_dict: - concrete = [i for (i, config) in target_dict['configurations'].iteritems() - if not config.get('abstract')] - target_dict['default_configuration'] = sorted(concrete)[0] - - merged_configurations = {} - configs = target_dict['configurations'] - for (configuration, old_configuration_dict) in configs.iteritems(): - # Skip abstract configurations (saves work only). - if old_configuration_dict.get('abstract'): - continue - # Configurations inherit (most) settings from the enclosing target scope. - # Get the inheritance relationship right by making a copy of the target - # dict. - new_configuration_dict = {} - for (key, target_val) in target_dict.iteritems(): - key_ext = key[-1:] - if key_ext in key_suffixes: - key_base = key[:-1] - else: - key_base = key - if not key_base in non_configuration_keys: - new_configuration_dict[key] = gyp.simple_copy.deepcopy(target_val) - - # Merge in configuration (with all its parents first). - MergeConfigWithInheritance(new_configuration_dict, build_file, - target_dict, configuration, []) - - merged_configurations[configuration] = new_configuration_dict - - # Put the new configurations back into the target dict as a configuration. - for configuration in merged_configurations.keys(): - target_dict['configurations'][configuration] = ( - merged_configurations[configuration]) - - # Now drop all the abstract ones. - for configuration in target_dict['configurations'].keys(): - old_configuration_dict = target_dict['configurations'][configuration] - if old_configuration_dict.get('abstract'): - del target_dict['configurations'][configuration] - - # Now that all of the target's configurations have been built, go through - # the target dict's keys and remove everything that's been moved into a - # "configurations" section. - delete_keys = [] - for key in target_dict: - key_ext = key[-1:] - if key_ext in key_suffixes: - key_base = key[:-1] - else: - key_base = key - if not key_base in non_configuration_keys: - delete_keys.append(key) - for key in delete_keys: - del target_dict[key] - - # Check the configurations to see if they contain invalid keys. - for configuration in target_dict['configurations'].keys(): - configuration_dict = target_dict['configurations'][configuration] - for key in configuration_dict.keys(): - if key in invalid_configuration_keys: - raise GypError('%s not allowed in the %s configuration, found in ' - 'target %s' % (key, configuration, target)) - - - -def ProcessListFiltersInDict(name, the_dict): - """Process regular expression and exclusion-based filters on lists. - - An exclusion list is in a dict key named with a trailing "!", like - "sources!". Every item in such a list is removed from the associated - main list, which in this example, would be "sources". Removed items are - placed into a "sources_excluded" list in the dict. - - Regular expression (regex) filters are contained in dict keys named with a - trailing "/", such as "sources/" to operate on the "sources" list. Regex - filters in a dict take the form: - 'sources/': [ ['exclude', '_(linux|mac|win)\\.cc$'], - ['include', '_mac\\.cc$'] ], - The first filter says to exclude all files ending in _linux.cc, _mac.cc, and - _win.cc. The second filter then includes all files ending in _mac.cc that - are now or were once in the "sources" list. Items matching an "exclude" - filter are subject to the same processing as would occur if they were listed - by name in an exclusion list (ending in "!"). Items matching an "include" - filter are brought back into the main list if previously excluded by an - exclusion list or exclusion regex filter. Subsequent matching "exclude" - patterns can still cause items to be excluded after matching an "include". - """ - - # Look through the dictionary for any lists whose keys end in "!" or "/". - # These are lists that will be treated as exclude lists and regular - # expression-based exclude/include lists. Collect the lists that are - # needed first, looking for the lists that they operate on, and assemble - # then into |lists|. This is done in a separate loop up front, because - # the _included and _excluded keys need to be added to the_dict, and that - # can't be done while iterating through it. - - lists = [] - del_lists = [] - for key, value in the_dict.iteritems(): - operation = key[-1] - if operation != '!' and operation != '/': - continue - - if type(value) is not list: - raise ValueError(name + ' key ' + key + ' must be list, not ' + \ - value.__class__.__name__) - - list_key = key[:-1] - if list_key not in the_dict: - # This happens when there's a list like "sources!" but no corresponding - # "sources" list. Since there's nothing for it to operate on, queue up - # the "sources!" list for deletion now. - del_lists.append(key) - continue - - if type(the_dict[list_key]) is not list: - value = the_dict[list_key] - raise ValueError(name + ' key ' + list_key + \ - ' must be list, not ' + \ - value.__class__.__name__ + ' when applying ' + \ - {'!': 'exclusion', '/': 'regex'}[operation]) - - if not list_key in lists: - lists.append(list_key) - - # Delete the lists that are known to be unneeded at this point. - for del_list in del_lists: - del the_dict[del_list] - - for list_key in lists: - the_list = the_dict[list_key] - - # Initialize the list_actions list, which is parallel to the_list. Each - # item in list_actions identifies whether the corresponding item in - # the_list should be excluded, unconditionally preserved (included), or - # whether no exclusion or inclusion has been applied. Items for which - # no exclusion or inclusion has been applied (yet) have value -1, items - # excluded have value 0, and items included have value 1. Includes and - # excludes override previous actions. All items in list_actions are - # initialized to -1 because no excludes or includes have been processed - # yet. - list_actions = list((-1,) * len(the_list)) - - exclude_key = list_key + '!' - if exclude_key in the_dict: - for exclude_item in the_dict[exclude_key]: - for index in xrange(0, len(the_list)): - if exclude_item == the_list[index]: - # This item matches the exclude_item, so set its action to 0 - # (exclude). - list_actions[index] = 0 - - # The "whatever!" list is no longer needed, dump it. - del the_dict[exclude_key] - - regex_key = list_key + '/' - if regex_key in the_dict: - for regex_item in the_dict[regex_key]: - [action, pattern] = regex_item - pattern_re = re.compile(pattern) - - if action == 'exclude': - # This item matches an exclude regex, so set its value to 0 (exclude). - action_value = 0 - elif action == 'include': - # This item matches an include regex, so set its value to 1 (include). - action_value = 1 - else: - # This is an action that doesn't make any sense. - raise ValueError('Unrecognized action ' + action + ' in ' + name + \ - ' key ' + regex_key) - - for index in xrange(0, len(the_list)): - list_item = the_list[index] - if list_actions[index] == action_value: - # Even if the regex matches, nothing will change so continue (regex - # searches are expensive). - continue - if pattern_re.search(list_item): - # Regular expression match. - list_actions[index] = action_value - - # The "whatever/" list is no longer needed, dump it. - del the_dict[regex_key] - - # Add excluded items to the excluded list. - # - # Note that exclude_key ("sources!") is different from excluded_key - # ("sources_excluded"). The exclude_key list is input and it was already - # processed and deleted; the excluded_key list is output and it's about - # to be created. - excluded_key = list_key + '_excluded' - if excluded_key in the_dict: - raise GypError(name + ' key ' + excluded_key + - ' must not be present prior ' - ' to applying exclusion/regex filters for ' + list_key) - - excluded_list = [] - - # Go backwards through the list_actions list so that as items are deleted, - # the indices of items that haven't been seen yet don't shift. That means - # that things need to be prepended to excluded_list to maintain them in the - # same order that they existed in the_list. - for index in xrange(len(list_actions) - 1, -1, -1): - if list_actions[index] == 0: - # Dump anything with action 0 (exclude). Keep anything with action 1 - # (include) or -1 (no include or exclude seen for the item). - excluded_list.insert(0, the_list[index]) - del the_list[index] - - # If anything was excluded, put the excluded list into the_dict at - # excluded_key. - if len(excluded_list) > 0: - the_dict[excluded_key] = excluded_list - - # Now recurse into subdicts and lists that may contain dicts. - for key, value in the_dict.iteritems(): - if type(value) is dict: - ProcessListFiltersInDict(key, value) - elif type(value) is list: - ProcessListFiltersInList(key, value) - - -def ProcessListFiltersInList(name, the_list): - for item in the_list: - if type(item) is dict: - ProcessListFiltersInDict(name, item) - elif type(item) is list: - ProcessListFiltersInList(name, item) - - -def ValidateTargetType(target, target_dict): - """Ensures the 'type' field on the target is one of the known types. - - Arguments: - target: string, name of target. - target_dict: dict, target spec. - - Raises an exception on error. - """ - VALID_TARGET_TYPES = ('executable', 'loadable_module', - 'static_library', 'shared_library', - 'mac_kernel_extension', 'none') - target_type = target_dict.get('type', None) - if target_type not in VALID_TARGET_TYPES: - raise GypError("Target %s has an invalid target type '%s'. " - "Must be one of %s." % - (target, target_type, '/'.join(VALID_TARGET_TYPES))) - if (target_dict.get('standalone_static_library', 0) and - not target_type == 'static_library'): - raise GypError('Target %s has type %s but standalone_static_library flag is' - ' only valid for static_library type.' % (target, - target_type)) - - -def ValidateSourcesInTarget(target, target_dict, build_file, - duplicate_basename_check): - if not duplicate_basename_check: - return - if target_dict.get('type', None) != 'static_library': - return - sources = target_dict.get('sources', []) - basenames = {} - for source in sources: - name, ext = os.path.splitext(source) - is_compiled_file = ext in [ - '.c', '.cc', '.cpp', '.cxx', '.m', '.mm', '.s', '.S'] - if not is_compiled_file: - continue - basename = os.path.basename(name) # Don't include extension. - basenames.setdefault(basename, []).append(source) - - error = '' - for basename, files in basenames.iteritems(): - if len(files) > 1: - error += ' %s: %s\n' % (basename, ' '.join(files)) - - if error: - print('static library %s has several files with the same basename:\n' % - target + error + 'libtool on Mac cannot handle that. Use ' - '--no-duplicate-basename-check to disable this validation.') - raise GypError('Duplicate basenames in sources section, see list above') - - -def ValidateRulesInTarget(target, target_dict, extra_sources_for_rules): - """Ensures that the rules sections in target_dict are valid and consistent, - and determines which sources they apply to. - - Arguments: - target: string, name of target. - target_dict: dict, target spec containing "rules" and "sources" lists. - extra_sources_for_rules: a list of keys to scan for rule matches in - addition to 'sources'. - """ - - # Dicts to map between values found in rules' 'rule_name' and 'extension' - # keys and the rule dicts themselves. - rule_names = {} - rule_extensions = {} - - rules = target_dict.get('rules', []) - for rule in rules: - # Make sure that there's no conflict among rule names and extensions. - rule_name = rule['rule_name'] - if rule_name in rule_names: - raise GypError('rule %s exists in duplicate, target %s' % - (rule_name, target)) - rule_names[rule_name] = rule - - rule_extension = rule['extension'] - if rule_extension.startswith('.'): - rule_extension = rule_extension[1:] - if rule_extension in rule_extensions: - raise GypError(('extension %s associated with multiple rules, ' + - 'target %s rules %s and %s') % - (rule_extension, target, - rule_extensions[rule_extension]['rule_name'], - rule_name)) - rule_extensions[rule_extension] = rule - - # Make sure rule_sources isn't already there. It's going to be - # created below if needed. - if 'rule_sources' in rule: - raise GypError( - 'rule_sources must not exist in input, target %s rule %s' % - (target, rule_name)) - - rule_sources = [] - source_keys = ['sources'] - source_keys.extend(extra_sources_for_rules) - for source_key in source_keys: - for source in target_dict.get(source_key, []): - (source_root, source_extension) = os.path.splitext(source) - if source_extension.startswith('.'): - source_extension = source_extension[1:] - if source_extension == rule_extension: - rule_sources.append(source) - - if len(rule_sources) > 0: - rule['rule_sources'] = rule_sources - - -def ValidateRunAsInTarget(target, target_dict, build_file): - target_name = target_dict.get('target_name') - run_as = target_dict.get('run_as') - if not run_as: - return - if type(run_as) is not dict: - raise GypError("The 'run_as' in target %s from file %s should be a " - "dictionary." % - (target_name, build_file)) - action = run_as.get('action') - if not action: - raise GypError("The 'run_as' in target %s from file %s must have an " - "'action' section." % - (target_name, build_file)) - if type(action) is not list: - raise GypError("The 'action' for 'run_as' in target %s from file %s " - "must be a list." % - (target_name, build_file)) - working_directory = run_as.get('working_directory') - if working_directory and type(working_directory) is not str: - raise GypError("The 'working_directory' for 'run_as' in target %s " - "in file %s should be a string." % - (target_name, build_file)) - environment = run_as.get('environment') - if environment and type(environment) is not dict: - raise GypError("The 'environment' for 'run_as' in target %s " - "in file %s should be a dictionary." % - (target_name, build_file)) - - -def ValidateActionsInTarget(target, target_dict, build_file): - '''Validates the inputs to the actions in a target.''' - target_name = target_dict.get('target_name') - actions = target_dict.get('actions', []) - for action in actions: - action_name = action.get('action_name') - if not action_name: - raise GypError("Anonymous action in target %s. " - "An action must have an 'action_name' field." % - target_name) - inputs = action.get('inputs', None) - if inputs is None: - raise GypError('Action in target %s has no inputs.' % target_name) - action_command = action.get('action') - if action_command and not action_command[0]: - raise GypError("Empty action as command in target %s." % target_name) - - -def TurnIntIntoStrInDict(the_dict): - """Given dict the_dict, recursively converts all integers into strings. - """ - # Use items instead of iteritems because there's no need to try to look at - # reinserted keys and their associated values. - for k, v in the_dict.items(): - if type(v) is int: - v = str(v) - the_dict[k] = v - elif type(v) is dict: - TurnIntIntoStrInDict(v) - elif type(v) is list: - TurnIntIntoStrInList(v) - - if type(k) is int: - del the_dict[k] - the_dict[str(k)] = v - - -def TurnIntIntoStrInList(the_list): - """Given list the_list, recursively converts all integers into strings. - """ - for index in xrange(0, len(the_list)): - item = the_list[index] - if type(item) is int: - the_list[index] = str(item) - elif type(item) is dict: - TurnIntIntoStrInDict(item) - elif type(item) is list: - TurnIntIntoStrInList(item) - - -def PruneUnwantedTargets(targets, flat_list, dependency_nodes, root_targets, - data): - """Return only the targets that are deep dependencies of |root_targets|.""" - qualified_root_targets = [] - for target in root_targets: - target = target.strip() - qualified_targets = gyp.common.FindQualifiedTargets(target, flat_list) - if not qualified_targets: - raise GypError("Could not find target %s" % target) - qualified_root_targets.extend(qualified_targets) - - wanted_targets = {} - for target in qualified_root_targets: - wanted_targets[target] = targets[target] - for dependency in dependency_nodes[target].DeepDependencies(): - wanted_targets[dependency] = targets[dependency] - - wanted_flat_list = [t for t in flat_list if t in wanted_targets] - - # Prune unwanted targets from each build_file's data dict. - for build_file in data['target_build_files']: - if not 'targets' in data[build_file]: - continue - new_targets = [] - for target in data[build_file]['targets']: - qualified_name = gyp.common.QualifiedTarget(build_file, - target['target_name'], - target['toolset']) - if qualified_name in wanted_targets: - new_targets.append(target) - data[build_file]['targets'] = new_targets - - return wanted_targets, wanted_flat_list - - -def VerifyNoCollidingTargets(targets): - """Verify that no two targets in the same directory share the same name. - - Arguments: - targets: A list of targets in the form 'path/to/file.gyp:target_name'. - """ - # Keep a dict going from 'subdirectory:target_name' to 'foo.gyp'. - used = {} - for target in targets: - # Separate out 'path/to/file.gyp, 'target_name' from - # 'path/to/file.gyp:target_name'. - path, name = target.rsplit(':', 1) - # Separate out 'path/to', 'file.gyp' from 'path/to/file.gyp'. - subdir, gyp = os.path.split(path) - # Use '.' for the current directory '', so that the error messages make - # more sense. - if not subdir: - subdir = '.' - # Prepare a key like 'path/to:target_name'. - key = subdir + ':' + name - if key in used: - # Complain if this target is already used. - raise GypError('Duplicate target name "%s" in directory "%s" used both ' - 'in "%s" and "%s".' % (name, subdir, gyp, used[key])) - used[key] = gyp - - -def SetGeneratorGlobals(generator_input_info): - # Set up path_sections and non_configuration_keys with the default data plus - # the generator-specific data. - global path_sections - path_sections = set(base_path_sections) - path_sections.update(generator_input_info['path_sections']) - - global non_configuration_keys - non_configuration_keys = base_non_configuration_keys[:] - non_configuration_keys.extend(generator_input_info['non_configuration_keys']) - - global multiple_toolsets - multiple_toolsets = generator_input_info[ - 'generator_supports_multiple_toolsets'] - - global generator_filelist_paths - generator_filelist_paths = generator_input_info['generator_filelist_paths'] - - -def Load(build_files, variables, includes, depth, generator_input_info, check, - circular_check, duplicate_basename_check, parallel, root_targets): - SetGeneratorGlobals(generator_input_info) - # A generator can have other lists (in addition to sources) be processed - # for rules. - extra_sources_for_rules = generator_input_info['extra_sources_for_rules'] - - # Load build files. This loads every target-containing build file into - # the |data| dictionary such that the keys to |data| are build file names, - # and the values are the entire build file contents after "early" or "pre" - # processing has been done and includes have been resolved. - # NOTE: data contains both "target" files (.gyp) and "includes" (.gypi), as - # well as meta-data (e.g. 'included_files' key). 'target_build_files' keeps - # track of the keys corresponding to "target" files. - data = {'target_build_files': set()} - # Normalize paths everywhere. This is important because paths will be - # used as keys to the data dict and for references between input files. - build_files = set(map(os.path.normpath, build_files)) - if parallel: - LoadTargetBuildFilesParallel(build_files, data, variables, includes, depth, - check, generator_input_info) - else: - aux_data = {} - for build_file in build_files: - try: - LoadTargetBuildFile(build_file, data, aux_data, - variables, includes, depth, check, True) - except Exception, e: - gyp.common.ExceptionAppend(e, 'while trying to load %s' % build_file) - raise - - # Build a dict to access each target's subdict by qualified name. - targets = BuildTargetsDict(data) - - # Fully qualify all dependency links. - QualifyDependencies(targets) - - # Remove self-dependencies from targets that have 'prune_self_dependencies' - # set to 1. - RemoveSelfDependencies(targets) - - # Expand dependencies specified as build_file:*. - ExpandWildcardDependencies(targets, data) - - # Remove all dependencies marked as 'link_dependency' from the targets of - # type 'none'. - RemoveLinkDependenciesFromNoneTargets(targets) - - # Apply exclude (!) and regex (/) list filters only for dependency_sections. - for target_name, target_dict in targets.iteritems(): - tmp_dict = {} - for key_base in dependency_sections: - for op in ('', '!', '/'): - key = key_base + op - if key in target_dict: - tmp_dict[key] = target_dict[key] - del target_dict[key] - ProcessListFiltersInDict(target_name, tmp_dict) - # Write the results back to |target_dict|. - for key in tmp_dict: - target_dict[key] = tmp_dict[key] - - # Make sure every dependency appears at most once. - RemoveDuplicateDependencies(targets) - - if circular_check: - # Make sure that any targets in a.gyp don't contain dependencies in other - # .gyp files that further depend on a.gyp. - VerifyNoGYPFileCircularDependencies(targets) - - [dependency_nodes, flat_list] = BuildDependencyList(targets) - - if root_targets: - # Remove, from |targets| and |flat_list|, the targets that are not deep - # dependencies of the targets specified in |root_targets|. - targets, flat_list = PruneUnwantedTargets( - targets, flat_list, dependency_nodes, root_targets, data) - - # Check that no two targets in the same directory have the same name. - VerifyNoCollidingTargets(flat_list) - - # Handle dependent settings of various types. - for settings_type in ['all_dependent_settings', - 'direct_dependent_settings', - 'link_settings']: - DoDependentSettings(settings_type, flat_list, targets, dependency_nodes) - - # Take out the dependent settings now that they've been published to all - # of the targets that require them. - for target in flat_list: - if settings_type in targets[target]: - del targets[target][settings_type] - - # Make sure static libraries don't declare dependencies on other static - # libraries, but that linkables depend on all unlinked static libraries - # that they need so that their link steps will be correct. - gii = generator_input_info - if gii['generator_wants_static_library_dependencies_adjusted']: - AdjustStaticLibraryDependencies(flat_list, targets, dependency_nodes, - gii['generator_wants_sorted_dependencies']) - - # Apply "post"/"late"/"target" variable expansions and condition evaluations. - for target in flat_list: - target_dict = targets[target] - build_file = gyp.common.BuildFile(target) - ProcessVariablesAndConditionsInDict( - target_dict, PHASE_LATE, variables, build_file) - - # Move everything that can go into a "configurations" section into one. - for target in flat_list: - target_dict = targets[target] - SetUpConfigurations(target, target_dict) - - # Apply exclude (!) and regex (/) list filters. - for target in flat_list: - target_dict = targets[target] - ProcessListFiltersInDict(target, target_dict) - - # Apply "latelate" variable expansions and condition evaluations. - for target in flat_list: - target_dict = targets[target] - build_file = gyp.common.BuildFile(target) - ProcessVariablesAndConditionsInDict( - target_dict, PHASE_LATELATE, variables, build_file) - - # Make sure that the rules make sense, and build up rule_sources lists as - # needed. Not all generators will need to use the rule_sources lists, but - # some may, and it seems best to build the list in a common spot. - # Also validate actions and run_as elements in targets. - for target in flat_list: - target_dict = targets[target] - build_file = gyp.common.BuildFile(target) - ValidateTargetType(target, target_dict) - ValidateSourcesInTarget(target, target_dict, build_file, - duplicate_basename_check) - ValidateRulesInTarget(target, target_dict, extra_sources_for_rules) - ValidateRunAsInTarget(target, target_dict, build_file) - ValidateActionsInTarget(target, target_dict, build_file) - - # Generators might not expect ints. Turn them into strs. - TurnIntIntoStrInDict(data) - - # TODO(mark): Return |data| for now because the generator needs a list of - # build files that came in. In the future, maybe it should just accept - # a list, and not the whole data dict. - return [flat_list, targets, data] diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input_test.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input_test.py deleted file mode 100755 index 4234fbb8302eb..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/input_test.py +++ /dev/null @@ -1,90 +0,0 @@ -#!/usr/bin/env python - -# Copyright 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. - -"""Unit tests for the input.py file.""" - -import gyp.input -import unittest -import sys - - -class TestFindCycles(unittest.TestCase): - def setUp(self): - self.nodes = {} - for x in ('a', 'b', 'c', 'd', 'e'): - self.nodes[x] = gyp.input.DependencyGraphNode(x) - - def _create_dependency(self, dependent, dependency): - dependent.dependencies.append(dependency) - dependency.dependents.append(dependent) - - def test_no_cycle_empty_graph(self): - for label, node in self.nodes.iteritems(): - self.assertEquals([], node.FindCycles()) - - def test_no_cycle_line(self): - self._create_dependency(self.nodes['a'], self.nodes['b']) - self._create_dependency(self.nodes['b'], self.nodes['c']) - self._create_dependency(self.nodes['c'], self.nodes['d']) - - for label, node in self.nodes.iteritems(): - self.assertEquals([], node.FindCycles()) - - def test_no_cycle_dag(self): - self._create_dependency(self.nodes['a'], self.nodes['b']) - self._create_dependency(self.nodes['a'], self.nodes['c']) - self._create_dependency(self.nodes['b'], self.nodes['c']) - - for label, node in self.nodes.iteritems(): - self.assertEquals([], node.FindCycles()) - - def test_cycle_self_reference(self): - self._create_dependency(self.nodes['a'], self.nodes['a']) - - self.assertEquals([[self.nodes['a'], self.nodes['a']]], - self.nodes['a'].FindCycles()) - - def test_cycle_two_nodes(self): - self._create_dependency(self.nodes['a'], self.nodes['b']) - self._create_dependency(self.nodes['b'], self.nodes['a']) - - self.assertEquals([[self.nodes['a'], self.nodes['b'], self.nodes['a']]], - self.nodes['a'].FindCycles()) - self.assertEquals([[self.nodes['b'], self.nodes['a'], self.nodes['b']]], - self.nodes['b'].FindCycles()) - - def test_two_cycles(self): - self._create_dependency(self.nodes['a'], self.nodes['b']) - self._create_dependency(self.nodes['b'], self.nodes['a']) - - self._create_dependency(self.nodes['b'], self.nodes['c']) - self._create_dependency(self.nodes['c'], self.nodes['b']) - - cycles = self.nodes['a'].FindCycles() - self.assertTrue( - [self.nodes['a'], self.nodes['b'], self.nodes['a']] in cycles) - self.assertTrue( - [self.nodes['b'], self.nodes['c'], self.nodes['b']] in cycles) - self.assertEquals(2, len(cycles)) - - def test_big_cycle(self): - self._create_dependency(self.nodes['a'], self.nodes['b']) - self._create_dependency(self.nodes['b'], self.nodes['c']) - self._create_dependency(self.nodes['c'], self.nodes['d']) - self._create_dependency(self.nodes['d'], self.nodes['e']) - self._create_dependency(self.nodes['e'], self.nodes['a']) - - self.assertEquals([[self.nodes['a'], - self.nodes['b'], - self.nodes['c'], - self.nodes['d'], - self.nodes['e'], - self.nodes['a']]], - self.nodes['a'].FindCycles()) - - -if __name__ == '__main__': - unittest.main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py deleted file mode 100755 index eeeaceb0c7aa2..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/mac_tool.py +++ /dev/null @@ -1,610 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2012 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. - -"""Utility functions to perform Xcode-style build steps. - -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 -import re -import shutil -import string -import subprocess -import sys -import tempfile - - -def main(args): - executor = MacTool() - exit_code = executor.Dispatch(args) - if exit_code is not None: - sys.exit(exit_code) - - -class MacTool(object): - """This class performs all the Mac tooling steps. The methods can either be - executed directly, or dispatched from an argument list.""" - - def Dispatch(self, args): - """Dispatches a string command to a method.""" - if len(args) < 1: - raise Exception("Not enough arguments") - - method = "Exec%s" % self._CommandifyName(args[0]) - return getattr(self, method)(*args[1:]) - - def _CommandifyName(self, name_string): - """Transforms a tool name like copy-info-plist to CopyInfoPlist""" - return name_string.title().replace('-', '') - - def ExecCopyBundleResource(self, source, dest, convert_to_binary): - """Copies a resource file to the bundle/Resources directory, performing any - necessary compilation on each resource.""" - extension = os.path.splitext(source)[1].lower() - if os.path.isdir(source): - # Copy tree. - # TODO(thakis): This copies file attributes like mtime, while the - # single-file branch below doesn't. This should probably be changed to - # be consistent with the single-file branch. - if os.path.exists(dest): - shutil.rmtree(dest) - shutil.copytree(source, dest) - elif extension == '.xib': - return self._CopyXIBFile(source, dest) - elif extension == '.storyboard': - return self._CopyXIBFile(source, dest) - elif extension == '.strings': - self._CopyStringsFile(source, dest, convert_to_binary) - else: - shutil.copy(source, dest) - - def _CopyXIBFile(self, source, dest): - """Compiles a XIB file with ibtool into a binary plist in the bundle.""" - - # ibtool sometimes crashes with relative paths. See crbug.com/314728. - base = os.path.dirname(os.path.realpath(__file__)) - if os.path.relpath(source): - source = os.path.join(base, source) - if os.path.relpath(dest): - dest = os.path.join(base, dest) - - args = ['xcrun', 'ibtool', '--errors', '--warnings', '--notices', - '--output-format', 'human-readable-text', '--compile', dest, source] - ibtool_section_re = re.compile(r'/\*.*\*/') - ibtool_re = re.compile(r'.*note:.*is clipping its content') - ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE) - current_section_header = None - for line in ibtoolout.stdout: - if ibtool_section_re.match(line): - current_section_header = line - elif not ibtool_re.match(line): - if current_section_header: - sys.stdout.write(current_section_header) - current_section_header = None - sys.stdout.write(line) - return ibtoolout.returncode - - def _ConvertToBinary(self, dest): - subprocess.check_call([ - 'xcrun', 'plutil', '-convert', 'binary1', '-o', dest, dest]) - - def _CopyStringsFile(self, source, dest, convert_to_binary): - """Copies a .strings file using iconv to reconvert the input into UTF-16.""" - input_code = self._DetectInputEncoding(source) or "UTF-8" - - # Xcode's CpyCopyStringsFile / builtin-copyStrings seems to call - # CFPropertyListCreateFromXMLData() behind the scenes; at least it prints - # CFPropertyListCreateFromXMLData(): Old-style plist parser: missing - # semicolon in dictionary. - # on invalid files. Do the same kind of validation. - import CoreFoundation - s = open(source, 'rb').read() - d = CoreFoundation.CFDataCreate(None, s, len(s)) - _, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None) - if error: - return - - fp = open(dest, 'wb') - fp.write(s.decode(input_code).encode('UTF-16')) - fp.close() - - if convert_to_binary == 'True': - self._ConvertToBinary(dest) - - def _DetectInputEncoding(self, file_name): - """Reads the first few bytes from file_name and tries to guess the text - encoding. Returns None as a guess if it can't detect it.""" - fp = open(file_name, 'rb') - try: - header = fp.read(3) - except e: - fp.close() - return None - fp.close() - if header.startswith("\xFE\xFF"): - return "UTF-16" - elif header.startswith("\xFF\xFE"): - return "UTF-16" - elif header.startswith("\xEF\xBB\xBF"): - return "UTF-8" - else: - return None - - def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys): - """Copies the |source| Info.plist to the destination directory |dest|.""" - # Read the source Info.plist into memory. - fd = open(source, 'r') - lines = fd.read() - fd.close() - - # Insert synthesized key/value pairs (e.g. BuildMachineOSBuild). - plist = plistlib.readPlistFromString(lines) - if keys: - plist = dict(plist.items() + json.loads(keys[0]).items()) - lines = plistlib.writePlistToString(plist) - - # Go through all the environment variables and replace them as variables in - # the file. - IDENT_RE = re.compile(r'[/\s]') - for key in os.environ: - if key.startswith('_'): - continue - evar = '${%s}' % key - evalue = os.environ[key] - lines = string.replace(lines, evar, evalue) - - # Xcode supports various suffices on environment variables, which are - # all undocumented. :rfc1034identifier is used in the standard project - # template these days, and :identifier was used earlier. They are used to - # convert non-url characters into things that look like valid urls -- - # except that the replacement character for :identifier, '_' isn't valid - # in a URL either -- oops, hence :rfc1034identifier was born. - evar = '${%s:identifier}' % key - evalue = IDENT_RE.sub('_', os.environ[key]) - lines = string.replace(lines, evar, evalue) - - evar = '${%s:rfc1034identifier}' % key - evalue = IDENT_RE.sub('-', os.environ[key]) - lines = string.replace(lines, evar, evalue) - - # Remove any keys with values that haven't been replaced. - lines = lines.split('\n') - for i in range(len(lines)): - if lines[i].strip().startswith("${"): - lines[i] = None - lines[i - 1] = None - lines = '\n'.join(filter(lambda x: x is not None, lines)) - - # Write out the file with variables replaced. - fd = open(dest, 'w') - fd.write(lines) - fd.close() - - # Now write out PkgInfo file now that the Info.plist file has been - # "compiled". - self._WritePkgInfo(dest) - - if convert_to_binary == 'True': - self._ConvertToBinary(dest) - - def _WritePkgInfo(self, info_plist): - """This writes the PkgInfo file from the data stored in Info.plist.""" - plist = plistlib.readPlist(info_plist) - if not plist: - return - - # Only create PkgInfo for executable types. - package_type = plist['CFBundlePackageType'] - if package_type != 'APPL': - return - - # The format of PkgInfo is eight characters, representing the bundle type - # and bundle signature, each four characters. If that is missing, four - # '?' characters are used instead. - signature_code = plist.get('CFBundleSignature', '????') - if len(signature_code) != 4: # Wrong length resets everything, too. - signature_code = '?' * 4 - - dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo') - fp = open(dest, 'w') - fp.write('%s%s' % (package_type, signature_code)) - fp.close() - - def ExecFlock(self, lockfile, *cmd_list): - """Emulates the most basic behavior of Linux's flock(1).""" - # Rely on exception handling to report errors. - fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666) - fcntl.flock(fd, fcntl.LOCK_EX) - return subprocess.call(cmd_list) - - def ExecFilterLibtool(self, *cmd_list): - """Calls libtool and filters out '/path/to/libtool: file: foo.o has no - symbols'.""" - libtool_re = re.compile(r'^.*libtool: file: .* has no symbols$') - libtool_re5 = re.compile( - r'^.*libtool: warning for library: ' + - r'.* the table of contents is empty ' + - r'\(no object file members in the library define global symbols\)$') - env = os.environ.copy() - # Ref: - # http://www.opensource.apple.com/source/cctools/cctools-809/misc/libtool.c - # The problem with this flag is that it resets the file mtime on the file to - # epoch=0, e.g. 1970-1-1 or 1969-12-31 depending on timezone. - env['ZERO_AR_DATE'] = '1' - libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE, env=env) - _, err = libtoolout.communicate() - for line in err.splitlines(): - if not libtool_re.match(line) and not libtool_re5.match(line): - print >>sys.stderr, line - # Unconditionally touch the output .a file on the command line if present - # and the command succeeded. A bit hacky. - if not libtoolout.returncode: - for i in range(len(cmd_list) - 1): - if cmd_list[i] == "-o" and cmd_list[i+1].endswith('.a'): - os.utime(cmd_list[i+1], None) - break - return libtoolout.returncode - - def ExecPackageFramework(self, framework, version): - """Takes a path to Something.framework and the Current version of that and - sets up all the symlinks.""" - # Find the name of the binary based on the part before the ".framework". - binary = os.path.basename(framework).split('.')[0] - - CURRENT = 'Current' - RESOURCES = 'Resources' - VERSIONS = 'Versions' - - if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)): - # Binary-less frameworks don't seem to contain symlinks (see e.g. - # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle). - return - - # Move into the framework directory to set the symlinks correctly. - pwd = os.getcwd() - os.chdir(framework) - - # Set up the Current version. - self._Relink(version, os.path.join(VERSIONS, CURRENT)) - - # Set up the root symlinks. - self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary) - self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES) - - # Back to where we were before! - os.chdir(pwd) - - def _Relink(self, dest, link): - """Creates a symlink to |dest| named |link|. If |link| already exists, - it is overwritten.""" - if os.path.lexists(link): - os.remove(link) - os.symlink(dest, link) - - def ExecCompileXcassets(self, keys, *inputs): - """Compiles multiple .xcassets files into a single .car file. - - This invokes 'actool' to compile all the inputs .xcassets files. The - |keys| arguments is a json-encoded dictionary of extra arguments to - pass to 'actool' when the asset catalogs contains an application icon - or a launch image. - - Note that 'actool' does not create the Assets.car file if the asset - catalogs does not contains imageset. - """ - command_line = [ - 'xcrun', 'actool', '--output-format', 'human-readable-text', - '--compress-pngs', '--notices', '--warnings', '--errors', - ] - is_iphone_target = 'IPHONEOS_DEPLOYMENT_TARGET' in os.environ - if is_iphone_target: - platform = os.environ['CONFIGURATION'].split('-')[-1] - if platform not in ('iphoneos', 'iphonesimulator'): - platform = 'iphonesimulator' - command_line.extend([ - '--platform', platform, '--target-device', 'iphone', - '--target-device', 'ipad', '--minimum-deployment-target', - os.environ['IPHONEOS_DEPLOYMENT_TARGET'], '--compile', - os.path.abspath(os.environ['CONTENTS_FOLDER_PATH']), - ]) - else: - command_line.extend([ - '--platform', 'macosx', '--target-device', 'mac', - '--minimum-deployment-target', os.environ['MACOSX_DEPLOYMENT_TARGET'], - '--compile', - os.path.abspath(os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']), - ]) - if keys: - keys = json.loads(keys) - for key, value in keys.iteritems(): - arg_name = '--' + key - if isinstance(value, bool): - if value: - command_line.append(arg_name) - elif isinstance(value, list): - for v in value: - command_line.append(arg_name) - command_line.append(str(v)) - else: - command_line.append(arg_name) - command_line.append(str(value)) - # Note: actool crashes if inputs path are relative, so use os.path.abspath - # to get absolute path name for inputs. - command_line.extend(map(os.path.abspath, inputs)) - subprocess.check_call(command_line) - - def ExecMergeInfoPlist(self, output, *inputs): - """Merge multiple .plist files into a single .plist file.""" - merged_plist = {} - for path in inputs: - plist = self._LoadPlistMaybeBinary(path) - self._MergePlist(merged_plist, plist) - plistlib.writePlist(merged_plist, output) - - 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 _MergePlist(self, merged_plist, plist): - """Merge |plist| into |merged_plist|.""" - for key, value in plist.iteritems(): - if isinstance(value, dict): - merged_value = merged_plist.get(key, {}) - if isinstance(merged_value, dict): - self._MergePlist(merged_value, value) - merged_plist[key] = merged_value - else: - merged_plist[key] = value - else: - merged_plist[key] = value - - 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 {k: self._ExpandVariables(data[k], substitutions) for k in data} - return data - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py deleted file mode 100644 index ca67b122f0b9b..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/msvs_emulation.py +++ /dev/null @@ -1,1087 +0,0 @@ -# Copyright (c) 2012 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. - -""" -This module helps emulate Visual Studio 2008 behavior on top of other -build systems, primarily ninja. -""" - -import os -import re -import subprocess -import sys - -from gyp.common import OrderedSet -import gyp.MSVSUtil -import gyp.MSVSVersion - - -windows_quoter_regex = re.compile(r'(\\*)"') - - -def QuoteForRspFile(arg): - """Quote a command line argument so that it appears as one argument when - processed via cmd.exe and parsed by CommandLineToArgvW (as is typical for - Windows programs).""" - # See http://goo.gl/cuFbX and http://goo.gl/dhPnp including the comment - # threads. This is actually the quoting rules for CommandLineToArgvW, not - # for the shell, because the shell doesn't do anything in Windows. This - # works more or less because most programs (including the compiler, etc.) - # use that function to handle command line arguments. - - # For a literal quote, CommandLineToArgvW requires 2n+1 backslashes - # preceding it, and results in n backslashes + the quote. So we substitute - # in 2* what we match, +1 more, plus the quote. - arg = windows_quoter_regex.sub(lambda mo: 2 * mo.group(1) + '\\"', arg) - - # %'s also need to be doubled otherwise they're interpreted as batch - # positional arguments. Also make sure to escape the % so that they're - # passed literally through escaping so they can be singled to just the - # original %. Otherwise, trying to pass the literal representation that - # looks like an environment variable to the shell (e.g. %PATH%) would fail. - arg = arg.replace('%', '%%') - - # These commands are used in rsp files, so no escaping for the shell (via ^) - # is necessary. - - # Finally, wrap the whole thing in quotes so that the above quote rule - # applies and whitespace isn't a word break. - return '"' + arg + '"' - - -def EncodeRspFileList(args): - """Process a list of arguments using QuoteCmdExeArgument.""" - # Note that the first argument is assumed to be the command. Don't add - # quotes around it because then built-ins like 'echo', etc. won't work. - # Take care to normpath only the path in the case of 'call ../x.bat' because - # otherwise the whole thing is incorrectly interpreted as a path and not - # normalized correctly. - if not args: return '' - if args[0].startswith('call '): - call, program = args[0].split(' ', 1) - program = call + ' ' + os.path.normpath(program) - else: - program = os.path.normpath(args[0]) - return program + ' ' + ' '.join(QuoteForRspFile(arg) for arg in args[1:]) - - -def _GenericRetrieve(root, default, path): - """Given a list of dictionary keys |path| and a tree of dicts |root|, find - value at path, or return |default| if any of the path doesn't exist.""" - if not root: - return default - if not path: - return root - return _GenericRetrieve(root.get(path[0]), default, path[1:]) - - -def _AddPrefix(element, prefix): - """Add |prefix| to |element| or each subelement if element is iterable.""" - if element is None: - return element - # Note, not Iterable because we don't want to handle strings like that. - if isinstance(element, list) or isinstance(element, tuple): - return [prefix + e for e in element] - else: - return prefix + element - - -def _DoRemapping(element, map): - """If |element| then remap it through |map|. If |element| is iterable then - each item will be remapped. Any elements not found will be removed.""" - if map is not None and element is not None: - if not callable(map): - map = map.get # Assume it's a dict, otherwise a callable to do the remap. - if isinstance(element, list) or isinstance(element, tuple): - element = filter(None, [map(elem) for elem in element]) - else: - element = map(element) - return element - - -def _AppendOrReturn(append, element): - """If |append| is None, simply return |element|. If |append| is not None, - then add |element| to it, adding each item in |element| if it's a list or - tuple.""" - if append is not None and element is not None: - if isinstance(element, list) or isinstance(element, tuple): - append.extend(element) - else: - append.append(element) - else: - return element - - -def _FindDirectXInstallation(): - """Try to find an installation location for the DirectX SDK. Check for the - standard environment variable, and if that doesn't exist, try to find - via the registry. May return None if not found in either location.""" - # Return previously calculated value, if there is one - if hasattr(_FindDirectXInstallation, 'dxsdk_dir'): - return _FindDirectXInstallation.dxsdk_dir - - dxsdk_dir = os.environ.get('DXSDK_DIR') - if not dxsdk_dir: - # Setup params to pass to and attempt to launch reg.exe. - cmd = ['reg.exe', 'query', r'HKLM\Software\Microsoft\DirectX', '/s'] - p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - for line in p.communicate()[0].splitlines(): - if 'InstallPath' in line: - dxsdk_dir = line.split(' ')[3] + "\\" - - # Cache return value - _FindDirectXInstallation.dxsdk_dir = dxsdk_dir - return dxsdk_dir - - -def GetGlobalVSMacroEnv(vs_version): - """Get a dict of variables mapping internal VS macro names to their gyp - equivalents. Returns all variables that are independent of the target.""" - env = {} - # '$(VSInstallDir)' and '$(VCInstallDir)' are available when and only when - # Visual Studio is actually installed. - if vs_version.Path(): - env['$(VSInstallDir)'] = vs_version.Path() - env['$(VCInstallDir)'] = os.path.join(vs_version.Path(), 'VC') + '\\' - # Chromium uses DXSDK_DIR in include/lib paths, but it may or may not be - # set. This happens when the SDK is sync'd via src-internal, rather than - # by typical end-user installation of the SDK. If it's not set, we don't - # want to leave the unexpanded variable in the path, so simply strip it. - dxsdk_dir = _FindDirectXInstallation() - env['$(DXSDK_DIR)'] = dxsdk_dir if dxsdk_dir else '' - # Try to find an installation location for the Windows DDK by checking - # the WDK_DIR environment variable, may be None. - env['$(WDK_DIR)'] = os.environ.get('WDK_DIR', '') - return env - -def ExtractSharedMSVSSystemIncludes(configs, generator_flags): - """Finds msvs_system_include_dirs that are common to all targets, removes - them from all targets, and returns an OrderedSet containing them.""" - all_system_includes = OrderedSet( - configs[0].get('msvs_system_include_dirs', [])) - for config in configs[1:]: - system_includes = config.get('msvs_system_include_dirs', []) - all_system_includes = all_system_includes & OrderedSet(system_includes) - if not all_system_includes: - return None - # Expand macros in all_system_includes. - env = GetGlobalVSMacroEnv(GetVSVersion(generator_flags)) - expanded_system_includes = OrderedSet([ExpandMacros(include, env) - for include in all_system_includes]) - if any(['$' in include for include in expanded_system_includes]): - # Some path relies on target-specific variables, bail. - return None - - # Remove system includes shared by all targets from the targets. - for config in configs: - includes = config.get('msvs_system_include_dirs', []) - if includes: # Don't insert a msvs_system_include_dirs key if not needed. - # This must check the unexpanded includes list: - new_includes = [i for i in includes if i not in all_system_includes] - config['msvs_system_include_dirs'] = new_includes - return expanded_system_includes - - -class MsvsSettings(object): - """A class that understands the gyp 'msvs_...' values (especially the - msvs_settings field). They largely correpond to the VS2008 IDE DOM. This - class helps map those settings to command line options.""" - - def __init__(self, spec, generator_flags): - self.spec = spec - self.vs_version = GetVSVersion(generator_flags) - - supported_fields = [ - ('msvs_configuration_attributes', dict), - ('msvs_settings', dict), - ('msvs_system_include_dirs', list), - ('msvs_disabled_warnings', list), - ('msvs_precompiled_header', str), - ('msvs_precompiled_source', str), - ('msvs_configuration_platform', str), - ('msvs_target_platform', str), - ] - configs = spec['configurations'] - for field, default in supported_fields: - setattr(self, field, {}) - for configname, config in configs.iteritems(): - getattr(self, field)[configname] = config.get(field, default()) - - self.msvs_cygwin_dirs = spec.get('msvs_cygwin_dirs', ['.']) - - unsupported_fields = [ - 'msvs_prebuild', - 'msvs_postbuild', - ] - unsupported = [] - for field in unsupported_fields: - for config in configs.values(): - if field in config: - unsupported += ["%s not supported (target %s)." % - (field, spec['target_name'])] - if unsupported: - raise Exception('\n'.join(unsupported)) - - def GetExtension(self): - """Returns the extension for the target, with no leading dot. - - Uses 'product_extension' if specified, otherwise uses MSVS defaults based on - the target type. - """ - ext = self.spec.get('product_extension', None) - if ext: - return ext - return gyp.MSVSUtil.TARGET_TYPE_EXT.get(self.spec['type'], '') - - def GetVSMacroEnv(self, base_to_build=None, config=None): - """Get a dict of variables mapping internal VS macro names to their gyp - equivalents.""" - target_platform = 'Win32' if self.GetArch(config) == 'x86' else 'x64' - target_name = self.spec.get('product_prefix', '') + \ - self.spec.get('product_name', self.spec['target_name']) - target_dir = base_to_build + '\\' if base_to_build else '' - target_ext = '.' + self.GetExtension() - target_file_name = target_name + target_ext - - replacements = { - '$(InputName)': '${root}', - '$(InputPath)': '${source}', - '$(IntDir)': '$!INTERMEDIATE_DIR', - '$(OutDir)\\': target_dir, - '$(PlatformName)': target_platform, - '$(ProjectDir)\\': '', - '$(ProjectName)': self.spec['target_name'], - '$(TargetDir)\\': target_dir, - '$(TargetExt)': target_ext, - '$(TargetFileName)': target_file_name, - '$(TargetName)': target_name, - '$(TargetPath)': os.path.join(target_dir, target_file_name), - } - replacements.update(GetGlobalVSMacroEnv(self.vs_version)) - return replacements - - def ConvertVSMacros(self, s, base_to_build=None, config=None): - """Convert from VS macro names to something equivalent.""" - env = self.GetVSMacroEnv(base_to_build, config=config) - return ExpandMacros(s, env) - - def AdjustLibraries(self, libraries): - """Strip -l from library if it's specified with that.""" - libs = [lib[2:] if lib.startswith('-l') else lib for lib in libraries] - return [lib + '.lib' if not lib.endswith('.lib') else lib for lib in libs] - - def _GetAndMunge(self, field, path, default, prefix, append, map): - """Retrieve a value from |field| at |path| or return |default|. If - |append| is specified, and the item is found, it will be appended to that - object instead of returned. If |map| is specified, results will be - remapped through |map| before being returned or appended.""" - result = _GenericRetrieve(field, default, path) - result = _DoRemapping(result, map) - result = _AddPrefix(result, prefix) - return _AppendOrReturn(append, result) - - class _GetWrapper(object): - def __init__(self, parent, field, base_path, append=None): - self.parent = parent - self.field = field - self.base_path = [base_path] - self.append = append - def __call__(self, name, map=None, prefix='', default=None): - return self.parent._GetAndMunge(self.field, self.base_path + [name], - default=default, prefix=prefix, append=self.append, map=map) - - def GetArch(self, config): - """Get architecture based on msvs_configuration_platform and - msvs_target_platform. Returns either 'x86' or 'x64'.""" - configuration_platform = self.msvs_configuration_platform.get(config, '') - platform = self.msvs_target_platform.get(config, '') - if not platform: # If no specific override, use the configuration's. - platform = configuration_platform - # Map from platform to architecture. - return {'Win32': 'x86', 'x64': 'x64'}.get(platform, 'x86') - - def _TargetConfig(self, config): - """Returns the target-specific configuration.""" - # There's two levels of architecture/platform specification in VS. The - # first level is globally for the configuration (this is what we consider - # "the" config at the gyp level, which will be something like 'Debug' or - # 'Release_x64'), and a second target-specific configuration, which is an - # override for the global one. |config| is remapped here to take into - # account the local target-specific overrides to the global configuration. - arch = self.GetArch(config) - if arch == 'x64' and not config.endswith('_x64'): - config += '_x64' - if arch == 'x86' and config.endswith('_x64'): - config = config.rsplit('_', 1)[0] - return config - - def _Setting(self, path, config, - default=None, prefix='', append=None, map=None): - """_GetAndMunge for msvs_settings.""" - return self._GetAndMunge( - self.msvs_settings[config], path, default, prefix, append, map) - - def _ConfigAttrib(self, path, config, - default=None, prefix='', append=None, map=None): - """_GetAndMunge for msvs_configuration_attributes.""" - return self._GetAndMunge( - self.msvs_configuration_attributes[config], - path, default, prefix, append, map) - - def AdjustIncludeDirs(self, include_dirs, config): - """Updates include_dirs to expand VS specific paths, and adds the system - include dirs used for platform SDK and similar.""" - config = self._TargetConfig(config) - includes = include_dirs + self.msvs_system_include_dirs[config] - includes.extend(self._Setting( - ('VCCLCompilerTool', 'AdditionalIncludeDirectories'), config, default=[])) - return [self.ConvertVSMacros(p, config=config) for p in includes] - - def AdjustMidlIncludeDirs(self, midl_include_dirs, config): - """Updates midl_include_dirs to expand VS specific paths, and adds the - system include dirs used for platform SDK and similar.""" - config = self._TargetConfig(config) - includes = midl_include_dirs + self.msvs_system_include_dirs[config] - includes.extend(self._Setting( - ('VCMIDLTool', 'AdditionalIncludeDirectories'), config, default=[])) - return [self.ConvertVSMacros(p, config=config) for p in includes] - - def GetComputedDefines(self, config): - """Returns the set of defines that are injected to the defines list based - on other VS settings.""" - config = self._TargetConfig(config) - defines = [] - if self._ConfigAttrib(['CharacterSet'], config) == '1': - defines.extend(('_UNICODE', 'UNICODE')) - if self._ConfigAttrib(['CharacterSet'], config) == '2': - defines.append('_MBCS') - defines.extend(self._Setting( - ('VCCLCompilerTool', 'PreprocessorDefinitions'), config, default=[])) - return defines - - def GetCompilerPdbName(self, config, expand_special): - """Get the pdb file name that should be used for compiler invocations, or - None if there's no explicit name specified.""" - config = self._TargetConfig(config) - pdbname = self._Setting( - ('VCCLCompilerTool', 'ProgramDataBaseFileName'), config) - if pdbname: - pdbname = expand_special(self.ConvertVSMacros(pdbname)) - return pdbname - - def GetMapFileName(self, config, expand_special): - """Gets the explicitly overriden map file name for a target or returns None - if it's not set.""" - config = self._TargetConfig(config) - map_file = self._Setting(('VCLinkerTool', 'MapFileName'), config) - if map_file: - map_file = expand_special(self.ConvertVSMacros(map_file, config=config)) - return map_file - - def GetOutputName(self, config, expand_special): - """Gets the explicitly overridden output name for a target or returns None - if it's not overridden.""" - config = self._TargetConfig(config) - type = self.spec['type'] - root = 'VCLibrarianTool' if type == 'static_library' else 'VCLinkerTool' - # TODO(scottmg): Handle OutputDirectory without OutputFile. - output_file = self._Setting((root, 'OutputFile'), config) - if output_file: - output_file = expand_special(self.ConvertVSMacros( - output_file, config=config)) - return output_file - - 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) - generate_debug_info = self._Setting( - ('VCLinkerTool', 'GenerateDebugInformation'), config) - if generate_debug_info == 'true': - if output_file: - return expand_special(self.ConvertVSMacros(output_file, config=config)) - else: - return default - else: - return None - - def GetNoImportLibrary(self, config): - """If NoImportLibrary: true, ninja will not expect the output to include - an import library.""" - config = self._TargetConfig(config) - noimplib = self._Setting(('NoImportLibrary',), config) - return noimplib == 'true' - - def GetAsmflags(self, config): - """Returns the flags that need to be added to ml invocations.""" - config = self._TargetConfig(config) - asmflags = [] - safeseh = self._Setting(('MASM', 'UseSafeExceptionHandlers'), config) - if safeseh == 'true': - asmflags.append('/safeseh') - return asmflags - - def GetCflags(self, config): - """Returns the flags that need to be added to .c and .cc compilations.""" - config = self._TargetConfig(config) - cflags = [] - cflags.extend(['/wd' + w for w in self.msvs_disabled_warnings[config]]) - cl = self._GetWrapper(self, self.msvs_settings[config], - 'VCCLCompilerTool', append=cflags) - cl('Optimization', - map={'0': 'd', '1': '1', '2': '2', '3': 'x'}, prefix='/O', default='2') - cl('InlineFunctionExpansion', prefix='/Ob') - cl('DisableSpecificWarnings', prefix='/wd') - cl('StringPooling', map={'true': '/GF'}) - cl('EnableFiberSafeOptimizations', map={'true': '/GT'}) - cl('OmitFramePointers', map={'false': '-', 'true': ''}, prefix='/Oy') - cl('EnableIntrinsicFunctions', map={'false': '-', 'true': ''}, prefix='/Oi') - cl('FavorSizeOrSpeed', map={'1': 't', '2': 's'}, prefix='/O') - cl('FloatingPointModel', - map={'0': 'precise', '1': 'strict', '2': 'fast'}, prefix='/fp:', - default='0') - cl('CompileAsManaged', map={'false': '', 'true': '/clr'}) - cl('WholeProgramOptimization', map={'true': '/GL'}) - cl('WarningLevel', prefix='/W') - cl('WarnAsError', map={'true': '/WX'}) - cl('CallingConvention', - map={'0': 'd', '1': 'r', '2': 'z', '3': 'v'}, prefix='/G') - cl('DebugInformationFormat', - map={'1': '7', '3': 'i', '4': 'I'}, prefix='/Z') - cl('RuntimeTypeInfo', map={'true': '/GR', 'false': '/GR-'}) - cl('EnableFunctionLevelLinking', map={'true': '/Gy', 'false': '/Gy-'}) - cl('MinimalRebuild', map={'true': '/Gm'}) - cl('BufferSecurityCheck', map={'true': '/GS', 'false': '/GS-'}) - cl('BasicRuntimeChecks', map={'1': 's', '2': 'u', '3': '1'}, prefix='/RTC') - cl('RuntimeLibrary', - map={'0': 'T', '1': 'Td', '2': 'D', '3': 'Dd'}, prefix='/M') - cl('ExceptionHandling', map={'1': 'sc','2': 'a'}, prefix='/EH') - cl('DefaultCharIsUnsigned', map={'true': '/J'}) - cl('TreatWChar_tAsBuiltInType', - map={'false': '-', 'true': ''}, prefix='/Zc:wchar_t') - cl('EnablePREfast', map={'true': '/analyze'}) - cl('AdditionalOptions', prefix='') - cl('EnableEnhancedInstructionSet', - map={'1': 'SSE', '2': 'SSE2', '3': 'AVX', '4': 'IA32', '5': 'AVX2'}, - prefix='/arch:') - cflags.extend(['/FI' + f for f in self._Setting( - ('VCCLCompilerTool', 'ForcedIncludeFiles'), config, default=[])]) - if self.vs_version.short_name in ('2013', '2013e', '2015'): - # New flag required in 2013 to maintain previous PDB behavior. - cflags.append('/FS') - # ninja handles parallelism by itself, don't have the compiler do it too. - cflags = filter(lambda x: not x.startswith('/MP'), cflags) - return cflags - - def _GetPchFlags(self, config, extension): - """Get the flags to be added to the cflags for precompiled header support. - """ - config = self._TargetConfig(config) - # The PCH is only built once by a particular source file. Usage of PCH must - # only be for the same language (i.e. C vs. C++), so only include the pch - # flags when the language matches. - if self.msvs_precompiled_header[config]: - source_ext = os.path.splitext(self.msvs_precompiled_source[config])[1] - if _LanguageMatchesForPch(source_ext, extension): - pch = os.path.split(self.msvs_precompiled_header[config])[1] - return ['/Yu' + pch, '/FI' + pch, '/Fp${pchprefix}.' + pch + '.pch'] - return [] - - def GetCflagsC(self, config): - """Returns the flags that need to be added to .c compilations.""" - config = self._TargetConfig(config) - return self._GetPchFlags(config, '.c') - - def GetCflagsCC(self, config): - """Returns the flags that need to be added to .cc compilations.""" - config = self._TargetConfig(config) - return ['/TP'] + self._GetPchFlags(config, '.cc') - - def _GetAdditionalLibraryDirectories(self, root, config, gyp_to_build_path): - """Get and normalize the list of paths in AdditionalLibraryDirectories - setting.""" - config = self._TargetConfig(config) - libpaths = self._Setting((root, 'AdditionalLibraryDirectories'), - config, default=[]) - libpaths = [os.path.normpath( - gyp_to_build_path(self.ConvertVSMacros(p, config=config))) - for p in libpaths] - return ['/LIBPATH:"' + p + '"' for p in libpaths] - - def GetLibFlags(self, config, gyp_to_build_path): - """Returns the flags that need to be added to lib commands.""" - config = self._TargetConfig(config) - libflags = [] - lib = self._GetWrapper(self, self.msvs_settings[config], - 'VCLibrarianTool', append=libflags) - libflags.extend(self._GetAdditionalLibraryDirectories( - 'VCLibrarianTool', config, gyp_to_build_path)) - lib('LinkTimeCodeGeneration', map={'true': '/LTCG'}) - lib('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'}, - prefix='/MACHINE:') - lib('AdditionalOptions') - return libflags - - def GetDefFile(self, gyp_to_build_path): - """Returns the .def file from sources, if any. Otherwise returns None.""" - spec = self.spec - if spec['type'] in ('shared_library', 'loadable_module', 'executable'): - def_files = [s for s in spec.get('sources', []) if s.endswith('.def')] - if len(def_files) == 1: - return gyp_to_build_path(def_files[0]) - elif len(def_files) > 1: - raise Exception("Multiple .def files") - return None - - def _GetDefFileAsLdflags(self, ldflags, gyp_to_build_path): - """.def files get implicitly converted to a ModuleDefinitionFile for the - linker in the VS generator. Emulate that behaviour here.""" - def_file = self.GetDefFile(gyp_to_build_path) - 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, 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) - ldflags = [] - ld = self._GetWrapper(self, self.msvs_settings[config], - 'VCLinkerTool', append=ldflags) - self._GetDefFileAsLdflags(ldflags, gyp_to_build_path) - ld('GenerateDebugInformation', map={'true': '/DEBUG'}) - ld('TargetMachine', map={'1': 'X86', '17': 'X64', '3': 'ARM'}, - prefix='/MACHINE:') - 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, 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='') - - 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:') - - stack_reserve_size = self._Setting( - ('VCLinkerTool', 'StackReserveSize'), config, default='') - if stack_reserve_size: - stack_commit_size = self._Setting( - ('VCLinkerTool', 'StackCommitSize'), config, default='') - if stack_commit_size: - stack_commit_size = ',' + stack_commit_size - ldflags.append('/STACK:%s%s' % (stack_reserve_size, stack_commit_size)) - - 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': '', '2': ':PGINSTRUMENT', '3': ':PGOPTIMIZE', - '4': ':PGUPDATE'}, - prefix='/LTCG') - ld('IgnoreDefaultLibraryNames', prefix='/NODEFAULTLIB:') - ld('ResourceOnlyDLL', map={'true': '/NOENTRY'}) - ld('EntryPointSymbol', prefix='/ENTRY:') - ld('Profile', map={'true': '/PROFILE'}) - ld('LargeAddressAware', - map={'1': ':NO', '2': ''}, prefix='/LARGEADDRESSAWARE') - # TODO(scottmg): This should sort of be somewhere else (not really a flag). - ld('AdditionalDependencies', prefix='') - - if self.GetArch(config) == 'x86': - safeseh_default = 'true' - else: - safeseh_default = None - ld('ImageHasSafeExceptionHandlers', - map={'false': ':NO', 'true': ''}, prefix='/SAFESEH', - default=safeseh_default) - - # If the base address is not specifically controlled, DYNAMICBASE should - # be on by default. - base_flags = filter(lambda x: 'DYNAMICBASE' in x or x == '/FIXED', - ldflags) - if not base_flags: - ldflags.append('/DYNAMICBASE') - - # If the NXCOMPAT flag has not been specified, default to on. Despite the - # documentation that says this only defaults to on when the subsystem is - # Vista or greater (which applies to the linker), the IDE defaults it on - # unless it's explicitly off. - if not filter(lambda x: 'NXCOMPAT' in x, ldflags): - ldflags.append('/NXCOMPAT') - - have_def_file = filter(lambda x: x.startswith('/DEF:'), ldflags) - 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) - 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'], [], [] - - 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 = \ -"" \ -"%s" \ -"" - if enable_uac == 'true': - execution_level = self._Setting(('VCLinkerTool', 'UACExecutionLevel'), - config, default='0') - execution_level_map = { - '0': 'asInvoker', - '1': 'highestAvailable', - '2': 'requireAdministrator' - } - - ui_access = self._Setting(('VCLinkerTool', 'UACUIAccess'), config, - default='false') - - inner = ''' - - - - - - -''' % (execution_level_map[execution_level], ui_access) - else: - 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') - - 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 - generated by the linker.""" - files = self._Setting(('VCManifestTool', 'AdditionalManifestFiles'), config, - default=[]) - if isinstance(files, str): - files = files.split(';') - return [os.path.normpath( - gyp_to_build_path(self.ConvertVSMacros(f, config=config))) - for f in files] - - def IsUseLibraryDependencyInputs(self, config): - """Returns whether the target should be linked via Use Library Dependency - Inputs (using component .objs of a given .lib).""" - config = self._TargetConfig(config) - uldi = self._Setting(('VCLinkerTool', 'UseLibraryDependencyInputs'), config) - return uldi == 'true' - - def IsEmbedManifest(self, config): - """Returns whether manifest should be linked into binary.""" - config = self._TargetConfig(config) - embed = self._Setting(('VCManifestTool', 'EmbedManifest'), config, - default='true') - return embed == 'true' - - def IsLinkIncremental(self, config): - """Returns whether the target should be linked incrementally.""" - config = self._TargetConfig(config) - link_inc = self._Setting(('VCLinkerTool', 'LinkIncremental'), config) - return link_inc != '1' - - def GetRcflags(self, config, gyp_to_ninja_path): - """Returns the flags that need to be added to invocations of the resource - compiler.""" - config = self._TargetConfig(config) - rcflags = [] - rc = self._GetWrapper(self, self.msvs_settings[config], - 'VCResourceCompilerTool', append=rcflags) - rc('AdditionalIncludeDirectories', map=gyp_to_ninja_path, prefix='/I') - rcflags.append('/I' + gyp_to_ninja_path('.')) - rc('PreprocessorDefinitions', prefix='/d') - # /l arg must be in hex without leading '0x' - rc('Culture', prefix='/l', map=lambda x: hex(int(x))[2:]) - return rcflags - - def BuildCygwinBashCommandLine(self, args, path_to_base): - """Build a command line that runs args via cygwin bash. We assume that all - incoming paths are in Windows normpath'd form, so they need to be - converted to posix style for the part of the command line that's passed to - bash. We also have to do some Visual Studio macro emulation here because - various rules use magic VS names for things. Also note that rules that - contain ninja variables cannot be fixed here (for example ${source}), so - the outer generator needs to make sure that the paths that are written out - are in posix style, if the command line will be used here.""" - cygwin_dir = os.path.normpath( - os.path.join(path_to_base, self.msvs_cygwin_dirs[0])) - cd = ('cd %s' % path_to_base).replace('\\', '/') - args = [a.replace('\\', '/').replace('"', '\\"') for a in args] - args = ["'%s'" % a.replace("'", "'\\''") for a in args] - bash_cmd = ' '.join(args) - cmd = ( - 'call "%s\\setup_env.bat" && set CYGWIN=nontsec && ' % cygwin_dir + - 'bash -c "%s ; %s"' % (cd, bash_cmd)) - return cmd - - def IsRuleRunUnderCygwin(self, rule): - """Determine if an action should be run under cygwin. If the variable is - unset, or set to 1 we use cygwin.""" - return int(rule.get('msvs_cygwin_shell', - self.spec.get('msvs_cygwin_shell', 1))) != 0 - - def _HasExplicitRuleForExtension(self, spec, extension): - """Determine if there's an explicit rule for a particular extension.""" - for rule in spec.get('rules', []): - if rule['extension'] == extension: - return True - return False - - def _HasExplicitIdlActions(self, spec): - """Determine if an action should not run midl for .idl files.""" - return any([action.get('explicit_idl_action', 0) - for action in spec.get('actions', [])]) - - def HasExplicitIdlRulesOrActions(self, spec): - """Determine if there's an explicit rule or action for idl files. When - there isn't we need to generate implicit rules to build MIDL .idl files.""" - return (self._HasExplicitRuleForExtension(spec, 'idl') or - self._HasExplicitIdlActions(spec)) - - def HasExplicitAsmRules(self, spec): - """Determine if there's an explicit rule for asm files. When there isn't we - need to generate implicit rules to assemble .asm files.""" - return self._HasExplicitRuleForExtension(spec, 'asm') - - def GetIdlBuildData(self, source, config): - """Determine the implicit outputs for an idl file. Returns output - directory, outputs, and variables and flags that are required.""" - config = self._TargetConfig(config) - midl_get = self._GetWrapper(self, self.msvs_settings[config], 'VCMIDLTool') - def midl(name, default=None): - return self.ConvertVSMacros(midl_get(name, default=default), - config=config) - tlb = midl('TypeLibraryName', default='${root}.tlb') - header = midl('HeaderFileName', default='${root}.h') - dlldata = midl('DLLDataFileName', default='dlldata.c') - iid = midl('InterfaceIdentifierFileName', default='${root}_i.c') - proxy = midl('ProxyFileName', default='${root}_p.c') - # Note that .tlb is not included in the outputs as it is not always - # generated depending on the content of the input idl file. - outdir = midl('OutputDirectory', default='') - output = [header, dlldata, iid, proxy] - variables = [('tlb', tlb), - ('h', header), - ('dlldata', dlldata), - ('iid', iid), - ('proxy', proxy)] - # TODO(scottmg): Are there configuration settings to set these flags? - target_platform = 'win32' if self.GetArch(config) == 'x86' else 'x64' - flags = ['/char', 'signed', '/env', target_platform, '/Oicf'] - return outdir, output, variables, flags - - -def _LanguageMatchesForPch(source_ext, pch_source_ext): - c_exts = ('.c',) - cc_exts = ('.cc', '.cxx', '.cpp') - return ((source_ext in c_exts and pch_source_ext in c_exts) or - (source_ext in cc_exts and pch_source_ext in cc_exts)) - - -class PrecompiledHeader(object): - """Helper to generate dependencies and build rules to handle generation of - precompiled headers. Interface matches the GCH handler in xcode_emulation.py. - """ - def __init__( - self, settings, config, gyp_to_build_path, gyp_to_unique_output, obj_ext): - self.settings = settings - self.config = config - pch_source = self.settings.msvs_precompiled_source[self.config] - self.pch_source = gyp_to_build_path(pch_source) - filename, _ = os.path.splitext(pch_source) - self.output_obj = gyp_to_unique_output(filename + obj_ext).lower() - - def _PchHeader(self): - """Get the header that will appear in an #include line for all source - files.""" - return os.path.split(self.settings.msvs_precompiled_header[self.config])[1] - - def GetObjDependencies(self, sources, objs, arch): - """Given a list of sources files and the corresponding object files, - returns a list of the pch files that should be depended upon. The - additional wrapping in the return value is for interface compatibility - with make.py on Mac, and xcode_emulation.py.""" - assert arch is None - if not self._PchHeader(): - return [] - pch_ext = os.path.splitext(self.pch_source)[1] - for source in sources: - if _LanguageMatchesForPch(os.path.splitext(source)[1], pch_ext): - return [(None, None, self.output_obj)] - return [] - - def GetPchBuildCommands(self, arch): - """Not used on Windows as there are no additional build steps required - (instead, existing steps are modified in GetFlagsModifications below).""" - return [] - - def GetFlagsModifications(self, input, output, implicit, command, - cflags_c, cflags_cc, expand_special): - """Get the modified cflags and implicit dependencies that should be used - for the pch compilation step.""" - if input == self.pch_source: - pch_output = ['/Yc' + self._PchHeader()] - if command == 'cxx': - return ([('cflags_cc', map(expand_special, cflags_cc + pch_output))], - self.output_obj, []) - elif command == 'cc': - return ([('cflags_c', map(expand_special, cflags_c + pch_output))], - self.output_obj, []) - return [], output, implicit - - -vs_version = None -def GetVSVersion(generator_flags): - global vs_version - if not vs_version: - vs_version = gyp.MSVSVersion.SelectVisualStudioVersion( - generator_flags.get('msvs_version', 'auto'), - allow_fallback=False) - return vs_version - -def _GetVsvarsSetupArgs(generator_flags, arch): - vs = GetVSVersion(generator_flags) - return vs.SetupScript() - -def ExpandMacros(string, expansions): - """Expand $(Variable) per expansions dict. See MsvsSettings.GetVSMacroEnv - for the canonical way to retrieve a suitable dict.""" - if '$' in string: - for old, new in expansions.iteritems(): - assert '$(' not in new, new - string = string.replace(old, new) - return string - -def _ExtractImportantEnvironment(output_of_set): - """Extracts environment variables required for the toolchain to run from - a textual dump output by the cmd.exe 'set' command.""" - envvars_to_save = ( - 'goma_.*', # TODO(scottmg): This is ugly, but needed for goma. - 'include', - 'lib', - 'libpath', - 'path', - 'pathext', - 'systemroot', - 'temp', - 'tmp', - ) - env = {} - for line in output_of_set.splitlines(): - for envvar in envvars_to_save: - if re.match(envvar + '=', line.lower()): - var, setting = line.split('=', 1) - if envvar == 'path': - # Our own rules (for running gyp-win-tool) and other actions in - # Chromium rely on python being in the path. Add the path to this - # python here so that if it's not in the path when ninja is run - # later, python will still be found. - setting = os.path.dirname(sys.executable) + os.pathsep + setting - env[var.upper()] = setting - break - for required in ('SYSTEMROOT', 'TEMP', 'TMP'): - if required not in env: - raise Exception('Environment variable "%s" ' - 'required to be set to valid path' % required) - return env - -def _FormatAsEnvironmentBlock(envvar_dict): - """Format as an 'environment block' directly suitable for CreateProcess. - Briefly this is a list of key=value\0, terminated by an additional \0. See - CreateProcess documentation for more details.""" - block = '' - nul = '\0' - for key, value in envvar_dict.iteritems(): - block += key + '=' + value + nul - block += nul - return block - -def _ExtractCLPath(output_of_where): - """Gets the path to cl.exe based on the output of calling the environment - setup batch file, followed by the equivalent of `where`.""" - # Take the first line, as that's the first found in the PATH. - for line in output_of_where.strip().splitlines(): - if line.startswith('LOC:'): - return line[len('LOC:'):].strip() - -def GenerateEnvironmentFiles(toplevel_build_dir, generator_flags, - system_includes, open_out): - """It's not sufficient to have the absolute path to the compiler, linker, - etc. on Windows, as those tools rely on .dlls being in the PATH. We also - need to support both x86 and x64 compilers within the same build (to support - msvs_target_platform hackery). Different architectures require a different - compiler binary, and different supporting environment variables (INCLUDE, - LIB, LIBPATH). So, we extract the environment here, wrap all invocations - of compiler tools (cl, link, lib, rc, midl, etc.) via win_tool.py which - sets up the environment, and then we do not prefix the compiler with - an absolute path, instead preferring something like "cl.exe" in the rule - which will then run whichever the environment setup has put in the path. - When the following procedure to generate environment files does not - meet your requirement (e.g. for custom toolchains), you can pass - "-G ninja_use_custom_environment_files" to the gyp to suppress file - generation and use custom environment files prepared by yourself.""" - archs = ('x86', 'x64') - if generator_flags.get('ninja_use_custom_environment_files', 0): - cl_paths = {} - for arch in archs: - cl_paths[arch] = 'cl.exe' - return cl_paths - vs = GetVSVersion(generator_flags) - cl_paths = {} - for arch in archs: - # Extract environment variables for subprocesses. - args = vs.SetupScript(arch) - args.extend(('&&', 'set')) - popen = subprocess.Popen( - args, shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - variables, _ = popen.communicate() - env = _ExtractImportantEnvironment(variables) - - # Inject system includes from gyp files into INCLUDE. - if system_includes: - system_includes = system_includes | OrderedSet( - env.get('INCLUDE', '').split(';')) - env['INCLUDE'] = ';'.join(system_includes) - - env_block = _FormatAsEnvironmentBlock(env) - f = open_out(os.path.join(toplevel_build_dir, 'environment.' + arch), 'wb') - f.write(env_block) - f.close() - - # Find cl.exe location for this architecture. - args = vs.SetupScript(arch) - args.extend(('&&', - 'for', '%i', 'in', '(cl.exe)', 'do', '@echo', 'LOC:%~$PATH:i')) - popen = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE) - output, _ = popen.communicate() - cl_paths[arch] = _ExtractCLPath(output) - return cl_paths - -def VerifyMissingSources(sources, build_dir, generator_flags, gyp_to_ninja): - """Emulate behavior of msvs_error_on_missing_sources present in the msvs - generator: Check that all regular source files, i.e. not created at run time, - exist on disk. Missing files cause needless recompilation when building via - VS, and we want this check to match for people/bots that build using ninja, - so they're not surprised when the VS build fails.""" - if int(generator_flags.get('msvs_error_on_missing_sources', 0)): - no_specials = filter(lambda x: '$' not in x, sources) - relative = [os.path.join(build_dir, gyp_to_ninja(s)) for s in no_specials] - missing = filter(lambda x: not os.path.exists(x), relative) - if missing: - # They'll look like out\Release\..\..\stuff\things.cc, so normalize the - # path for a slightly less crazy looking output. - cleaned_up = [os.path.normpath(x) for x in missing] - raise Exception('Missing input files:\n%s' % '\n'.join(cleaned_up)) - -# Sets some values in default_variables, which are required for many -# generators, run on Windows. -def CalculateCommonVariables(default_variables, params): - generator_flags = params.get('generator_flags', {}) - - # Set a variable so conditions can be based on msvs_version. - msvs_version = gyp.msvs_emulation.GetVSVersion(generator_flags) - default_variables['MSVS_VERSION'] = msvs_version.ShortName() - - # To determine processor word size on Windows, in addition to checking - # PROCESSOR_ARCHITECTURE (which reflects the word size of the current - # process), it is also necessary to check PROCESSOR_ARCHITEW6432 (which - # contains the actual word size of the system when running thru WOW64). - if ('64' in os.environ.get('PROCESSOR_ARCHITECTURE', '') or - '64' in os.environ.get('PROCESSOR_ARCHITEW6432', '')): - default_variables['MSVS_OS_BITS'] = 64 - else: - default_variables['MSVS_OS_BITS'] = 32 diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py deleted file mode 100644 index d2948f06c08e3..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ninja_syntax.py +++ /dev/null @@ -1,160 +0,0 @@ -# This file comes from -# https://github.com/martine/ninja/blob/master/misc/ninja_syntax.py -# Do not edit! Edit the upstream one instead. - -"""Python module for generating .ninja files. - -Note that this is emphatically not a required piece of Ninja; it's -just a helpful utility for build-file-generation systems that already -use Python. -""" - -import textwrap -import re - -def escape_path(word): - return word.replace('$ ','$$ ').replace(' ','$ ').replace(':', '$:') - -class Writer(object): - def __init__(self, output, width=78): - self.output = output - self.width = width - - def newline(self): - self.output.write('\n') - - def comment(self, text): - for line in textwrap.wrap(text, self.width - 2): - self.output.write('# ' + line + '\n') - - def variable(self, key, value, indent=0): - if value is None: - return - if isinstance(value, list): - value = ' '.join(filter(None, value)) # Filter out empty strings. - self._line('%s = %s' % (key, value), indent) - - def pool(self, name, depth): - self._line('pool %s' % name) - self.variable('depth', depth, indent=1) - - def rule(self, name, command, description=None, depfile=None, - generator=False, pool=None, restat=False, rspfile=None, - rspfile_content=None, deps=None): - self._line('rule %s' % name) - self.variable('command', command, indent=1) - if description: - self.variable('description', description, indent=1) - if depfile: - self.variable('depfile', depfile, indent=1) - if generator: - self.variable('generator', '1', indent=1) - if pool: - self.variable('pool', pool, indent=1) - if restat: - self.variable('restat', '1', indent=1) - if rspfile: - self.variable('rspfile', rspfile, indent=1) - if rspfile_content: - self.variable('rspfile_content', rspfile_content, indent=1) - if deps: - self.variable('deps', deps, indent=1) - - def build(self, outputs, rule, inputs=None, implicit=None, order_only=None, - variables=None): - outputs = self._as_list(outputs) - all_inputs = self._as_list(inputs)[:] - out_outputs = list(map(escape_path, outputs)) - all_inputs = list(map(escape_path, all_inputs)) - - if implicit: - implicit = map(escape_path, self._as_list(implicit)) - all_inputs.append('|') - all_inputs.extend(implicit) - if order_only: - order_only = map(escape_path, self._as_list(order_only)) - all_inputs.append('||') - all_inputs.extend(order_only) - - self._line('build %s: %s' % (' '.join(out_outputs), - ' '.join([rule] + all_inputs))) - - if variables: - if isinstance(variables, dict): - iterator = iter(variables.items()) - else: - iterator = iter(variables) - - for key, val in iterator: - self.variable(key, val, indent=1) - - return outputs - - def include(self, path): - self._line('include %s' % path) - - def subninja(self, path): - self._line('subninja %s' % path) - - def default(self, paths): - self._line('default %s' % ' '.join(self._as_list(paths))) - - def _count_dollars_before_index(self, s, i): - """Returns the number of '$' characters right in front of s[i].""" - dollar_count = 0 - dollar_index = i - 1 - while dollar_index > 0 and s[dollar_index] == '$': - dollar_count += 1 - dollar_index -= 1 - return dollar_count - - def _line(self, text, indent=0): - """Write 'text' word-wrapped at self.width characters.""" - leading_space = ' ' * indent - while len(leading_space) + len(text) > self.width: - # The text is too wide; wrap if possible. - - # Find the rightmost space that would obey our width constraint and - # that's not an escaped space. - available_space = self.width - len(leading_space) - len(' $') - space = available_space - while True: - space = text.rfind(' ', 0, space) - if space < 0 or \ - self._count_dollars_before_index(text, space) % 2 == 0: - break - - if space < 0: - # No such space; just use the first unescaped space we can find. - space = available_space - 1 - while True: - space = text.find(' ', space + 1) - if space < 0 or \ - self._count_dollars_before_index(text, space) % 2 == 0: - break - if space < 0: - # Give up on breaking. - break - - self.output.write(leading_space + text[0:space] + ' $\n') - text = text[space+1:] - - # Subsequent lines are continuations, so indent them. - leading_space = ' ' * (indent+2) - - self.output.write(leading_space + text + '\n') - - def _as_list(self, input): - if input is None: - return [] - if isinstance(input, list): - return input - return [input] - - -def escape(string): - """Escape a string such that it can be embedded into a Ninja file without - further interpretation.""" - assert '\n' not in string, 'Ninja syntax does not allow newlines' - # We only have one special metacharacter: '$'. - return string.replace('$', '$$') diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ordered_dict.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ordered_dict.py deleted file mode 100644 index a1e89f9199087..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/ordered_dict.py +++ /dev/null @@ -1,289 +0,0 @@ -# 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/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py deleted file mode 100644 index 74c98c5a79594..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/simple_copy.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2014 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. - -"""A clone of the default copy.deepcopy that doesn't handle cyclic -structures or complex types except for dicts and lists. This is -because gyp copies so large structure that small copy overhead ends up -taking seconds in a project the size of Chromium.""" - -class Error(Exception): - pass - -__all__ = ["Error", "deepcopy"] - -def deepcopy(x): - """Deep copy operation on gyp objects such as strings, ints, dicts - and lists. More than twice as fast as copy.deepcopy but much less - generic.""" - - try: - return _deepcopy_dispatch[type(x)](x) - except KeyError: - raise Error('Unsupported type %s for deepcopy. Use copy.deepcopy ' + - 'or expand simple_copy support.' % type(x)) - -_deepcopy_dispatch = d = {} - -def _deepcopy_atomic(x): - return x - -for x in (type(None), int, long, float, - bool, str, unicode, type): - d[x] = _deepcopy_atomic - -def _deepcopy_list(x): - return [deepcopy(a) for a in x] -d[list] = _deepcopy_list - -def _deepcopy_dict(x): - y = {} - for key, value in x.iteritems(): - y[deepcopy(key)] = deepcopy(value) - return y -d[dict] = _deepcopy_dict - -del d diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py deleted file mode 100755 index bb6f1ea436f25..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/win_tool.py +++ /dev/null @@ -1,314 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2012 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. - -"""Utility functions for Windows builds. - -These functions are executed via gyp-win-tool when using the ninja generator. -""" - -import os -import re -import shutil -import subprocess -import stat -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.+)$', re.IGNORECASE) - -def main(args): - executor = WinTool() - exit_code = executor.Dispatch(args) - if exit_code is not None: - sys.exit(exit_code) - - -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 = re.sub(r'\W+', '', - '%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: - raise Exception("Not enough arguments") - - method = "Exec%s" % self._CommandifyName(args[0]) - return getattr(self, method)(*args[1:]) - - def _CommandifyName(self, name_string): - """Transforms a tool name like recursive-mirror to RecursiveMirror.""" - return name_string.title().replace('-', '') - - def _GetEnv(self, arch): - """Gets the saved environment from a file for a given architecture.""" - # The environment is saved as an "environment block" (see CreateProcess - # and msvs_emulation for details). We convert to a dict here. - # Drop last 2 NULs, one for list terminator, one for trailing vs. separator. - pairs = open(arch).read()[:-2].split('\0') - kvs = [item.split('=', 1) for item in pairs] - return dict(kvs) - - def ExecStamp(self, path): - """Simple stamp command.""" - open(path, 'w').close() - - def ExecRecursiveMirror(self, source, dest): - """Emulation of rm -rf out && cp -af in out.""" - if os.path.exists(dest): - if os.path.isdir(dest): - def _on_error(fn, path, excinfo): - # The operation failed, possibly because the file is set to - # read-only. If that's why, make it writable and try the op again. - if not os.access(path, os.W_OK): - os.chmod(path, stat.S_IWRITE) - fn(path) - shutil.rmtree(dest, onerror=_on_error) - else: - if not os.access(dest, os.W_OK): - # Attempt to make the file writable before deleting it. - os.chmod(dest, stat.S_IWRITE) - os.unlink(dest) - - if os.path.isdir(source): - shutil.copytree(source, dest) - else: - shutil.copy2(source, dest) - - 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) - if use_separate_mspdbsrv == 'True': - self._UseSeparateMspdbsrv(env, args) - link = subprocess.Popen([args[0].replace('/', '\\')] + list(args[1:]), - shell=True, - env=env, - stdout=subprocess.PIPE, - stderr=subprocess.STDOUT) - out, _ = link.communicate() - for line in out.splitlines(): - if (not line.startswith(' Creating library ') and - not line.startswith('Generating code') and - not line.startswith('Finished generating code')): - print line - 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 - (some XML blocks are recognized by the OS loader, but not the manifest - tool).""" - env = self._GetEnv(arch) - popen = subprocess.Popen(args, shell=True, env=env, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - out, _ = popen.communicate() - for line in out.splitlines(): - if line and 'manifest authoring warning 81010002' not in line: - print line - return popen.returncode - - def ExecManifestToRc(self, arch, *args): - """Creates a resource file pointing a SxS assembly manifest. - |args| is tuple containing path to resource file, path to manifest file - and resource name which can be "1" (for executables) or "2" (for DLLs).""" - manifest_path, resource_path, resource_name = args - with open(resource_path, 'wb') as output: - output.write('#include \n%s RT_MANIFEST "%s"' % ( - resource_name, - os.path.abspath(manifest_path).replace('\\', '/'))) - - def ExecMidlWrapper(self, arch, outdir, tlb, h, dlldata, iid, proxy, idl, - *flags): - """Filter noisy filenames output from MIDL compile step that isn't - quietable via command line flags. - """ - args = ['midl', '/nologo'] + list(flags) + [ - '/out', outdir, - '/tlb', tlb, - '/h', h, - '/dlldata', dlldata, - '/iid', iid, - '/proxy', proxy, - idl] - env = self._GetEnv(arch) - popen = subprocess.Popen(args, shell=True, env=env, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - out, _ = popen.communicate() - # Filter junk out of stdout, and write filtered versions. Output we want - # to filter is pairs of lines that look like this: - # Processing C:\Program Files (x86)\Microsoft SDKs\...\include\objidl.idl - # objidl.idl - lines = out.splitlines() - prefixes = ('Processing ', '64 bit Processing ') - processing = set(os.path.basename(x) - for x in lines if x.startswith(prefixes)) - for line in lines: - if not line.startswith(prefixes) and line not in processing: - print line - return popen.returncode - - def ExecAsmWrapper(self, arch, *args): - """Filter logo banner from invocations of asm.exe.""" - env = self._GetEnv(arch) - popen = subprocess.Popen(args, shell=True, env=env, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - out, _ = popen.communicate() - for line in out.splitlines(): - if (not line.startswith('Copyright (C) Microsoft Corporation') and - not line.startswith('Microsoft (R) Macro Assembler') and - not line.startswith(' Assembling: ') and - line): - print line - return popen.returncode - - def ExecRcWrapper(self, arch, *args): - """Filter logo banner from invocations of rc.exe. Older versions of RC - don't support the /nologo flag.""" - env = self._GetEnv(arch) - popen = subprocess.Popen(args, shell=True, env=env, - stdout=subprocess.PIPE, stderr=subprocess.STDOUT) - out, _ = popen.communicate() - for line in out.splitlines(): - if (not line.startswith('Microsoft (R) Windows (R) Resource Compiler') and - not line.startswith('Copyright (C) Microsoft Corporation') and - line): - print line - return popen.returncode - - def ExecActionWrapper(self, arch, rspfile, *dir): - """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 - return subprocess.call(args, shell=True, env=env, cwd=dir) - - def ExecClCompile(self, project_dir, selected_files): - """Executed by msvs-ninja projects when the 'ClCompile' target is used to - build selected C/C++ files.""" - project_dir = os.path.relpath(project_dir, BASE_DIR) - selected_files = selected_files.split(';') - ninja_targets = [os.path.join(project_dir, filename) + '^^' - for filename in selected_files] - cmd = ['ninja.exe'] - cmd.extend(ninja_targets) - return subprocess.call(cmd, shell=True, cwd=BASE_DIR) - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py deleted file mode 100644 index 69f7d97cfa69a..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_emulation.py +++ /dev/null @@ -1,1653 +0,0 @@ -# Copyright (c) 2012 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. - -""" -This module contains classes that help to emulate xcodebuild behavior on top of -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 - -# Populated lazily by XcodeVersion, for efficiency, and to fix an issue when -# "xcodebuild" is called too quickly (it has been found to return incorrect -# version number). -XCODE_VERSION_CACHE = None - -# Populated lazily by GetXcodeArchsDefault, to an |XcodeArchsDefault| instance -# corresponding to the installed version of Xcode. -XCODE_ARCHS_DEFAULT_CACHE = None - - -def XcodeArchsVariableMapping(archs, archs_including_64_bit=None): - """Constructs a dictionary with expansion for $(ARCHS_STANDARD) variable, - and optionally for $(ARCHS_STANDARD_INCLUDING_64_BIT).""" - mapping = {'$(ARCHS_STANDARD)': archs} - if archs_including_64_bit: - mapping['$(ARCHS_STANDARD_INCLUDING_64_BIT)'] = archs_including_64_bit - return mapping - -class XcodeArchsDefault(object): - """A class to resolve ARCHS variable from xcode_settings, resolving Xcode - macros and implementing filtering by VALID_ARCHS. The expansion of macros - depends on the SDKROOT used ("macosx", "iphoneos", "iphonesimulator") and - on the version of Xcode. - """ - - # Match variable like $(ARCHS_STANDARD). - variable_pattern = re.compile(r'\$\([a-zA-Z_][a-zA-Z0-9_]*\)$') - - def __init__(self, default, mac, iphonesimulator, iphoneos): - self._default = (default,) - self._archs = {'mac': mac, 'ios': iphoneos, 'iossim': iphonesimulator} - - def _VariableMapping(self, sdkroot): - """Returns the dictionary of variable mapping depending on the SDKROOT.""" - sdkroot = sdkroot.lower() - if 'iphoneos' in sdkroot: - return self._archs['ios'] - elif 'iphonesimulator' in sdkroot: - return self._archs['iossim'] - else: - return self._archs['mac'] - - def _ExpandArchs(self, archs, sdkroot): - """Expands variables references in ARCHS, and remove duplicates.""" - variable_mapping = self._VariableMapping(sdkroot) - expanded_archs = [] - for arch in archs: - if self.variable_pattern.match(arch): - variable = arch - try: - variable_expansion = variable_mapping[variable] - for arch in variable_expansion: - if arch not in expanded_archs: - expanded_archs.append(arch) - except KeyError as e: - print 'Warning: Ignoring unsupported variable "%s".' % variable - elif arch not in expanded_archs: - expanded_archs.append(arch) - return expanded_archs - - def ActiveArchs(self, archs, valid_archs, sdkroot): - """Expands variables references in ARCHS, and filter by VALID_ARCHS if it - is defined (if not set, Xcode accept any value in ARCHS, otherwise, only - values present in VALID_ARCHS are kept).""" - expanded_archs = self._ExpandArchs(archs or self._default, sdkroot or '') - if valid_archs: - filtered_archs = [] - for arch in expanded_archs: - if arch in valid_archs: - filtered_archs.append(arch) - expanded_archs = filtered_archs - return expanded_archs - - -def GetXcodeArchsDefault(): - """Returns the |XcodeArchsDefault| object to use to expand ARCHS for the - installed version of Xcode. The default values used by Xcode for ARCHS - and the expansion of the variables depends on the version of Xcode used. - - For all version anterior to Xcode 5.0 or posterior to Xcode 5.1 included - uses $(ARCHS_STANDARD) if ARCHS is unset, while Xcode 5.0 to 5.0.2 uses - $(ARCHS_STANDARD_INCLUDING_64_BIT). This variable was added to Xcode 5.0 - and deprecated with Xcode 5.1. - - For "macosx" SDKROOT, all version starting with Xcode 5.0 includes 64-bit - architecture as part of $(ARCHS_STANDARD) and default to only building it. - - For "iphoneos" and "iphonesimulator" SDKROOT, 64-bit architectures are part - of $(ARCHS_STANDARD_INCLUDING_64_BIT) from Xcode 5.0. From Xcode 5.1, they - are also part of $(ARCHS_STANDARD). - - All thoses rules are coded in the construction of the |XcodeArchsDefault| - object to use depending on the version of Xcode detected. The object is - for performance reason.""" - global XCODE_ARCHS_DEFAULT_CACHE - if XCODE_ARCHS_DEFAULT_CACHE: - return XCODE_ARCHS_DEFAULT_CACHE - xcode_version, _ = XcodeVersion() - if xcode_version < '0500': - XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault( - '$(ARCHS_STANDARD)', - XcodeArchsVariableMapping(['i386']), - XcodeArchsVariableMapping(['i386']), - XcodeArchsVariableMapping(['armv7'])) - elif xcode_version < '0510': - XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault( - '$(ARCHS_STANDARD_INCLUDING_64_BIT)', - XcodeArchsVariableMapping(['x86_64'], ['x86_64']), - XcodeArchsVariableMapping(['i386'], ['i386', 'x86_64']), - XcodeArchsVariableMapping( - ['armv7', 'armv7s'], - ['armv7', 'armv7s', 'arm64'])) - else: - XCODE_ARCHS_DEFAULT_CACHE = XcodeArchsDefault( - '$(ARCHS_STANDARD)', - XcodeArchsVariableMapping(['x86_64'], ['x86_64']), - XcodeArchsVariableMapping(['i386', 'x86_64'], ['i386', 'x86_64']), - XcodeArchsVariableMapping( - ['armv7', 'armv7s', 'arm64'], - ['armv7', 'armv7s', 'arm64'])) - return XCODE_ARCHS_DEFAULT_CACHE - - -class XcodeSettings(object): - """A class that understands the gyp 'xcode_settings' 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. - _plist_cache = {} - - # Populated lazily by GetIOSPostbuilds. Shared by all XcodeSettings, so - # cached at class-level for efficiency. - _codesigning_key_cache = {} - - def __init__(self, spec): - self.spec = spec - - self.isIOS = False - - # Per-target 'xcode_settings' are pushed down into configs earlier by gyp. - # This means self.xcode_settings[config] always contains all settings - # for that config -- the per-target settings as well. Settings that are - # the same for all configs are implicitly per-target settings. - self.xcode_settings = {} - configs = spec['configurations'] - for configname, config in configs.iteritems(): - self.xcode_settings[configname] = config.get('xcode_settings', {}) - self._ConvertConditionalKeys(configname) - if self.xcode_settings[configname].get('IPHONEOS_DEPLOYMENT_TARGET', - None): - self.isIOS = True - - # This is only non-None temporarily during the execution of some methods. - self.configname = None - - # Used by _AdjustLibrary to match .a and .dylib entries in libraries. - self.library_re = re.compile(r'^lib([^/]+)\.(a|dylib)$') - - def _ConvertConditionalKeys(self, configname): - """Converts or warns on conditional keys. Xcode supports conditional keys, - such as CODE_SIGN_IDENTITY[sdk=iphoneos*]. This is a partial implementation - with some keys converted while the rest force a warning.""" - settings = self.xcode_settings[configname] - conditional_keys = [key for key in settings if key.endswith(']')] - for key in conditional_keys: - # If you need more, speak up at http://crbug.com/122592 - if key.endswith("[sdk=iphoneos*]"): - if configname.endswith("iphoneos"): - new_key = key.split("[")[0] - settings[new_key] = settings[key] - else: - print 'Warning: Conditional keys not implemented, ignoring:', \ - ' '.join(conditional_keys) - del settings[key] - - def _Settings(self): - assert self.configname - return self.xcode_settings[self.configname] - - def _Test(self, test_key, cond_key, default): - return self._Settings().get(test_key, default) == cond_key - - def _Appendf(self, lst, test_key, format_str, default=None): - if test_key in self._Settings(): - lst.append(format_str % str(self._Settings()[test_key])) - elif default: - lst.append(format_str % str(default)) - - def _WarnUnimplemented(self, test_key): - if test_key in self._Settings(): - print 'Warning: Ignoring not yet implemented key "%s".' % test_key - - def IsBinaryOutputFormat(self, configname): - default = "binary" if self.isIOS else "xml" - format = self.xcode_settings[configname].get('INFOPLIST_OUTPUT_FORMAT', - default) - return format == "binary" - - def _IsBundle(self): - return int(self.spec.get('mac_bundle', 0)) != 0 - - def _IsIosAppExtension(self): - return int(self.spec.get('ios_app_extension', 0)) != 0 - - def _IsIosWatchKitExtension(self): - return int(self.spec.get('ios_watchkit_extension', 0)) != 0 - - def _IsIosWatchApp(self): - return int(self.spec.get('ios_watch_app', 0)) != 0 - - def _IsXCTest(self): - return int(self.spec.get('mac_xctest_bundle', 0)) != 0 - - def GetFrameworkVersion(self): - """Returns the framework version of the current target. Only valid for - bundles.""" - assert self._IsBundle() - return self.GetPerTargetSetting('FRAMEWORK_VERSION', default='A') - - def GetWrapperExtension(self): - """Returns the bundle extension (.app, .framework, .plugin, etc). Only - valid for bundles.""" - assert self._IsBundle() - if self.spec['type'] in ('loadable_module', 'shared_library'): - default_wrapper_extension = { - 'loadable_module': 'bundle', - 'shared_library': 'framework', - }[self.spec['type']] - wrapper_extension = self.GetPerTargetSetting( - 'WRAPPER_EXTENSION', default=default_wrapper_extension) - return '.' + self.spec.get('product_extension', wrapper_extension) - elif self.spec['type'] == 'executable': - if self._IsIosAppExtension() or self._IsIosWatchKitExtension(): - return '.' + self.spec.get('product_extension', 'appex') - else: - return '.' + self.spec.get('product_extension', 'app') - else: - assert False, "Don't know extension for '%s', target '%s'" % ( - self.spec['type'], self.spec['target_name']) - - def GetProductName(self): - """Returns PRODUCT_NAME.""" - return self.spec.get('product_name', self.spec['target_name']) - - def GetFullProductName(self): - """Returns FULL_PRODUCT_NAME.""" - if self._IsBundle(): - return self.GetWrapperName() - else: - return self._GetStandaloneBinaryPath() - - def GetWrapperName(self): - """Returns the directory name of the bundle represented by this target. - Only valid for bundles.""" - assert self._IsBundle() - return self.GetProductName() + self.GetWrapperExtension() - - def GetBundleContentsFolderPath(self): - """Returns the qualified path to the bundle's contents folder. E.g. - Chromium.app/Contents or Foo.bundle/Versions/A. Only valid for bundles.""" - if self.isIOS: - return self.GetWrapperName() - assert self._IsBundle() - if self.spec['type'] == 'shared_library': - return os.path.join( - self.GetWrapperName(), 'Versions', self.GetFrameworkVersion()) - else: - # loadable_modules have a 'Contents' folder like executables. - return os.path.join(self.GetWrapperName(), 'Contents') - - def GetBundleResourceFolder(self): - """Returns the qualified path to the bundle's resource folder. E.g. - Chromium.app/Contents/Resources. Only valid for bundles.""" - assert self._IsBundle() - if self.isIOS: - return self.GetBundleContentsFolderPath() - return os.path.join(self.GetBundleContentsFolderPath(), 'Resources') - - def GetBundlePlistPath(self): - """Returns the qualified path to the bundle's plist file. E.g. - Chromium.app/Contents/Info.plist. Only valid for bundles.""" - assert self._IsBundle() - if self.spec['type'] in ('executable', 'loadable_module'): - return os.path.join(self.GetBundleContentsFolderPath(), 'Info.plist') - else: - return os.path.join(self.GetBundleContentsFolderPath(), - 'Resources', 'Info.plist') - - def GetProductType(self): - """Returns the PRODUCT_TYPE of this target.""" - if self._IsIosAppExtension(): - assert self._IsBundle(), ('ios_app_extension flag requires mac_bundle ' - '(target %s)' % self.spec['target_name']) - return 'com.apple.product-type.app-extension' - if self._IsIosWatchKitExtension(): - assert self._IsBundle(), ('ios_watchkit_extension flag requires ' - 'mac_bundle (target %s)' % self.spec['target_name']) - return 'com.apple.product-type.watchkit-extension' - if self._IsIosWatchApp(): - assert self._IsBundle(), ('ios_watch_app flag requires mac_bundle ' - '(target %s)' % self.spec['target_name']) - return 'com.apple.product-type.application.watchapp' - if self._IsBundle(): - return { - 'executable': 'com.apple.product-type.application', - 'loadable_module': 'com.apple.product-type.bundle', - 'shared_library': 'com.apple.product-type.framework', - }[self.spec['type']] - else: - return { - 'executable': 'com.apple.product-type.tool', - 'loadable_module': 'com.apple.product-type.library.dynamic', - 'shared_library': 'com.apple.product-type.library.dynamic', - 'static_library': 'com.apple.product-type.library.static', - }[self.spec['type']] - - def GetMachOType(self): - """Returns the MACH_O_TYPE of this target.""" - # Weird, but matches Xcode. - if not self._IsBundle() and self.spec['type'] == 'executable': - return '' - return { - 'executable': 'mh_execute', - 'static_library': 'staticlib', - 'shared_library': 'mh_dylib', - 'loadable_module': 'mh_bundle', - }[self.spec['type']] - - def _GetBundleBinaryPath(self): - """Returns the name of the bundle binary of by this target. - E.g. Chromium.app/Contents/MacOS/Chromium. Only valid for bundles.""" - assert self._IsBundle() - if self.spec['type'] in ('shared_library') or self.isIOS: - path = self.GetBundleContentsFolderPath() - elif self.spec['type'] in ('executable', 'loadable_module'): - path = os.path.join(self.GetBundleContentsFolderPath(), 'MacOS') - return os.path.join(path, self.GetExecutableName()) - - def _GetStandaloneExecutableSuffix(self): - if 'product_extension' in self.spec: - return '.' + self.spec['product_extension'] - return { - 'executable': '', - 'static_library': '.a', - 'shared_library': '.dylib', - 'loadable_module': '.so', - }[self.spec['type']] - - def _GetStandaloneExecutablePrefix(self): - return self.spec.get('product_prefix', { - 'executable': '', - 'static_library': 'lib', - 'shared_library': 'lib', - # Non-bundled loadable_modules are called foo.so for some reason - # (that is, .so and no prefix) with the xcode build -- match that. - 'loadable_module': '', - }[self.spec['type']]) - - def _GetStandaloneBinaryPath(self): - """Returns the name of the non-bundle binary represented by this target. - E.g. hello_world. Only valid for non-bundles.""" - assert not self._IsBundle() - assert self.spec['type'] in ( - 'executable', 'shared_library', 'static_library', 'loadable_module'), ( - 'Unexpected type %s' % self.spec['type']) - target = self.spec['target_name'] - if self.spec['type'] == 'static_library': - if target[:3] == 'lib': - target = target[3:] - elif self.spec['type'] in ('loadable_module', 'shared_library'): - if target[:3] == 'lib': - target = target[3:] - - target_prefix = self._GetStandaloneExecutablePrefix() - target = self.spec.get('product_name', target) - target_ext = self._GetStandaloneExecutableSuffix() - return target_prefix + target + target_ext - - def GetExecutableName(self): - """Returns the executable name of the bundle represented by this target. - E.g. Chromium.""" - if self._IsBundle(): - return self.spec.get('product_name', self.spec['target_name']) - else: - return self._GetStandaloneBinaryPath() - - def GetExecutablePath(self): - """Returns the directory name of the bundle represented by this target. E.g. - Chromium.app/Contents/MacOS/Chromium.""" - if self._IsBundle(): - return self._GetBundleBinaryPath() - else: - return self._GetStandaloneBinaryPath() - - def GetActiveArchs(self, configname): - """Returns the architectures this target should be built for.""" - config_settings = self.xcode_settings[configname] - xcode_archs_default = GetXcodeArchsDefault() - return xcode_archs_default.ActiveArchs( - config_settings.get('ARCHS'), - config_settings.get('VALID_ARCHS'), - config_settings.get('SDKROOT')) - - def _GetSdkVersionInfoItem(self, sdk, infoitem): - # xcodebuild requires Xcode and can't run on Command Line Tools-only - # systems from 10.7 onward. - # Since the CLT has no SDK paths anyway, returning None is the - # most sensible route and should still do the right thing. - try: - return GetStdoutQuiet(['xcodebuild', '-version', '-sdk', sdk, infoitem]) - except: - pass - - def _SdkRoot(self, configname): - if configname is None: - configname = self.configname - return self.GetPerConfigSetting('SDKROOT', configname, default='') - - def _SdkPath(self, configname=None): - 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: - 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): - self._Appendf(lst, 'MACOSX_DEPLOYMENT_TARGET', '-mmacosx-version-min=%s') - if 'IPHONEOS_DEPLOYMENT_TARGET' in self._Settings(): - # TODO: Implement this better? - sdk_path_basename = os.path.basename(self._SdkPath()) - if sdk_path_basename.lower().startswith('iphonesimulator'): - self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET', - '-mios-simulator-version-min=%s') - else: - self._Appendf(lst, 'IPHONEOS_DEPLOYMENT_TARGET', - '-miphoneos-version-min=%s') - - def GetCflags(self, configname, arch=None): - """Returns flags that need to be added to .c, .cc, .m, and .mm - compilations.""" - # This functions (and the similar ones below) do not offer complete - # emulation of all xcode_settings keys. They're implemented on demand. - - self.configname = configname - cflags = [] - - sdk_root = self._SdkPath() - if 'SDKROOT' in self._Settings() and sdk_root: - cflags.append('-isysroot %s' % sdk_root) - - if self._Test('CLANG_WARN_CONSTANT_CONVERSION', 'YES', default='NO'): - cflags.append('-Wconstant-conversion') - - if self._Test('GCC_CHAR_IS_UNSIGNED_CHAR', 'YES', default='NO'): - cflags.append('-funsigned-char') - - if self._Test('GCC_CW_ASM_SYNTAX', 'YES', default='YES'): - cflags.append('-fasm-blocks') - - if 'GCC_DYNAMIC_NO_PIC' in self._Settings(): - if self._Settings()['GCC_DYNAMIC_NO_PIC'] == 'YES': - cflags.append('-mdynamic-no-pic') - else: - pass - # TODO: In this case, it depends on the target. xcode passes - # mdynamic-no-pic by default for executable and possibly static lib - # according to mento - - if self._Test('GCC_ENABLE_PASCAL_STRINGS', 'YES', default='YES'): - cflags.append('-mpascal-strings') - - self._Appendf(cflags, 'GCC_OPTIMIZATION_LEVEL', '-O%s', default='s') - - if self._Test('GCC_GENERATE_DEBUGGING_SYMBOLS', 'YES', default='YES'): - dbg_format = self._Settings().get('DEBUG_INFORMATION_FORMAT', 'dwarf') - if dbg_format == 'dwarf': - cflags.append('-gdwarf-2') - elif dbg_format == 'stabs': - raise NotImplementedError('stabs debug format is not supported yet.') - elif dbg_format == 'dwarf-with-dsym': - cflags.append('-gdwarf-2') - else: - raise NotImplementedError('Unknown debug format %s' % dbg_format) - - if self._Settings().get('GCC_STRICT_ALIASING') == 'YES': - cflags.append('-fstrict-aliasing') - elif self._Settings().get('GCC_STRICT_ALIASING') == 'NO': - cflags.append('-fno-strict-aliasing') - - if self._Test('GCC_SYMBOLS_PRIVATE_EXTERN', 'YES', default='NO'): - cflags.append('-fvisibility=hidden') - - if self._Test('GCC_TREAT_WARNINGS_AS_ERRORS', 'YES', default='NO'): - cflags.append('-Werror') - - if self._Test('GCC_WARN_ABOUT_MISSING_NEWLINE', 'YES', default='NO'): - cflags.append('-Wnewline-eof') - - # In Xcode, this is only activated when GCC_COMPILER_VERSION is clang or - # llvm-gcc. It also requires a fairly recent libtool, and - # if the system clang isn't used, DYLD_LIBRARY_PATH needs to contain the - # path to the libLTO.dylib that matches the used clang. - if self._Test('LLVM_LTO', 'YES', default='NO'): - cflags.append('-flto') - - self._AppendPlatformVersionMinFlags(cflags) - - # TODO: - if self._Test('COPY_PHASE_STRIP', 'YES', default='NO'): - self._WarnUnimplemented('COPY_PHASE_STRIP') - self._WarnUnimplemented('GCC_DEBUGGING_SYMBOLS') - self._WarnUnimplemented('GCC_ENABLE_OBJC_EXCEPTIONS') - - # TODO: This is exported correctly, but assigning to it is not supported. - self._WarnUnimplemented('MACH_O_TYPE') - self._WarnUnimplemented('PRODUCT_TYPE') - - if arch is not None: - archs = [arch] - else: - assert self.configname - archs = self.GetActiveArchs(self.configname) - if len(archs) != 1: - # TODO: Supporting fat binaries will be annoying. - self._WarnUnimplemented('ARCHS') - archs = ['i386'] - cflags.append('-arch ' + archs[0]) - - if archs[0] in ('i386', 'x86_64'): - if self._Test('GCC_ENABLE_SSE3_EXTENSIONS', 'YES', default='NO'): - cflags.append('-msse3') - if self._Test('GCC_ENABLE_SUPPLEMENTAL_SSE3_INSTRUCTIONS', 'YES', - default='NO'): - cflags.append('-mssse3') # Note 3rd 's'. - if self._Test('GCC_ENABLE_SSE41_EXTENSIONS', 'YES', default='NO'): - cflags.append('-msse4.1') - if self._Test('GCC_ENABLE_SSE42_EXTENSIONS', 'YES', default='NO'): - cflags.append('-msse4.2') - - cflags += self._Settings().get('WARNING_CFLAGS', []) - - if self._IsXCTest(): - platform_root = self._XcodePlatformPath(configname) - if platform_root: - cflags.append('-F' + platform_root + '/Developer/Library/Frameworks/') - - 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 - - def GetCflagsC(self, configname): - """Returns flags that need to be added to .c, and .m compilations.""" - self.configname = configname - cflags_c = [] - if self._Settings().get('GCC_C_LANGUAGE_STANDARD', '') == 'ansi': - cflags_c.append('-ansi') - else: - self._Appendf(cflags_c, 'GCC_C_LANGUAGE_STANDARD', '-std=%s') - cflags_c += self._Settings().get('OTHER_CFLAGS', []) - self.configname = None - return cflags_c - - def GetCflagsCC(self, configname): - """Returns flags that need to be added to .cc, and .mm compilations.""" - self.configname = configname - cflags_cc = [] - - clang_cxx_language_standard = self._Settings().get( - 'CLANG_CXX_LANGUAGE_STANDARD') - # Note: Don't make c++0x to c++11 so that c++0x can be used with older - # clangs that don't understand c++11 yet (like Xcode 4.2's). - if clang_cxx_language_standard: - cflags_cc.append('-std=%s' % clang_cxx_language_standard) - - self._Appendf(cflags_cc, 'CLANG_CXX_LIBRARY', '-stdlib=%s') - - if self._Test('GCC_ENABLE_CPP_RTTI', 'NO', default='YES'): - cflags_cc.append('-fno-rtti') - if self._Test('GCC_ENABLE_CPP_EXCEPTIONS', 'NO', default='YES'): - cflags_cc.append('-fno-exceptions') - if self._Test('GCC_INLINES_ARE_PRIVATE_EXTERN', 'YES', default='NO'): - cflags_cc.append('-fvisibility-inlines-hidden') - if self._Test('GCC_THREADSAFE_STATICS', 'NO', default='YES'): - cflags_cc.append('-fno-threadsafe-statics') - # Note: This flag is a no-op for clang, it only has an effect for gcc. - if self._Test('GCC_WARN_ABOUT_INVALID_OFFSETOF_MACRO', 'NO', default='YES'): - cflags_cc.append('-Wno-invalid-offsetof') - - other_ccflags = [] - - for flag in self._Settings().get('OTHER_CPLUSPLUSFLAGS', ['$(inherited)']): - # TODO: More general variable expansion. Missing in many other places too. - if flag in ('$inherited', '$(inherited)', '${inherited}'): - flag = '$OTHER_CFLAGS' - if flag in ('$OTHER_CFLAGS', '$(OTHER_CFLAGS)', '${OTHER_CFLAGS}'): - other_ccflags += self._Settings().get('OTHER_CFLAGS', []) - else: - other_ccflags.append(flag) - cflags_cc += other_ccflags - - self.configname = None - return cflags_cc - - def _AddObjectiveCGarbageCollectionFlags(self, flags): - gc_policy = self._Settings().get('GCC_ENABLE_OBJC_GC', 'unsupported') - if gc_policy == 'supported': - flags.append('-fobjc-gc') - elif gc_policy == 'required': - flags.append('-fobjc-gc-only') - - def _AddObjectiveCARCFlags(self, flags): - if self._Test('CLANG_ENABLE_OBJC_ARC', 'YES', default='NO'): - flags.append('-fobjc-arc') - - def _AddObjectiveCMissingPropertySynthesisFlags(self, flags): - if self._Test('CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS', - 'YES', default='NO'): - flags.append('-Wobjc-missing-property-synthesis') - - def GetCflagsObjC(self, configname): - """Returns flags that need to be added to .m compilations.""" - self.configname = configname - cflags_objc = [] - self._AddObjectiveCGarbageCollectionFlags(cflags_objc) - self._AddObjectiveCARCFlags(cflags_objc) - self._AddObjectiveCMissingPropertySynthesisFlags(cflags_objc) - self.configname = None - return cflags_objc - - def GetCflagsObjCC(self, configname): - """Returns flags that need to be added to .mm compilations.""" - self.configname = configname - cflags_objcc = [] - self._AddObjectiveCGarbageCollectionFlags(cflags_objcc) - self._AddObjectiveCARCFlags(cflags_objcc) - self._AddObjectiveCMissingPropertySynthesisFlags(cflags_objcc) - if self._Test('GCC_OBJC_CALL_CXX_CDTORS', 'YES', default='NO'): - cflags_objcc.append('-fobjc-call-cxx-cdtors') - self.configname = None - return cflags_objcc - - def GetInstallNameBase(self): - """Return DYLIB_INSTALL_NAME_BASE for this target.""" - # Xcode sets this for shared_libraries, and for nonbundled loadable_modules. - if (self.spec['type'] != 'shared_library' and - (self.spec['type'] != 'loadable_module' or self._IsBundle())): - return None - install_base = self.GetPerTargetSetting( - 'DYLIB_INSTALL_NAME_BASE', - default='/Library/Frameworks' if self._IsBundle() else '/usr/local/lib') - return install_base - - def _StandardizePath(self, path): - """Do :standardizepath processing for path.""" - # I'm not quite sure what :standardizepath does. Just call normpath(), - # but don't let @executable_path/../foo collapse to foo. - if '/' in path: - prefix, rest = '', path - if path.startswith('@'): - prefix, rest = path.split('/', 1) - rest = os.path.normpath(rest) # :standardizepath - path = os.path.join(prefix, rest) - return path - - def GetInstallName(self): - """Return LD_DYLIB_INSTALL_NAME for this target.""" - # Xcode sets this for shared_libraries, and for nonbundled loadable_modules. - if (self.spec['type'] != 'shared_library' and - (self.spec['type'] != 'loadable_module' or self._IsBundle())): - return None - - default_install_name = \ - '$(DYLIB_INSTALL_NAME_BASE:standardizepath)/$(EXECUTABLE_PATH)' - install_name = self.GetPerTargetSetting( - 'LD_DYLIB_INSTALL_NAME', default=default_install_name) - - # Hardcode support for the variables used in chromium for now, to - # unblock people using the make build. - if '$' in install_name: - assert install_name in ('$(DYLIB_INSTALL_NAME_BASE:standardizepath)/' - '$(WRAPPER_NAME)/$(PRODUCT_NAME)', default_install_name), ( - 'Variables in LD_DYLIB_INSTALL_NAME are not generally supported ' - 'yet in target \'%s\' (got \'%s\')' % - (self.spec['target_name'], install_name)) - - install_name = install_name.replace( - '$(DYLIB_INSTALL_NAME_BASE:standardizepath)', - self._StandardizePath(self.GetInstallNameBase())) - if self._IsBundle(): - # These are only valid for bundles, hence the |if|. - install_name = install_name.replace( - '$(WRAPPER_NAME)', self.GetWrapperName()) - install_name = install_name.replace( - '$(PRODUCT_NAME)', self.GetProductName()) - else: - assert '$(WRAPPER_NAME)' not in install_name - assert '$(PRODUCT_NAME)' not in install_name - - install_name = install_name.replace( - '$(EXECUTABLE_PATH)', self.GetExecutablePath()) - return install_name - - def _MapLinkerFlagFilename(self, ldflag, gyp_to_build_path): - """Checks if ldflag contains a filename and if so remaps it from - gyp-directory-relative to build-directory-relative.""" - # This list is expanded on demand. - # They get matched as: - # -exported_symbols_list file - # -Wl,exported_symbols_list file - # -Wl,exported_symbols_list,file - LINKER_FILE = r'(\S+)' - WORD = r'\S+' - linker_flags = [ - ['-exported_symbols_list', LINKER_FILE], # Needed for NaCl. - ['-unexported_symbols_list', LINKER_FILE], - ['-reexported_symbols_list', LINKER_FILE], - ['-sectcreate', WORD, WORD, LINKER_FILE], # Needed for remoting. - ] - for flag_pattern in linker_flags: - regex = re.compile('(?:-Wl,)?' + '[ ,]'.join(flag_pattern)) - m = regex.match(ldflag) - if m: - ldflag = ldflag[:m.start(1)] + gyp_to_build_path(m.group(1)) + \ - ldflag[m.end(1):] - # Required for ffmpeg (no idea why they don't use LIBRARY_SEARCH_PATHS, - # TODO(thakis): Update ffmpeg.gyp): - if ldflag.startswith('-L'): - ldflag = '-L' + gyp_to_build_path(ldflag[len('-L'):]) - return ldflag - - def GetLdflags(self, configname, product_dir, gyp_to_build_path, arch=None): - """Returns flags that need to be passed to the linker. - - Args: - configname: The name of the configuration to get ld flags for. - product_dir: The directory where products such static and dynamic - libraries are placed. This is added to the library search path. - gyp_to_build_path: A function that converts paths relative to the - current gyp file to paths relative to the build direcotry. - """ - self.configname = configname - ldflags = [] - - # The xcode build is relative to a gyp file's directory, and OTHER_LDFLAGS - # can contain entries that depend on this. Explicitly absolutify these. - for ldflag in self._Settings().get('OTHER_LDFLAGS', []): - ldflags.append(self._MapLinkerFlagFilename(ldflag, gyp_to_build_path)) - - if self._Test('DEAD_CODE_STRIPPING', 'YES', default='NO'): - ldflags.append('-Wl,-dead_strip') - - if self._Test('PREBINDING', 'YES', default='NO'): - ldflags.append('-Wl,-prebind') - - self._Appendf( - ldflags, 'DYLIB_COMPATIBILITY_VERSION', '-compatibility_version %s') - self._Appendf( - ldflags, 'DYLIB_CURRENT_VERSION', '-current_version %s') - - self._AppendPlatformVersionMinFlags(ldflags) - - if 'SDKROOT' in self._Settings() and self._SdkPath(): - ldflags.append('-isysroot ' + self._SdkPath()) - - for library_path in self._Settings().get('LIBRARY_SEARCH_PATHS', []): - ldflags.append('-L' + gyp_to_build_path(library_path)) - - if 'ORDER_FILE' in self._Settings(): - ldflags.append('-Wl,-order_file ' + - '-Wl,' + gyp_to_build_path( - self._Settings()['ORDER_FILE'])) - - if arch is not None: - archs = [arch] - else: - assert self.configname - archs = self.GetActiveArchs(self.configname) - if len(archs) != 1: - # TODO: Supporting fat binaries will be annoying. - self._WarnUnimplemented('ARCHS') - archs = ['i386'] - ldflags.append('-arch ' + archs[0]) - - # Xcode adds the product directory by default. - ldflags.append('-L' + product_dir) - - install_name = self.GetInstallName() - if install_name and self.spec['type'] != 'loadable_module': - ldflags.append('-install_name ' + install_name.replace(' ', r'\ ')) - - for rpath in self._Settings().get('LD_RUNPATH_SEARCH_PATHS', []): - ldflags.append('-Wl,-rpath,' + rpath) - - 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)) - - if self._IsXCTest(): - platform_root = self._XcodePlatformPath(configname) - if platform_root: - cflags.append('-F' + platform_root + '/Developer/Library/Frameworks/') - - is_extension = self._IsIosAppExtension() or self._IsIosWatchKitExtension() - if sdk_root and is_extension: - # Adds the link flags for extensions. These flags are common for all - # extensions and provide loader and main function. - # These flags reflect the compilation options used by xcode to compile - # extensions. - ldflags.append('-lpkstart') - if XcodeVersion() < '0900': - ldflags.append(sdk_root + - '/System/Library/PrivateFrameworks/PlugInKit.framework/PlugInKit') - ldflags.append('-fapplication-extension') - ldflags.append('-Xlinker -rpath ' - '-Xlinker @executable_path/../../Frameworks') - - self._Appendf(ldflags, 'CLANG_CXX_LIBRARY', '-stdlib=%s') - - self.configname = None - return ldflags - - def GetLibtoolflags(self, configname): - """Returns flags that need to be passed to the static linker. - - Args: - configname: The name of the configuration to get ld flags for. - """ - self.configname = configname - libtoolflags = [] - - for libtoolflag in self._Settings().get('OTHER_LDFLAGS', []): - libtoolflags.append(libtoolflag) - # TODO(thakis): ARCHS? - - self.configname = None - return libtoolflags - - def GetPerTargetSettings(self): - """Gets a list of all the per-target settings. This will only fetch keys - whose values are the same across all configurations.""" - first_pass = True - result = {} - for configname in sorted(self.xcode_settings.keys()): - if first_pass: - result = dict(self.xcode_settings[configname]) - first_pass = False - else: - for key, value in self.xcode_settings[configname].iteritems(): - if key not in result: - continue - elif result[key] != value: - del result[key] - return result - - def GetPerConfigSetting(self, setting, configname, default=None): - if configname in self.xcode_settings: - return self.xcode_settings[configname].get(setting, default) - else: - return self.GetPerTargetSetting(setting, default) - - def GetPerTargetSetting(self, setting, default=None): - """Tries to get xcode_settings.setting from spec. Assumes that the setting - has the same value in all configurations and throws otherwise.""" - is_first_pass = True - result = None - for configname in sorted(self.xcode_settings.keys()): - if is_first_pass: - result = self.xcode_settings[configname].get(setting, None) - is_first_pass = False - else: - assert result == self.xcode_settings[configname].get(setting, None), ( - "Expected per-target setting for '%s', got per-config setting " - "(target %s)" % (setting, self.spec['target_name'])) - if result is None: - return default - return result - - def _GetStripPostbuilds(self, configname, output_binary, quiet): - """Returns a list of shell commands that contain the shell commands - neccessary to strip this target's binary. These should be run as postbuilds - before the actual postbuilds run.""" - self.configname = configname - - result = [] - if (self._Test('DEPLOYMENT_POSTPROCESSING', 'YES', default='NO') and - self._Test('STRIP_INSTALLED_PRODUCT', 'YES', default='NO')): - - default_strip_style = 'debugging' - if self.spec['type'] == 'loadable_module' and self._IsBundle(): - default_strip_style = 'non-global' - elif self.spec['type'] == 'executable': - default_strip_style = 'all' - - strip_style = self._Settings().get('STRIP_STYLE', default_strip_style) - strip_flags = { - 'all': '', - 'non-global': '-x', - 'debugging': '-S', - }[strip_style] - - explicit_strip_flags = self._Settings().get('STRIPFLAGS', '') - if explicit_strip_flags: - strip_flags += ' ' + _NormalizeEnvVarReferences(explicit_strip_flags) - - if not quiet: - result.append('echo STRIP\\(%s\\)' % self.spec['target_name']) - result.append('strip %s %s' % (strip_flags, output_binary)) - - self.configname = None - return result - - def _GetDebugInfoPostbuilds(self, configname, output, output_binary, quiet): - """Returns a list of shell commands that contain the shell commands - neccessary to massage this target's debug information. These should be run - as postbuilds before the actual postbuilds run.""" - self.configname = configname - - # For static libraries, no dSYMs are created. - result = [] - if (self._Test('GCC_GENERATE_DEBUGGING_SYMBOLS', 'YES', default='YES') and - self._Test( - 'DEBUG_INFORMATION_FORMAT', 'dwarf-with-dsym', default='dwarf') and - self.spec['type'] != 'static_library'): - if not quiet: - result.append('echo DSYMUTIL\\(%s\\)' % self.spec['target_name']) - result.append('dsymutil %s -o %s' % (output_binary, output + '.dSYM')) - - self.configname = None - return result - - def _GetTargetPostbuilds(self, configname, output, output_binary, - quiet=False): - """Returns a list of shell commands that contain the shell commands - to run as postbuilds for this target, before the actual postbuilds.""" - # dSYMs need to build before stripping happens. - return ( - self._GetDebugInfoPostbuilds(configname, output, output_binary, quiet) + - self._GetStripPostbuilds(configname, output_binary, quiet)) - - def _GetIOSPostbuilds(self, configname, output_binary): - """Return a shell command to codesign the iOS output binary so it can - be deployed to a device. This should be run as the very last step of the - build.""" - if not (self.isIOS and self.spec['type'] == 'executable'): - return [] - - 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: - 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): - """Returns a list of shell commands that should run before and after - |postbuilds|.""" - assert output_binary is not None - pre = self._GetTargetPostbuilds(configname, output, output_binary, quiet) - post = self._GetIOSPostbuilds(configname, output_binary) - return pre + postbuilds + post - - def _AdjustLibrary(self, library, config_name=None): - if library.endswith('.framework'): - l = '-framework ' + os.path.splitext(os.path.basename(library))[0] - else: - m = self.library_re.match(library) - if m: - l = '-l' + m.group(1) - else: - l = library - - sdk_root = self._SdkPath(config_name) - if not sdk_root: - sdk_root = '' - # Xcode 7 started shipping with ".tbd" (text based stubs) files instead of - # ".dylib" without providing a real support for them. What it does, for - # "/usr/lib" libraries, is do "-L/usr/lib -lname" which is dependent on the - # library order and cause collision when building Chrome. - # - # Instead substitude ".tbd" to ".dylib" in the generated project when the - # following conditions are both true: - # - library is referenced in the gyp file as "$(SDKROOT)/**/*.dylib", - # - the ".dylib" file does not exists but a ".tbd" file do. - library = l.replace('$(SDKROOT)', sdk_root) - if l.startswith('$(SDKROOT)'): - basename, ext = os.path.splitext(library) - if ext == '.dylib' and not os.path.exists(library): - tbd_library = basename + '.tbd' - if os.path.exists(tbd_library): - library = tbd_library - return library - - def AdjustLibraries(self, libraries, config_name=None): - """Transforms entries like 'Cocoa.framework' in libraries into entries like - '-framework Cocoa', 'libcrypto.dylib' into '-lcrypto', etc. - """ - libraries = [self._AdjustLibrary(library, config_name) - for library in libraries] - return libraries - - def _BuildMachineOSBuild(self): - return GetStdout(['sw_vers', '-buildVersion']) - - def _XcodeIOSDeviceFamily(self, configname): - family = self.xcode_settings[configname].get('TARGETED_DEVICE_FAMILY', '1') - return [int(x) for x in family.split(',')] - - def GetExtraPlistItems(self, configname=None): - """Returns a dictionary with extra items to insert into Info.plist.""" - if configname not in XcodeSettings._plist_cache: - cache = {} - cache['BuildMachineOSBuild'] = self._BuildMachineOSBuild() - - xcode, xcode_build = XcodeVersion() - cache['DTXcode'] = xcode - 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( - sdk_root, 'ProductBuildVersion') - else: - cache['DTSDKBuild'] = cache['BuildMachineOSBuild'] - - if self.isIOS: - cache['DTPlatformName'] = cache['DTSDKName'] - if configname.endswith("iphoneos"): - cache['DTPlatformVersion'] = self._GetSdkVersionInfoItem( - sdk_root, 'ProductVersion') - cache['CFBundleSupportedPlatforms'] = ['iPhoneOS'] - else: - cache['CFBundleSupportedPlatforms'] = ['iPhoneSimulator'] - XcodeSettings._plist_cache[configname] = cache - - # Include extra plist items that are per-target, not per global - # XcodeSettings. - items = dict(XcodeSettings._plist_cache[configname]) - if self.isIOS: - 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. - """ - xcode_version, xcode_build = XcodeVersion() - if xcode_version < '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 = 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 '' - - -class MacPrefixHeader(object): - """A class that helps with emulating Xcode's GCC_PREFIX_HEADER feature. - - This feature consists of several pieces: - * If GCC_PREFIX_HEADER is present, all compilations in that project get an - additional |-include path_to_prefix_header| cflag. - * If GCC_PRECOMPILE_PREFIX_HEADER is present too, then the prefix header is - instead compiled, and all other compilations in the project get an - additional |-include path_to_compiled_header| instead. - + Compiled prefix headers have the extension gch. There is one gch file for - every language used in the project (c, cc, m, mm), since gch files for - different languages aren't compatible. - + gch files themselves are built with the target's normal cflags, but they - obviously don't get the |-include| flag. Instead, they need a -x flag that - describes their language. - + All o files in the target need to depend on the gch file, to make sure - it's built before any o file is built. - - This class helps with some of these tasks, but it needs help from the build - system for writing dependencies to the gch files, for writing build commands - for the gch files, and for figuring out the location of the gch files. - """ - def __init__(self, xcode_settings, - gyp_path_to_build_path, gyp_path_to_build_output): - """If xcode_settings is None, all methods on this class are no-ops. - - Args: - gyp_path_to_build_path: A function that takes a gyp-relative path, - and returns a path relative to the build directory. - gyp_path_to_build_output: A function that takes a gyp-relative path and - a language code ('c', 'cc', 'm', or 'mm'), and that returns a path - to where the output of precompiling that path for that language - should be placed (without the trailing '.gch'). - """ - # This doesn't support per-configuration prefix headers. Good enough - # for now. - self.header = None - self.compile_headers = False - if xcode_settings: - self.header = xcode_settings.GetPerTargetSetting('GCC_PREFIX_HEADER') - self.compile_headers = xcode_settings.GetPerTargetSetting( - 'GCC_PRECOMPILE_PREFIX_HEADER', default='NO') != 'NO' - self.compiled_headers = {} - if self.header: - if self.compile_headers: - for lang in ['c', 'cc', 'm', 'mm']: - self.compiled_headers[lang] = gyp_path_to_build_output( - self.header, lang) - self.header = gyp_path_to_build_path(self.header) - - def _CompiledHeader(self, lang, arch): - assert self.compile_headers - h = self.compiled_headers[lang] - if arch: - h += '.' + arch - return h - - def GetInclude(self, lang, arch=None): - """Gets the cflags to include the prefix header for language |lang|.""" - if self.compile_headers and lang in self.compiled_headers: - return '-include %s' % self._CompiledHeader(lang, arch) - elif self.header: - return '-include %s' % self.header - else: - return '' - - def _Gch(self, lang, arch): - """Returns the actual file name of the prefix header for language |lang|.""" - assert self.compile_headers - return self._CompiledHeader(lang, arch) + '.gch' - - def GetObjDependencies(self, sources, objs, arch=None): - """Given a list of source files and the corresponding object files, returns - a list of (source, object, gch) tuples, where |gch| is the build-directory - relative path to the gch file each object file depends on. |compilable[i]| - has to be the source file belonging to |objs[i]|.""" - if not self.header or not self.compile_headers: - return [] - - result = [] - for source, obj in zip(sources, objs): - ext = os.path.splitext(source)[1] - lang = { - '.c': 'c', - '.cpp': 'cc', '.cc': 'cc', '.cxx': 'cc', - '.m': 'm', - '.mm': 'mm', - }.get(ext, None) - if lang: - result.append((source, obj, self._Gch(lang, arch))) - return result - - def GetPchBuildCommands(self, arch=None): - """Returns [(path_to_gch, language_flag, language, header)]. - |path_to_gch| and |header| are relative to the build directory. - """ - if not self.header or not self.compile_headers: - return [] - return [ - (self._Gch('c', arch), '-x c-header', 'c', self.header), - (self._Gch('cc', arch), '-x c++-header', 'cc', self.header), - (self._Gch('m', arch), '-x objective-c-header', 'm', self.header), - (self._Gch('mm', arch), '-x objective-c++-header', 'mm', self.header), - ] - - -def XcodeVersion(): - """Returns a tuple of version and build version of installed Xcode.""" - # `xcodebuild -version` output looks like - # Xcode 4.6.3 - # Build version 4H1503 - # or like - # Xcode 3.2.6 - # Component versions: DevToolsCore-1809.0; DevToolsSupport-1806.0 - # BuildVersion: 10M2518 - # Convert that to '0463', '4H1503'. - global XCODE_VERSION_CACHE - if XCODE_VERSION_CACHE: - return XCODE_VERSION_CACHE - try: - version_list = GetStdoutQuiet(['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 = CLTVersion() - if version: - version = re.match(r'(\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] - XCODE_VERSION_CACHE = (version, build) - return XCODE_VERSION_CACHE - - -# This function ported from the logic in Homebrew's CLT version check -def CLTVersion(): - """Returns the version of command-line tools from pkgutil.""" - # 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.+)') - for key in [MAVERICKS_PKG_ID, STANDALONE_PKG_ID, FROM_XCODE_PKG_ID]: - try: - output = GetStdout(['/usr/sbin/pkgutil', '--pkg-info', key]) - return re.search(regex, output).groupdict()['version'] - except: - continue - - -def GetStdoutQuiet(cmdlist): - """Returns the content of standard output returned by invoking |cmdlist|. - Ignores the stderr. - Raises |GypError| if the command return with a non-zero return code.""" - job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - out = job.communicate()[0] - if job.returncode != 0: - raise GypError('Error %d running %s' % (job.returncode, cmdlist[0])) - return out.rstrip('\n') - - -def GetStdout(cmdlist): - """Returns the content of standard output returned by invoking |cmdlist|. - Raises |GypError| if the command return with a non-zero return code.""" - job = subprocess.Popen(cmdlist, stdout=subprocess.PIPE) - out = job.communicate()[0] - if job.returncode != 0: - sys.stderr.write(out + '\n') - raise GypError('Error %d running %s' % (job.returncode, cmdlist[0])) - return out.rstrip('\n') - - -def MergeGlobalXcodeSettingsToSpec(global_dict, spec): - """Merges the global xcode_settings dictionary into each configuration of the - target represented by spec. For keys that are both in the global and the local - xcode_settings dict, the local key gets precendence. - """ - # The xcode generator special-cases global xcode_settings and does something - # that amounts to merging in the global xcode_settings into each local - # xcode_settings dict. - global_xcode_settings = global_dict.get('xcode_settings', {}) - for config in spec['configurations'].values(): - if 'xcode_settings' in config: - new_settings = global_xcode_settings.copy() - new_settings.update(config['xcode_settings']) - config['xcode_settings'] = new_settings - - -def IsMacBundle(flavor, spec): - """Returns if |spec| should be treated as a bundle. - - Bundles are directories with a certain subdirectory structure, instead of - just a single file. Bundle rules do not produce a binary but also package - resources into that directory.""" - is_mac_bundle = (int(spec.get('mac_bundle', 0)) != 0 and flavor == 'mac') - if is_mac_bundle: - assert spec['type'] != 'none', ( - 'mac_bundle targets cannot have type none (target "%s")' % - spec['target_name']) - return is_mac_bundle - - -def GetMacBundleResources(product_dir, xcode_settings, resources): - """Yields (output, resource) pairs for every resource in |resources|. - Only call this for mac bundle targets. - - Args: - product_dir: Path to the directory containing the output bundle, - relative to the build directory. - xcode_settings: The XcodeSettings of the current target. - resources: A list of bundle resources, relative to the build directory. - """ - dest = os.path.join(product_dir, - xcode_settings.GetBundleResourceFolder()) - for res in resources: - output = dest - - # The make generator doesn't support it, so forbid it everywhere - # to keep the generators more interchangable. - assert ' ' not in res, ( - "Spaces in resource filenames not supported (%s)" % res) - - # Split into (path,file). - res_parts = os.path.split(res) - - # Now split the path into (prefix,maybe.lproj). - lproj_parts = os.path.split(res_parts[0]) - # If the resource lives in a .lproj bundle, add that to the destination. - if lproj_parts[1].endswith('.lproj'): - output = os.path.join(output, lproj_parts[1]) - - output = os.path.join(output, res_parts[1]) - # Compiled XIB files are referred to by .nib. - if output.endswith('.xib'): - output = os.path.splitext(output)[0] + '.nib' - # Compiled storyboard files are referred to by .storyboardc. - if output.endswith('.storyboard'): - output = os.path.splitext(output)[0] + '.storyboardc' - - yield output, res - - -def GetMacInfoPlist(product_dir, xcode_settings, gyp_path_to_build_path): - """Returns (info_plist, dest_plist, defines, extra_env), where: - * |info_plist| is the source plist path, relative to the - build directory, - * |dest_plist| is the destination plist path, relative to the - build directory, - * |defines| is a list of preprocessor defines (empty if the plist - shouldn't be preprocessed, - * |extra_env| is a dict of env variables that should be exported when - invoking |mac_tool copy-info-plist|. - - Only call this for mac bundle targets. - - Args: - product_dir: Path to the directory containing the output bundle, - relative to the build directory. - xcode_settings: The XcodeSettings of the current target. - gyp_to_build_path: A function that converts paths relative to the - current gyp file to paths relative to the build direcotry. - """ - info_plist = xcode_settings.GetPerTargetSetting('INFOPLIST_FILE') - if not info_plist: - return None, None, [], {} - - # The make generator doesn't support it, so forbid it everywhere - # to keep the generators more interchangable. - assert ' ' not in info_plist, ( - "Spaces in Info.plist filenames not supported (%s)" % info_plist) - - info_plist = gyp_path_to_build_path(info_plist) - - # If explicitly set to preprocess the plist, invoke the C preprocessor and - # specify any defines as -D flags. - if xcode_settings.GetPerTargetSetting( - 'INFOPLIST_PREPROCESS', default='NO') == 'YES': - # Create an intermediate file based on the path. - defines = shlex.split(xcode_settings.GetPerTargetSetting( - 'INFOPLIST_PREPROCESSOR_DEFINITIONS', default='')) - else: - defines = [] - - dest_plist = os.path.join(product_dir, xcode_settings.GetBundlePlistPath()) - extra_env = xcode_settings.GetPerTargetSettings() - - return info_plist, dest_plist, defines, extra_env - - -def _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, - additional_settings=None): - """Return the environment variables that Xcode would set. See - http://developer.apple.com/library/mac/#documentation/DeveloperTools/Reference/XcodeBuildSettingRef/1-Build_Setting_Reference/build_setting_ref.html#//apple_ref/doc/uid/TP40003931-CH3-SW153 - for a full list. - - Args: - xcode_settings: An XcodeSettings object. If this is None, this function - returns an empty dict. - built_products_dir: Absolute path to the built products dir. - srcroot: Absolute path to the source root. - configuration: The build configuration name. - additional_settings: An optional dict with more values to add to the - result. - """ - if not xcode_settings: return {} - - # This function is considered a friend of XcodeSettings, so let it reach into - # its implementation details. - spec = xcode_settings.spec - - # These are filled in on a as-needed basis. - env = { - 'BUILT_FRAMEWORKS_DIR' : built_products_dir, - 'BUILT_PRODUCTS_DIR' : built_products_dir, - 'CONFIGURATION' : configuration, - 'PRODUCT_NAME' : xcode_settings.GetProductName(), - # See /Developer/Platforms/MacOSX.platform/Developer/Library/Xcode/Specifications/MacOSX\ Product\ Types.xcspec for FULL_PRODUCT_NAME - 'SRCROOT' : srcroot, - 'SOURCE_ROOT': '${SRCROOT}', - # This is not true for static libraries, but currently the env is only - # written for bundles: - 'TARGET_BUILD_DIR' : built_products_dir, - 'TEMP_DIR' : '${TMPDIR}', - } - if xcode_settings.GetPerConfigSetting('SDKROOT', configuration): - env['SDKROOT'] = xcode_settings._SdkPath(configuration) - else: - env['SDKROOT'] = '' - - if spec['type'] in ( - 'executable', 'static_library', 'shared_library', 'loadable_module'): - env['EXECUTABLE_NAME'] = xcode_settings.GetExecutableName() - env['EXECUTABLE_PATH'] = xcode_settings.GetExecutablePath() - env['FULL_PRODUCT_NAME'] = xcode_settings.GetFullProductName() - mach_o_type = xcode_settings.GetMachOType() - if mach_o_type: - env['MACH_O_TYPE'] = mach_o_type - env['PRODUCT_TYPE'] = xcode_settings.GetProductType() - if xcode_settings._IsBundle(): - env['CONTENTS_FOLDER_PATH'] = \ - xcode_settings.GetBundleContentsFolderPath() - env['UNLOCALIZED_RESOURCES_FOLDER_PATH'] = \ - xcode_settings.GetBundleResourceFolder() - env['INFOPLIST_PATH'] = xcode_settings.GetBundlePlistPath() - env['WRAPPER_NAME'] = xcode_settings.GetWrapperName() - - install_name = xcode_settings.GetInstallName() - if install_name: - env['LD_DYLIB_INSTALL_NAME'] = install_name - install_name_base = xcode_settings.GetInstallNameBase() - if install_name_base: - env['DYLIB_INSTALL_NAME_BASE'] = install_name_base - if XcodeVersion() >= '0500' and not env.get('SDKROOT'): - sdk_root = xcode_settings._SdkRoot(configuration) - if not sdk_root: - sdk_root = xcode_settings._XcodeSdkPath('') - if sdk_root is None: - sdk_root = '' - env['SDKROOT'] = sdk_root - - if not additional_settings: - additional_settings = {} - else: - # Flatten lists to strings. - for k in additional_settings: - if not isinstance(additional_settings[k], str): - additional_settings[k] = ' '.join(additional_settings[k]) - additional_settings.update(env) - - for k in additional_settings: - additional_settings[k] = _NormalizeEnvVarReferences(additional_settings[k]) - - return additional_settings - - -def _NormalizeEnvVarReferences(str): - """Takes a string containing variable references in the form ${FOO}, $(FOO), - or $FOO, and returns a string with all variable references in the form ${FOO}. - """ - # $FOO -> ${FOO} - str = re.sub(r'\$([a-zA-Z_][a-zA-Z0-9_]*)', r'${\1}', str) - - # $(FOO) -> ${FOO} - matches = re.findall(r'(\$\(([a-zA-Z0-9\-_]+)\))', str) - for match in matches: - to_replace, variable = match - assert '$(' not in match, '$($(FOO)) variables not supported: ' + match - str = str.replace(to_replace, '${' + variable + '}') - - return str - - -def ExpandEnvVars(string, expansions): - """Expands ${VARIABLES}, $(VARIABLES), and $VARIABLES in string per the - expansions list. If the variable expands to something that references - another variable, this variable is expanded as well if it's in env -- - until no variables present in env are left.""" - for k, v in reversed(expansions): - string = string.replace('${' + k + '}', v) - string = string.replace('$(' + k + ')', v) - string = string.replace('$' + k, v) - return string - - -def _TopologicallySortedEnvVarKeys(env): - """Takes a dict |env| whose values are strings that can refer to other keys, - for example env['foo'] = '$(bar) and $(baz)'. Returns a list L of all keys of - env such that key2 is after key1 in L if env[key2] refers to env[key1]. - - Throws an Exception in case of dependency cycles. - """ - # Since environment variables can refer to other variables, the evaluation - # order is important. Below is the logic to compute the dependency graph - # and sort it. - regex = re.compile(r'\$\{([a-zA-Z0-9\-_]+)\}') - def GetEdges(node): - # Use a definition of edges such that user_of_variable -> used_varible. - # This happens to be easier in this case, since a variable's - # definition contains all variables it references in a single string. - # We can then reverse the result of the topological sort at the end. - # Since: reverse(topsort(DAG)) = topsort(reverse_edges(DAG)) - matches = set([v for v in regex.findall(env[node]) if v in env]) - for dependee in matches: - assert '${' not in dependee, 'Nested variables not supported: ' + dependee - return matches - - try: - # Topologically sort, and then reverse, because we used an edge definition - # that's inverted from the expected result of this function (see comment - # above). - order = gyp.common.TopologicallySorted(env.keys(), GetEdges) - order.reverse() - return order - except gyp.common.CycleError, e: - raise GypError( - 'Xcode environment variables are cyclically dependent: ' + str(e.nodes)) - - -def GetSortedXcodeEnv(xcode_settings, built_products_dir, srcroot, - configuration, additional_settings=None): - env = _GetXcodeEnv(xcode_settings, built_products_dir, srcroot, configuration, - additional_settings) - return [(key, env[key]) for key in _TopologicallySortedEnvVarKeys(env)] - - -def GetSpecPostbuildCommands(spec, quiet=False): - """Returns the list of postbuilds explicitly defined on |spec|, in a form - executable by a shell.""" - postbuilds = [] - for postbuild in spec.get('postbuilds', []): - if not quiet: - postbuilds.append('echo POSTBUILD\\(%s\\) %s' % ( - spec['target_name'], postbuild['postbuild_name'])) - postbuilds.append(gyp.common.EncodePOSIXShellList(postbuild['action'])) - return postbuilds - - -def _HasIOSTarget(targets): - """Returns true if any target contains the iOS specific key - IPHONEOS_DEPLOYMENT_TARGET.""" - for target_dict in targets.values(): - for config in target_dict['configurations'].values(): - if config.get('xcode_settings', {}).get('IPHONEOS_DEPLOYMENT_TARGET'): - return True - return False - - -def _AddIOSDeviceConfigurations(targets): - """Clone all targets and append -iphoneos to the name. Configure these targets - to build for iOS devices and use correct architectures for those builds.""" - for target_dict in targets.itervalues(): - toolset = target_dict['toolset'] - configs = target_dict['configurations'] - for config_name, config_dict in dict(configs).iteritems(): - iphoneos_config_dict = copy.deepcopy(config_dict) - configs[config_name + '-iphoneos'] = iphoneos_config_dict - configs[config_name + '-iphonesimulator'] = config_dict - if toolset == 'target': - iphoneos_config_dict['xcode_settings']['SDKROOT'] = 'iphoneos' - return targets - -def CloneConfigurationForDeviceAndEmulator(target_dicts): - """If |target_dicts| contains any iOS targets, automatically create -iphoneos - targets for iOS device builds.""" - if _HasIOSTarget(target_dicts): - return _AddIOSDeviceConfigurations(target_dicts) - return target_dicts diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py deleted file mode 100644 index 3820d6bf04817..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcode_ninja.py +++ /dev/null @@ -1,270 +0,0 @@ -# Copyright (c) 2014 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. - -"""Xcode-ninja wrapper project file generator. - -This updates the data structures passed to the Xcode gyp generator to build -with ninja instead. The Xcode project itself is transformed into a list of -executable targets, each with a build step to build with ninja, and a target -with every source and resource file. This appears to sidestep some of the -major performance headaches experienced using complex projects and large number -of targets within Xcode. -""" - -import errno -import gyp.generator.ninja -import os -import re -import xml.sax.saxutils - - -def _WriteWorkspace(main_gyp, sources_gyp, params): - """ Create a workspace to wrap main and sources gyp paths. """ - (build_file_root, build_file_ext) = os.path.splitext(main_gyp) - workspace_path = build_file_root + '.xcworkspace' - options = params['options'] - if options.generator_output: - workspace_path = os.path.join(options.generator_output, workspace_path) - try: - os.makedirs(workspace_path) - except OSError, e: - if e.errno != errno.EEXIST: - raise - output_string = '\n' + \ - '\n' - for gyp_name in [main_gyp, sources_gyp]: - name = os.path.splitext(os.path.basename(gyp_name))[0] + '.xcodeproj' - name = xml.sax.saxutils.quoteattr("group:" + name) - output_string += ' \n' % name - output_string += '\n' - - workspace_file = os.path.join(workspace_path, "contents.xcworkspacedata") - - try: - with open(workspace_file, 'r') as input_file: - input_string = input_file.read() - if input_string == output_string: - return - except IOError: - # Ignore errors if the file doesn't exist. - pass - - with open(workspace_file, 'w') as output_file: - output_file.write(output_string) - -def _TargetFromSpec(old_spec, params): - """ Create fake target for xcode-ninja wrapper. """ - # Determine ninja top level build dir (e.g. /path/to/out). - ninja_toplevel = None - jobs = 0 - if params: - options = params['options'] - ninja_toplevel = \ - os.path.join(options.toplevel_dir, - gyp.generator.ninja.ComputeOutputDir(params)) - jobs = params.get('generator_flags', {}).get('xcode_ninja_jobs', 0) - - target_name = old_spec.get('target_name') - product_name = old_spec.get('product_name', target_name) - product_extension = old_spec.get('product_extension') - - ninja_target = {} - ninja_target['target_name'] = target_name - ninja_target['product_name'] = product_name - if product_extension: - ninja_target['product_extension'] = product_extension - ninja_target['toolset'] = old_spec.get('toolset') - ninja_target['default_configuration'] = old_spec.get('default_configuration') - ninja_target['configurations'] = {} - - # Tell Xcode to look in |ninja_toplevel| for build products. - new_xcode_settings = {} - if ninja_toplevel: - new_xcode_settings['CONFIGURATION_BUILD_DIR'] = \ - "%s/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)" % ninja_toplevel - - if 'configurations' in old_spec: - for config in old_spec['configurations'].iterkeys(): - old_xcode_settings = \ - old_spec['configurations'][config].get('xcode_settings', {}) - if 'IPHONEOS_DEPLOYMENT_TARGET' in old_xcode_settings: - new_xcode_settings['CODE_SIGNING_REQUIRED'] = "NO" - new_xcode_settings['IPHONEOS_DEPLOYMENT_TARGET'] = \ - old_xcode_settings['IPHONEOS_DEPLOYMENT_TARGET'] - ninja_target['configurations'][config] = {} - ninja_target['configurations'][config]['xcode_settings'] = \ - new_xcode_settings - - ninja_target['mac_bundle'] = old_spec.get('mac_bundle', 0) - ninja_target['ios_app_extension'] = old_spec.get('ios_app_extension', 0) - ninja_target['ios_watchkit_extension'] = \ - old_spec.get('ios_watchkit_extension', 0) - ninja_target['ios_watchkit_app'] = old_spec.get('ios_watchkit_app', 0) - ninja_target['type'] = old_spec['type'] - if ninja_toplevel: - ninja_target['actions'] = [ - { - 'action_name': 'Compile and copy %s via ninja' % target_name, - 'inputs': [], - 'outputs': [], - 'action': [ - 'env', - 'PATH=%s' % os.environ['PATH'], - 'ninja', - '-C', - new_xcode_settings['CONFIGURATION_BUILD_DIR'], - target_name, - ], - 'message': 'Compile and copy %s via ninja' % target_name, - }, - ] - if jobs > 0: - ninja_target['actions'][0]['action'].extend(('-j', jobs)) - return ninja_target - -def IsValidTargetForWrapper(target_extras, executable_target_pattern, spec): - """Limit targets for Xcode wrapper. - - Xcode sometimes performs poorly with too many targets, so only include - proper executable targets, with filters to customize. - Arguments: - target_extras: Regular expression to always add, matching any target. - executable_target_pattern: Regular expression limiting executable targets. - spec: Specifications for target. - """ - target_name = spec.get('target_name') - # Always include targets matching target_extras. - if target_extras is not None and re.search(target_extras, target_name): - return True - - # Otherwise just show executable targets. - if spec.get('type', '') == 'executable' and \ - spec.get('product_extension', '') != 'bundle': - - # If there is a filter and the target does not match, exclude the target. - if executable_target_pattern is not None: - if not re.search(executable_target_pattern, target_name): - return False - return True - return False - -def CreateWrapper(target_list, target_dicts, data, params): - """Initialize targets for the ninja wrapper. - - This sets up the necessary variables in the targets to generate Xcode projects - that use ninja as an external builder. - Arguments: - target_list: List of target pairs: 'base/base.gyp:base'. - target_dicts: Dict of target properties keyed on target pair. - data: Dict of flattened build files keyed on gyp path. - params: Dict of global options for gyp. - """ - orig_gyp = params['build_files'][0] - for gyp_name, gyp_dict in data.iteritems(): - if gyp_name == orig_gyp: - depth = gyp_dict['_DEPTH'] - - # Check for custom main gyp name, otherwise use the default CHROMIUM_GYP_FILE - # and prepend .ninja before the .gyp extension. - generator_flags = params.get('generator_flags', {}) - main_gyp = generator_flags.get('xcode_ninja_main_gyp', None) - if main_gyp is None: - (build_file_root, build_file_ext) = os.path.splitext(orig_gyp) - main_gyp = build_file_root + ".ninja" + build_file_ext - - # Create new |target_list|, |target_dicts| and |data| data structures. - new_target_list = [] - new_target_dicts = {} - new_data = {} - - # Set base keys needed for |data|. - new_data[main_gyp] = {} - new_data[main_gyp]['included_files'] = [] - new_data[main_gyp]['targets'] = [] - new_data[main_gyp]['xcode_settings'] = \ - data[orig_gyp].get('xcode_settings', {}) - - # Normally the xcode-ninja generator includes only valid executable targets. - # If |xcode_ninja_executable_target_pattern| is set, that list is reduced to - # executable targets that match the pattern. (Default all) - executable_target_pattern = \ - generator_flags.get('xcode_ninja_executable_target_pattern', None) - - # For including other non-executable targets, add the matching target name - # to the |xcode_ninja_target_pattern| regular expression. (Default none) - target_extras = generator_flags.get('xcode_ninja_target_pattern', None) - - for old_qualified_target in target_list: - spec = target_dicts[old_qualified_target] - if IsValidTargetForWrapper(target_extras, executable_target_pattern, spec): - # Add to new_target_list. - target_name = spec.get('target_name') - new_target_name = '%s:%s#target' % (main_gyp, target_name) - new_target_list.append(new_target_name) - - # Add to new_target_dicts. - new_target_dicts[new_target_name] = _TargetFromSpec(spec, params) - - # Add to new_data. - for old_target in data[old_qualified_target.split(':')[0]]['targets']: - if old_target['target_name'] == target_name: - new_data_target = {} - new_data_target['target_name'] = old_target['target_name'] - new_data_target['toolset'] = old_target['toolset'] - new_data[main_gyp]['targets'].append(new_data_target) - - # Create sources target. - sources_target_name = 'sources_for_indexing' - sources_target = _TargetFromSpec( - { 'target_name' : sources_target_name, - 'toolset': 'target', - 'default_configuration': 'Default', - 'mac_bundle': '0', - 'type': 'executable' - }, None) - - # Tell Xcode to look everywhere for headers. - sources_target['configurations'] = {'Default': { 'include_dirs': [ depth ] } } - - sources = [] - for target, target_dict in target_dicts.iteritems(): - base = os.path.dirname(target) - files = target_dict.get('sources', []) + \ - target_dict.get('mac_bundle_resources', []) - for action in target_dict.get('actions', []): - files.extend(action.get('inputs', [])) - # Remove files starting with $. These are mostly intermediate files for the - # build system. - files = [ file for file in files if not file.startswith('$')] - - # Make sources relative to root build file. - relative_path = os.path.dirname(main_gyp) - sources += [ os.path.relpath(os.path.join(base, file), relative_path) - for file in files ] - - sources_target['sources'] = sorted(set(sources)) - - # Put sources_to_index in it's own gyp. - sources_gyp = \ - os.path.join(os.path.dirname(main_gyp), sources_target_name + ".gyp") - fully_qualified_target_name = \ - '%s:%s#target' % (sources_gyp, sources_target_name) - - # Add to new_target_list, new_target_dicts and new_data. - new_target_list.append(fully_qualified_target_name) - new_target_dicts[fully_qualified_target_name] = sources_target - new_data_target = {} - new_data_target['target_name'] = sources_target['target_name'] - new_data_target['_DEPTH'] = depth - new_data_target['toolset'] = "target" - new_data[sources_gyp] = {} - new_data[sources_gyp]['targets'] = [] - new_data[sources_gyp]['included_files'] = [] - new_data[sources_gyp]['xcode_settings'] = \ - data[orig_gyp].get('xcode_settings', {}) - new_data[sources_gyp]['targets'].append(new_data_target) - - # Write workspace to file. - _WriteWorkspace(main_gyp, sources_gyp, params) - return (new_target_list, new_target_dicts, new_data) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py deleted file mode 100644 index d08b7f777002f..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xcodeproj_file.py +++ /dev/null @@ -1,2927 +0,0 @@ -# Copyright (c) 2012 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. - -"""Xcode project file generator. - -This module is both an Xcode project file generator and a documentation of the -Xcode project file format. Knowledge of the project file format was gained -based on extensive experience with Xcode, and by making changes to projects in -Xcode.app and observing the resultant changes in the associated project files. - -XCODE PROJECT FILES - -The generator targets the file format as written by Xcode 3.2 (specifically, -3.2.6), but past experience has taught that the format has not changed -significantly in the past several years, and future versions of Xcode are able -to read older project files. - -Xcode project files are "bundled": the project "file" from an end-user's -perspective is actually a directory with an ".xcodeproj" extension. The -project file from this module's perspective is actually a file inside this -directory, always named "project.pbxproj". This file contains a complete -description of the project and is all that is needed to use the xcodeproj. -Other files contained in the xcodeproj directory are simply used to store -per-user settings, such as the state of various UI elements in the Xcode -application. - -The project.pbxproj file is a property list, stored in a format almost -identical to the NeXTstep property list format. The file is able to carry -Unicode data, and is encoded in UTF-8. The root element in the property list -is a dictionary that contains several properties of minimal interest, and two -properties of immense interest. The most important property is a dictionary -named "objects". The entire structure of the project is represented by the -children of this property. The objects dictionary is keyed by unique 96-bit -values represented by 24 uppercase hexadecimal characters. Each value in the -objects dictionary is itself a dictionary, describing an individual object. - -Each object in the dictionary is a member of a class, which is identified by -the "isa" property of each object. A variety of classes are represented in a -project file. Objects can refer to other objects by ID, using the 24-character -hexadecimal object key. A project's objects form a tree, with a root object -of class PBXProject at the root. As an example, the PBXProject object serves -as parent to an XCConfigurationList object defining the build configurations -used in the project, a PBXGroup object serving as a container for all files -referenced in the project, and a list of target objects, each of which defines -a target in the project. There are several different types of target object, -such as PBXNativeTarget and PBXAggregateTarget. In this module, this -relationship is expressed by having each target type derive from an abstract -base named XCTarget. - -The project.pbxproj file's root dictionary also contains a property, sibling to -the "objects" dictionary, named "rootObject". The value of rootObject is a -24-character object key referring to the root PBXProject object in the -objects dictionary. - -In Xcode, every file used as input to a target or produced as a final product -of a target must appear somewhere in the hierarchy rooted at the PBXGroup -object referenced by the PBXProject's mainGroup property. A PBXGroup is -generally represented as a folder in the Xcode application. PBXGroups can -contain other PBXGroups as well as PBXFileReferences, which are pointers to -actual files. - -Each XCTarget contains a list of build phases, represented in this module by -the abstract base XCBuildPhase. Examples of concrete XCBuildPhase derivations -are PBXSourcesBuildPhase and PBXFrameworksBuildPhase, which correspond to the -"Compile Sources" and "Link Binary With Libraries" phases displayed in the -Xcode application. Files used as input to these phases (for example, source -files in the former case and libraries and frameworks in the latter) are -represented by PBXBuildFile objects, referenced by elements of "files" lists -in XCTarget objects. Each PBXBuildFile object refers to a PBXBuildFile -object as a "weak" reference: it does not "own" the PBXBuildFile, which is -owned by the root object's mainGroup or a descendant group. In most cases, the -layer of indirection between an XCBuildPhase and a PBXFileReference via a -PBXBuildFile appears extraneous, but there's actually one reason for this: -file-specific compiler flags are added to the PBXBuildFile object so as to -allow a single file to be a member of multiple targets while having distinct -compiler flags for each. These flags can be modified in the Xcode applciation -in the "Build" tab of a File Info window. - -When a project is open in the Xcode application, Xcode will rewrite it. As -such, this module is careful to adhere to the formatting used by Xcode, to -avoid insignificant changes appearing in the file when it is used in the -Xcode application. This will keep version control repositories happy, and -makes it possible to compare a project file used in Xcode to one generated by -this module to determine if any significant changes were made in the -application. - -Xcode has its own way of assigning 24-character identifiers to each object, -which is not duplicated here. Because the identifier only is only generated -once, when an object is created, and is then left unchanged, there is no need -to attempt to duplicate Xcode's behavior in this area. The generator is free -to select any identifier, even at random, to refer to the objects it creates, -and Xcode will retain those identifiers and use them when subsequently -rewriting the project file. However, the generator would choose new random -identifiers each time the project files are generated, leading to difficulties -comparing "used" project files to "pristine" ones produced by this module, -and causing the appearance of changes as every object identifier is changed -when updated projects are checked in to a version control repository. To -mitigate this problem, this module chooses identifiers in a more deterministic -way, by hashing a description of each object as well as its parent and ancestor -objects. This strategy should result in minimal "shift" in IDs as successive -generations of project files are produced. - -THIS MODULE - -This module introduces several classes, all derived from the XCObject class. -Nearly all of the "brains" are built into the XCObject class, which understands -how to create and modify objects, maintain the proper tree structure, compute -identifiers, and print objects. For the most part, classes derived from -XCObject need only provide a _schema class object, a dictionary that -expresses what properties objects of the class may contain. - -Given this structure, it's possible to build a minimal project file by creating -objects of the appropriate types and making the proper connections: - - config_list = XCConfigurationList() - group = PBXGroup() - project = PBXProject({'buildConfigurationList': config_list, - 'mainGroup': group}) - -With the project object set up, it can be added to an XCProjectFile object. -XCProjectFile is a pseudo-class in the sense that it is a concrete XCObject -subclass that does not actually correspond to a class type found in a project -file. Rather, it is used to represent the project file's root dictionary. -Printing an XCProjectFile will print the entire project file, including the -full "objects" dictionary. - - project_file = XCProjectFile({'rootObject': project}) - project_file.ComputeIDs() - project_file.Print() - -Xcode project files are always encoded in UTF-8. This module will accept -strings of either the str class or the unicode class. Strings of class str -are assumed to already be encoded in UTF-8. Obviously, if you're just using -ASCII, you won't encounter difficulties because ASCII is a UTF-8 subset. -Strings of class unicode are handled properly and encoded in UTF-8 when -a project file is output. -""" - -import gyp.common -import posixpath -import re -import struct -import sys - -# hashlib is supplied as of Python 2.5 as the replacement interface for sha -# and other secure hashes. In 2.6, sha is deprecated. Import hashlib if -# available, avoiding a deprecation warning under 2.6. Import sha otherwise, -# preserving 2.4 compatibility. -try: - import hashlib - _new_sha1 = hashlib.sha1 -except ImportError: - import sha - _new_sha1 = sha.new - - -# See XCObject._EncodeString. This pattern is used to determine when a string -# can be printed unquoted. Strings that match this pattern may be printed -# unquoted. Strings that do not match must be quoted and may be further -# transformed to be properly encoded. Note that this expression matches the -# characters listed with "+", for 1 or more occurrences: if a string is empty, -# it must not match this pattern, because it needs to be encoded as "". -_unquoted = re.compile('^[A-Za-z0-9$./_]+$') - -# Strings that match this pattern are quoted regardless of what _unquoted says. -# Oddly, Xcode will quote any string with a run of three or more underscores. -_quoted = re.compile('___') - -# This pattern should match any character that needs to be escaped by -# XCObject._EncodeString. See that function. -_escaped = re.compile('[\\\\"]|[\x00-\x1f]') - - -# Used by SourceTreeAndPathFromPath -_path_leading_variable = re.compile(r'^\$\((.*?)\)(/(.*))?$') - -def SourceTreeAndPathFromPath(input_path): - """Given input_path, returns a tuple with sourceTree and path values. - - Examples: - input_path (source_tree, output_path) - '$(VAR)/path' ('VAR', 'path') - '$(VAR)' ('VAR', None) - 'path' (None, 'path') - """ - - source_group_match = _path_leading_variable.match(input_path) - if source_group_match: - source_tree = source_group_match.group(1) - output_path = source_group_match.group(3) # This may be None. - else: - source_tree = None - output_path = input_path - - return (source_tree, output_path) - -def ConvertVariablesToShellSyntax(input_string): - return re.sub(r'\$\((.*?)\)', '${\\1}', input_string) - -class XCObject(object): - """The abstract base of all class types used in Xcode project files. - - Class variables: - _schema: A dictionary defining the properties of this class. The keys to - _schema are string property keys as used in project files. Values - are a list of four or five elements: - [ is_list, property_type, is_strong, is_required, default ] - is_list: True if the property described is a list, as opposed - to a single element. - property_type: The type to use as the value of the property, - or if is_list is True, the type to use for each - element of the value's list. property_type must - be an XCObject subclass, or one of the built-in - types str, int, or dict. - is_strong: If property_type is an XCObject subclass, is_strong - is True to assert that this class "owns," or serves - as parent, to the property value (or, if is_list is - True, values). is_strong must be False if - property_type is not an XCObject subclass. - is_required: True if the property is required for the class. - Note that is_required being True does not preclude - an empty string ("", in the case of property_type - str) or list ([], in the case of is_list True) from - being set for the property. - default: Optional. If is_requried is True, default may be set - to provide a default value for objects that do not supply - their own value. If is_required is True and default - is not provided, users of the class must supply their own - value for the property. - Note that although the values of the array are expressed in - boolean terms, subclasses provide values as integers to conserve - horizontal space. - _should_print_single_line: False in XCObject. Subclasses whose objects - should be written to the project file in the - alternate single-line format, such as - PBXFileReference and PBXBuildFile, should - set this to True. - _encode_transforms: Used by _EncodeString to encode unprintable characters. - The index into this list is the ordinal of the - character to transform; each value is a string - used to represent the character in the output. XCObject - provides an _encode_transforms list suitable for most - XCObject subclasses. - _alternate_encode_transforms: Provided for subclasses that wish to use - the alternate encoding rules. Xcode seems - to use these rules when printing objects in - single-line format. Subclasses that desire - this behavior should set _encode_transforms - to _alternate_encode_transforms. - _hashables: A list of XCObject subclasses that can be hashed by ComputeIDs - to construct this object's ID. Most classes that need custom - hashing behavior should do it by overriding Hashables, - but in some cases an object's parent may wish to push a - hashable value into its child, and it can do so by appending - to _hashables. - Attributes: - id: The object's identifier, a 24-character uppercase hexadecimal string. - Usually, objects being created should not set id until the entire - project file structure is built. At that point, UpdateIDs() should - be called on the root object to assign deterministic values for id to - each object in the tree. - parent: The object's parent. This is set by a parent XCObject when a child - object is added to it. - _properties: The object's property dictionary. An object's properties are - described by its class' _schema variable. - """ - - _schema = {} - _should_print_single_line = False - - # See _EncodeString. - _encode_transforms = [] - i = 0 - while i < ord(' '): - _encode_transforms.append('\\U%04x' % i) - i = i + 1 - _encode_transforms[7] = '\\a' - _encode_transforms[8] = '\\b' - _encode_transforms[9] = '\\t' - _encode_transforms[10] = '\\n' - _encode_transforms[11] = '\\v' - _encode_transforms[12] = '\\f' - _encode_transforms[13] = '\\n' - - _alternate_encode_transforms = list(_encode_transforms) - _alternate_encode_transforms[9] = chr(9) - _alternate_encode_transforms[10] = chr(10) - _alternate_encode_transforms[11] = chr(11) - - def __init__(self, properties=None, id=None, parent=None): - self.id = id - self.parent = parent - self._properties = {} - self._hashables = [] - self._SetDefaultsFromSchema() - self.UpdateProperties(properties) - - def __repr__(self): - try: - name = self.Name() - except NotImplementedError: - return '<%s at 0x%x>' % (self.__class__.__name__, id(self)) - return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self)) - - def Copy(self): - """Make a copy of this object. - - The new object will have its own copy of lists and dicts. Any XCObject - objects owned by this object (marked "strong") will be copied in the - new object, even those found in lists. If this object has any weak - references to other XCObjects, the same references are added to the new - object without making a copy. - """ - - that = self.__class__(id=self.id, parent=self.parent) - for key, value in self._properties.iteritems(): - is_strong = self._schema[key][2] - - if isinstance(value, XCObject): - if is_strong: - new_value = value.Copy() - new_value.parent = that - that._properties[key] = new_value - else: - that._properties[key] = value - elif isinstance(value, str) or isinstance(value, unicode) or \ - isinstance(value, int): - that._properties[key] = value - elif isinstance(value, list): - if is_strong: - # If is_strong is True, each element is an XCObject, so it's safe to - # call Copy. - that._properties[key] = [] - for item in value: - new_item = item.Copy() - new_item.parent = that - that._properties[key].append(new_item) - else: - that._properties[key] = value[:] - elif isinstance(value, dict): - # dicts are never strong. - if is_strong: - raise TypeError('Strong dict for key ' + key + ' in ' + \ - self.__class__.__name__) - else: - that._properties[key] = value.copy() - else: - raise TypeError('Unexpected type ' + value.__class__.__name__ + \ - ' for key ' + key + ' in ' + self.__class__.__name__) - - return that - - def Name(self): - """Return the name corresponding to an object. - - Not all objects necessarily need to be nameable, and not all that do have - a "name" property. Override as needed. - """ - - # If the schema indicates that "name" is required, try to access the - # property even if it doesn't exist. This will result in a KeyError - # being raised for the property that should be present, which seems more - # appropriate than NotImplementedError in this case. - if 'name' in self._properties or \ - ('name' in self._schema and self._schema['name'][3]): - return self._properties['name'] - - raise NotImplementedError(self.__class__.__name__ + ' must implement Name') - - def Comment(self): - """Return a comment string for the object. - - Most objects just use their name as the comment, but PBXProject uses - different values. - - The returned comment is not escaped and does not have any comment marker - strings applied to it. - """ - - return self.Name() - - def Hashables(self): - hashables = [self.__class__.__name__] - - name = self.Name() - if name != None: - hashables.append(name) - - hashables.extend(self._hashables) - - return hashables - - def HashablesForChild(self): - return None - - def ComputeIDs(self, recursive=True, overwrite=True, seed_hash=None): - """Set "id" properties deterministically. - - An object's "id" property is set based on a hash of its class type and - name, as well as the class type and name of all ancestor objects. As - such, it is only advisable to call ComputeIDs once an entire project file - tree is built. - - If recursive is True, recurse into all descendant objects and update their - hashes. - - If overwrite is True, any existing value set in the "id" property will be - replaced. - """ - - def _HashUpdate(hash, data): - """Update hash with data's length and contents. - - If the hash were updated only with the value of data, it would be - possible for clowns to induce collisions by manipulating the names of - their objects. By adding the length, it's exceedingly less likely that - ID collisions will be encountered, intentionally or not. - """ - - hash.update(struct.pack('>i', len(data))) - hash.update(data) - - if seed_hash is None: - seed_hash = _new_sha1() - - hash = seed_hash.copy() - - hashables = self.Hashables() - assert len(hashables) > 0 - for hashable in hashables: - _HashUpdate(hash, hashable) - - if recursive: - hashables_for_child = self.HashablesForChild() - if hashables_for_child is None: - child_hash = hash - else: - assert len(hashables_for_child) > 0 - child_hash = seed_hash.copy() - for hashable in hashables_for_child: - _HashUpdate(child_hash, hashable) - - for child in self.Children(): - child.ComputeIDs(recursive, overwrite, child_hash) - - if overwrite or self.id is None: - # Xcode IDs are only 96 bits (24 hex characters), but a SHA-1 digest is - # is 160 bits. Instead of throwing out 64 bits of the digest, xor them - # into the portion that gets used. - assert hash.digest_size % 4 == 0 - digest_int_count = hash.digest_size / 4 - digest_ints = struct.unpack('>' + 'I' * digest_int_count, hash.digest()) - id_ints = [0, 0, 0] - for index in xrange(0, digest_int_count): - id_ints[index % 3] ^= digest_ints[index] - self.id = '%08X%08X%08X' % tuple(id_ints) - - def EnsureNoIDCollisions(self): - """Verifies that no two objects have the same ID. Checks all descendants. - """ - - ids = {} - descendants = self.Descendants() - for descendant in descendants: - if descendant.id in ids: - other = ids[descendant.id] - raise KeyError( - 'Duplicate ID %s, objects "%s" and "%s" in "%s"' % \ - (descendant.id, str(descendant._properties), - str(other._properties), self._properties['rootObject'].Name())) - ids[descendant.id] = descendant - - def Children(self): - """Returns a list of all of this object's owned (strong) children.""" - - children = [] - for property, attributes in self._schema.iteritems(): - (is_list, property_type, is_strong) = attributes[0:3] - if is_strong and property in self._properties: - if not is_list: - children.append(self._properties[property]) - else: - children.extend(self._properties[property]) - return children - - def Descendants(self): - """Returns a list of all of this object's descendants, including this - object. - """ - - children = self.Children() - descendants = [self] - for child in children: - descendants.extend(child.Descendants()) - return descendants - - def PBXProjectAncestor(self): - # The base case for recursion is defined at PBXProject.PBXProjectAncestor. - if self.parent: - return self.parent.PBXProjectAncestor() - return None - - def _EncodeComment(self, comment): - """Encodes a comment to be placed in the project file output, mimicing - Xcode behavior. - """ - - # This mimics Xcode behavior by wrapping the comment in "/*" and "*/". If - # the string already contains a "*/", it is turned into "(*)/". This keeps - # the file writer from outputting something that would be treated as the - # end of a comment in the middle of something intended to be entirely a - # comment. - - return '/* ' + comment.replace('*/', '(*)/') + ' */' - - def _EncodeTransform(self, match): - # This function works closely with _EncodeString. It will only be called - # by re.sub with match.group(0) containing a character matched by the - # the _escaped expression. - char = match.group(0) - - # Backslashes (\) and quotation marks (") are always replaced with a - # backslash-escaped version of the same. Everything else gets its - # replacement from the class' _encode_transforms array. - if char == '\\': - return '\\\\' - if char == '"': - return '\\"' - return self._encode_transforms[ord(char)] - - def _EncodeString(self, value): - """Encodes a string to be placed in the project file output, mimicing - Xcode behavior. - """ - - # Use quotation marks when any character outside of the range A-Z, a-z, 0-9, - # $ (dollar sign), . (period), and _ (underscore) is present. Also use - # quotation marks to represent empty strings. - # - # Escape " (double-quote) and \ (backslash) by preceding them with a - # backslash. - # - # Some characters below the printable ASCII range are encoded specially: - # 7 ^G BEL is encoded as "\a" - # 8 ^H BS is encoded as "\b" - # 11 ^K VT is encoded as "\v" - # 12 ^L NP is encoded as "\f" - # 127 ^? DEL is passed through as-is without escaping - # - In PBXFileReference and PBXBuildFile objects: - # 9 ^I HT is passed through as-is without escaping - # 10 ^J NL is passed through as-is without escaping - # 13 ^M CR is passed through as-is without escaping - # - In other objects: - # 9 ^I HT is encoded as "\t" - # 10 ^J NL is encoded as "\n" - # 13 ^M CR is encoded as "\n" rendering it indistinguishable from - # 10 ^J NL - # All other characters within the ASCII control character range (0 through - # 31 inclusive) are encoded as "\U001f" referring to the Unicode code point - # in hexadecimal. For example, character 14 (^N SO) is encoded as "\U000e". - # Characters above the ASCII range are passed through to the output encoded - # as UTF-8 without any escaping. These mappings are contained in the - # class' _encode_transforms list. - - if _unquoted.search(value) and not _quoted.search(value): - return value - - return '"' + _escaped.sub(self._EncodeTransform, value) + '"' - - def _XCPrint(self, file, tabs, line): - file.write('\t' * tabs + line) - - def _XCPrintableValue(self, tabs, value, flatten_list=False): - """Returns a representation of value that may be printed in a project file, - mimicing Xcode's behavior. - - _XCPrintableValue can handle str and int values, XCObjects (which are - made printable by returning their id property), and list and dict objects - composed of any of the above types. When printing a list or dict, and - _should_print_single_line is False, the tabs parameter is used to determine - how much to indent the lines corresponding to the items in the list or - dict. - - If flatten_list is True, single-element lists will be transformed into - strings. - """ - - printable = '' - comment = None - - if self._should_print_single_line: - sep = ' ' - element_tabs = '' - end_tabs = '' - else: - sep = '\n' - element_tabs = '\t' * (tabs + 1) - end_tabs = '\t' * tabs - - if isinstance(value, XCObject): - printable += value.id - comment = value.Comment() - elif isinstance(value, str): - printable += self._EncodeString(value) - elif isinstance(value, unicode): - printable += self._EncodeString(value.encode('utf-8')) - elif isinstance(value, int): - printable += str(value) - elif isinstance(value, list): - if flatten_list and len(value) <= 1: - if len(value) == 0: - printable += self._EncodeString('') - else: - printable += self._EncodeString(value[0]) - else: - printable = '(' + sep - for item in value: - printable += element_tabs + \ - self._XCPrintableValue(tabs + 1, item, flatten_list) + \ - ',' + sep - printable += end_tabs + ')' - elif isinstance(value, dict): - printable = '{' + sep - for item_key, item_value in sorted(value.iteritems()): - printable += element_tabs + \ - self._XCPrintableValue(tabs + 1, item_key, flatten_list) + ' = ' + \ - self._XCPrintableValue(tabs + 1, item_value, flatten_list) + ';' + \ - sep - printable += end_tabs + '}' - else: - raise TypeError("Can't make " + value.__class__.__name__ + ' printable') - - if comment != None: - printable += ' ' + self._EncodeComment(comment) - - return printable - - def _XCKVPrint(self, file, tabs, key, value): - """Prints a key and value, members of an XCObject's _properties dictionary, - to file. - - tabs is an int identifying the indentation level. If the class' - _should_print_single_line variable is True, tabs is ignored and the - key-value pair will be followed by a space insead of a newline. - """ - - if self._should_print_single_line: - printable = '' - after_kv = ' ' - else: - printable = '\t' * tabs - after_kv = '\n' - - # Xcode usually prints remoteGlobalIDString values in PBXContainerItemProxy - # objects without comments. Sometimes it prints them with comments, but - # the majority of the time, it doesn't. To avoid unnecessary changes to - # the project file after Xcode opens it, don't write comments for - # remoteGlobalIDString. This is a sucky hack and it would certainly be - # cleaner to extend the schema to indicate whether or not a comment should - # be printed, but since this is the only case where the problem occurs and - # Xcode itself can't seem to make up its mind, the hack will suffice. - # - # Also see PBXContainerItemProxy._schema['remoteGlobalIDString']. - if key == 'remoteGlobalIDString' and isinstance(self, - PBXContainerItemProxy): - value_to_print = value.id - else: - value_to_print = value - - # PBXBuildFile's settings property is represented in the output as a dict, - # but a hack here has it represented as a string. Arrange to strip off the - # quotes so that it shows up in the output as expected. - if key == 'settings' and isinstance(self, PBXBuildFile): - strip_value_quotes = True - else: - strip_value_quotes = False - - # In another one-off, let's set flatten_list on buildSettings properties - # of XCBuildConfiguration objects, because that's how Xcode treats them. - if key == 'buildSettings' and isinstance(self, XCBuildConfiguration): - flatten_list = True - else: - flatten_list = False - - try: - printable_key = self._XCPrintableValue(tabs, key, flatten_list) - printable_value = self._XCPrintableValue(tabs, value_to_print, - flatten_list) - if strip_value_quotes and len(printable_value) > 1 and \ - printable_value[0] == '"' and printable_value[-1] == '"': - printable_value = printable_value[1:-1] - printable += printable_key + ' = ' + printable_value + ';' + after_kv - except TypeError, e: - gyp.common.ExceptionAppend(e, - 'while printing key "%s"' % key) - raise - - self._XCPrint(file, 0, printable) - - def Print(self, file=sys.stdout): - """Prints a reprentation of this object to file, adhering to Xcode output - formatting. - """ - - self.VerifyHasRequiredProperties() - - if self._should_print_single_line: - # When printing an object in a single line, Xcode doesn't put any space - # between the beginning of a dictionary (or presumably a list) and the - # first contained item, so you wind up with snippets like - # ...CDEF = {isa = PBXFileReference; fileRef = 0123... - # If it were me, I would have put a space in there after the opening - # curly, but I guess this is just another one of those inconsistencies - # between how Xcode prints PBXFileReference and PBXBuildFile objects as - # compared to other objects. Mimic Xcode's behavior here by using an - # empty string for sep. - sep = '' - end_tabs = 0 - else: - sep = '\n' - end_tabs = 2 - - # Start the object. For example, '\t\tPBXProject = {\n'. - self._XCPrint(file, 2, self._XCPrintableValue(2, self) + ' = {' + sep) - - # "isa" isn't in the _properties dictionary, it's an intrinsic property - # of the class which the object belongs to. Xcode always outputs "isa" - # as the first element of an object dictionary. - self._XCKVPrint(file, 3, 'isa', self.__class__.__name__) - - # The remaining elements of an object dictionary are sorted alphabetically. - for property, value in sorted(self._properties.iteritems()): - self._XCKVPrint(file, 3, property, value) - - # End the object. - self._XCPrint(file, end_tabs, '};\n') - - def UpdateProperties(self, properties, do_copy=False): - """Merge the supplied properties into the _properties dictionary. - - The input properties must adhere to the class schema or a KeyError or - TypeError exception will be raised. If adding an object of an XCObject - subclass and the schema indicates a strong relationship, the object's - parent will be set to this object. - - If do_copy is True, then lists, dicts, strong-owned XCObjects, and - strong-owned XCObjects in lists will be copied instead of having their - references added. - """ - - if properties is None: - return - - for property, value in properties.iteritems(): - # Make sure the property is in the schema. - if not property in self._schema: - raise KeyError(property + ' not in ' + self.__class__.__name__) - - # Make sure the property conforms to the schema. - (is_list, property_type, is_strong) = self._schema[property][0:3] - if is_list: - if value.__class__ != list: - raise TypeError( - property + ' of ' + self.__class__.__name__ + \ - ' must be list, not ' + value.__class__.__name__) - for item in value: - if not isinstance(item, property_type) and \ - not (item.__class__ == unicode and property_type == str): - # Accept unicode where str is specified. str is treated as - # UTF-8-encoded. - raise TypeError( - 'item of ' + property + ' of ' + self.__class__.__name__ + \ - ' must be ' + property_type.__name__ + ', not ' + \ - item.__class__.__name__) - elif not isinstance(value, property_type) and \ - not (value.__class__ == unicode and property_type == str): - # Accept unicode where str is specified. str is treated as - # UTF-8-encoded. - raise TypeError( - property + ' of ' + self.__class__.__name__ + ' must be ' + \ - property_type.__name__ + ', not ' + value.__class__.__name__) - - # Checks passed, perform the assignment. - if do_copy: - if isinstance(value, XCObject): - if is_strong: - self._properties[property] = value.Copy() - else: - self._properties[property] = value - elif isinstance(value, str) or isinstance(value, unicode) or \ - isinstance(value, int): - self._properties[property] = value - elif isinstance(value, list): - if is_strong: - # If is_strong is True, each element is an XCObject, so it's safe - # to call Copy. - self._properties[property] = [] - for item in value: - self._properties[property].append(item.Copy()) - else: - self._properties[property] = value[:] - elif isinstance(value, dict): - self._properties[property] = value.copy() - else: - raise TypeError("Don't know how to copy a " + \ - value.__class__.__name__ + ' object for ' + \ - property + ' in ' + self.__class__.__name__) - else: - self._properties[property] = value - - # Set up the child's back-reference to this object. Don't use |value| - # any more because it may not be right if do_copy is true. - if is_strong: - if not is_list: - self._properties[property].parent = self - else: - for item in self._properties[property]: - item.parent = self - - def HasProperty(self, key): - return key in self._properties - - def GetProperty(self, key): - return self._properties[key] - - def SetProperty(self, key, value): - self.UpdateProperties({key: value}) - - def DelProperty(self, key): - if key in self._properties: - del self._properties[key] - - def AppendProperty(self, key, value): - # TODO(mark): Support ExtendProperty too (and make this call that)? - - # Schema validation. - if not key in self._schema: - raise KeyError(key + ' not in ' + self.__class__.__name__) - - (is_list, property_type, is_strong) = self._schema[key][0:3] - if not is_list: - raise TypeError(key + ' of ' + self.__class__.__name__ + ' must be list') - if not isinstance(value, property_type): - raise TypeError('item of ' + key + ' of ' + self.__class__.__name__ + \ - ' must be ' + property_type.__name__ + ', not ' + \ - value.__class__.__name__) - - # If the property doesn't exist yet, create a new empty list to receive the - # item. - if not key in self._properties: - self._properties[key] = [] - - # Set up the ownership link. - if is_strong: - value.parent = self - - # Store the item. - self._properties[key].append(value) - - def VerifyHasRequiredProperties(self): - """Ensure that all properties identified as required by the schema are - set. - """ - - # TODO(mark): A stronger verification mechanism is needed. Some - # subclasses need to perform validation beyond what the schema can enforce. - for property, attributes in self._schema.iteritems(): - (is_list, property_type, is_strong, is_required) = attributes[0:4] - if is_required and not property in self._properties: - raise KeyError(self.__class__.__name__ + ' requires ' + property) - - def _SetDefaultsFromSchema(self): - """Assign object default values according to the schema. This will not - overwrite properties that have already been set.""" - - defaults = {} - for property, attributes in self._schema.iteritems(): - (is_list, property_type, is_strong, is_required) = attributes[0:4] - if is_required and len(attributes) >= 5 and \ - not property in self._properties: - default = attributes[4] - - defaults[property] = default - - if len(defaults) > 0: - # Use do_copy=True so that each new object gets its own copy of strong - # objects, lists, and dicts. - self.UpdateProperties(defaults, do_copy=True) - - -class XCHierarchicalElement(XCObject): - """Abstract base for PBXGroup and PBXFileReference. Not represented in a - project file.""" - - # TODO(mark): Do name and path belong here? Probably so. - # If path is set and name is not, name may have a default value. Name will - # be set to the basename of path, if the basename of path is different from - # the full value of path. If path is already just a leaf name, name will - # not be set. - _schema = XCObject._schema.copy() - _schema.update({ - 'comments': [0, str, 0, 0], - 'fileEncoding': [0, str, 0, 0], - 'includeInIndex': [0, int, 0, 0], - 'indentWidth': [0, int, 0, 0], - 'lineEnding': [0, int, 0, 0], - 'sourceTree': [0, str, 0, 1, ''], - 'tabWidth': [0, int, 0, 0], - 'usesTabs': [0, int, 0, 0], - 'wrapsLines': [0, int, 0, 0], - }) - - def __init__(self, properties=None, id=None, parent=None): - # super - XCObject.__init__(self, properties, id, parent) - if 'path' in self._properties and not 'name' in self._properties: - path = self._properties['path'] - name = posixpath.basename(path) - if name != '' and path != name: - self.SetProperty('name', name) - - if 'path' in self._properties and \ - (not 'sourceTree' in self._properties or \ - self._properties['sourceTree'] == ''): - # If the pathname begins with an Xcode variable like "$(SDKROOT)/", take - # the variable out and make the path be relative to that variable by - # assigning the variable name as the sourceTree. - (source_tree, path) = SourceTreeAndPathFromPath(self._properties['path']) - if source_tree != None: - self._properties['sourceTree'] = source_tree - if path != None: - self._properties['path'] = path - if source_tree != None and path is None and \ - not 'name' in self._properties: - # The path was of the form "$(SDKROOT)" with no path following it. - # This object is now relative to that variable, so it has no path - # attribute of its own. It does, however, keep a name. - del self._properties['path'] - self._properties['name'] = source_tree - - def Name(self): - if 'name' in self._properties: - return self._properties['name'] - elif 'path' in self._properties: - return self._properties['path'] - else: - # This happens in the case of the root PBXGroup. - return None - - def Hashables(self): - """Custom hashables for XCHierarchicalElements. - - XCHierarchicalElements are special. Generally, their hashes shouldn't - change if the paths don't change. The normal XCObject implementation of - Hashables adds a hashable for each object, which means that if - the hierarchical structure changes (possibly due to changes caused when - TakeOverOnlyChild runs and encounters slight changes in the hierarchy), - the hashes will change. For example, if a project file initially contains - a/b/f1 and a/b becomes collapsed into a/b, f1 will have a single parent - a/b. If someone later adds a/f2 to the project file, a/b can no longer be - collapsed, and f1 winds up with parent b and grandparent a. That would - be sufficient to change f1's hash. - - To counteract this problem, hashables for all XCHierarchicalElements except - for the main group (which has neither a name nor a path) are taken to be - just the set of path components. Because hashables are inherited from - parents, this provides assurance that a/b/f1 has the same set of hashables - whether its parent is b or a/b. - - The main group is a special case. As it is permitted to have no name or - path, it is permitted to use the standard XCObject hash mechanism. This - is not considered a problem because there can be only one main group. - """ - - if self == self.PBXProjectAncestor()._properties['mainGroup']: - # super - return XCObject.Hashables(self) - - hashables = [] - - # Put the name in first, ensuring that if TakeOverOnlyChild collapses - # children into a top-level group like "Source", the name always goes - # into the list of hashables without interfering with path components. - if 'name' in self._properties: - # Make it less likely for people to manipulate hashes by following the - # pattern of always pushing an object type value onto the list first. - hashables.append(self.__class__.__name__ + '.name') - hashables.append(self._properties['name']) - - # NOTE: This still has the problem that if an absolute path is encountered, - # including paths with a sourceTree, they'll still inherit their parents' - # hashables, even though the paths aren't relative to their parents. This - # is not expected to be much of a problem in practice. - path = self.PathFromSourceTreeAndPath() - if path != None: - components = path.split(posixpath.sep) - for component in components: - hashables.append(self.__class__.__name__ + '.path') - hashables.append(component) - - hashables.extend(self._hashables) - - return hashables - - def Compare(self, other): - # Allow comparison of these types. PBXGroup has the highest sort rank; - # PBXVariantGroup is treated as equal to PBXFileReference. - valid_class_types = { - PBXFileReference: 'file', - PBXGroup: 'group', - PBXVariantGroup: 'file', - } - self_type = valid_class_types[self.__class__] - other_type = valid_class_types[other.__class__] - - if self_type == other_type: - # If the two objects are of the same sort rank, compare their names. - return cmp(self.Name(), other.Name()) - - # Otherwise, sort groups before everything else. - if self_type == 'group': - return -1 - return 1 - - def CompareRootGroup(self, other): - # This function should be used only to compare direct children of the - # containing PBXProject's mainGroup. These groups should appear in the - # listed order. - # TODO(mark): "Build" is used by gyp.generator.xcode, perhaps the - # generator should have a way of influencing this list rather than having - # to hardcode for the generator here. - order = ['Source', 'Intermediates', 'Projects', 'Frameworks', 'Products', - 'Build'] - - # If the groups aren't in the listed order, do a name comparison. - # Otherwise, groups in the listed order should come before those that - # aren't. - self_name = self.Name() - other_name = other.Name() - self_in = isinstance(self, PBXGroup) and self_name in order - other_in = isinstance(self, PBXGroup) and other_name in order - if not self_in and not other_in: - return self.Compare(other) - if self_name in order and not other_name in order: - return -1 - if other_name in order and not self_name in order: - return 1 - - # If both groups are in the listed order, go by the defined order. - self_index = order.index(self_name) - other_index = order.index(other_name) - if self_index < other_index: - return -1 - if self_index > other_index: - return 1 - return 0 - - def PathFromSourceTreeAndPath(self): - # Turn the object's sourceTree and path properties into a single flat - # string of a form comparable to the path parameter. If there's a - # sourceTree property other than "", wrap it in $(...) for the - # comparison. - components = [] - if self._properties['sourceTree'] != '': - components.append('$(' + self._properties['sourceTree'] + ')') - if 'path' in self._properties: - components.append(self._properties['path']) - - if len(components) > 0: - return posixpath.join(*components) - - return None - - def FullPath(self): - # Returns a full path to self relative to the project file, or relative - # to some other source tree. Start with self, and walk up the chain of - # parents prepending their paths, if any, until no more parents are - # available (project-relative path) or until a path relative to some - # source tree is found. - xche = self - path = None - while isinstance(xche, XCHierarchicalElement) and \ - (path is None or \ - (not path.startswith('/') and not path.startswith('$'))): - this_path = xche.PathFromSourceTreeAndPath() - if this_path != None and path != None: - path = posixpath.join(this_path, path) - elif this_path != None: - path = this_path - xche = xche.parent - - return path - - -class PBXGroup(XCHierarchicalElement): - """ - Attributes: - _children_by_path: Maps pathnames of children of this PBXGroup to the - actual child XCHierarchicalElement objects. - _variant_children_by_name_and_path: Maps (name, path) tuples of - PBXVariantGroup children to the actual child PBXVariantGroup objects. - """ - - _schema = XCHierarchicalElement._schema.copy() - _schema.update({ - 'children': [1, XCHierarchicalElement, 1, 1, []], - 'name': [0, str, 0, 0], - 'path': [0, str, 0, 0], - }) - - def __init__(self, properties=None, id=None, parent=None): - # super - XCHierarchicalElement.__init__(self, properties, id, parent) - self._children_by_path = {} - self._variant_children_by_name_and_path = {} - for child in self._properties.get('children', []): - self._AddChildToDicts(child) - - def Hashables(self): - # super - hashables = XCHierarchicalElement.Hashables(self) - - # It is not sufficient to just rely on name and parent to build a unique - # hashable : a node could have two child PBXGroup sharing a common name. - # To add entropy the hashable is enhanced with the names of all its - # children. - for child in self._properties.get('children', []): - child_name = child.Name() - if child_name != None: - hashables.append(child_name) - - return hashables - - def HashablesForChild(self): - # To avoid a circular reference the hashables used to compute a child id do - # not include the child names. - return XCHierarchicalElement.Hashables(self) - - def _AddChildToDicts(self, child): - # Sets up this PBXGroup object's dicts to reference the child properly. - child_path = child.PathFromSourceTreeAndPath() - if child_path: - if child_path in self._children_by_path: - raise ValueError('Found multiple children with path ' + child_path) - self._children_by_path[child_path] = child - - if isinstance(child, PBXVariantGroup): - child_name = child._properties.get('name', None) - key = (child_name, child_path) - if key in self._variant_children_by_name_and_path: - raise ValueError('Found multiple PBXVariantGroup children with ' + \ - 'name ' + str(child_name) + ' and path ' + \ - str(child_path)) - self._variant_children_by_name_and_path[key] = child - - def AppendChild(self, child): - # Callers should use this instead of calling - # AppendProperty('children', child) directly because this function - # maintains the group's dicts. - self.AppendProperty('children', child) - self._AddChildToDicts(child) - - def GetChildByName(self, name): - # This is not currently optimized with a dict as GetChildByPath is because - # it has few callers. Most callers probably want GetChildByPath. This - # function is only useful to get children that have names but no paths, - # which is rare. The children of the main group ("Source", "Products", - # etc.) is pretty much the only case where this likely to come up. - # - # TODO(mark): Maybe this should raise an error if more than one child is - # present with the same name. - if not 'children' in self._properties: - return None - - for child in self._properties['children']: - if child.Name() == name: - return child - - return None - - def GetChildByPath(self, path): - if not path: - return None - - if path in self._children_by_path: - return self._children_by_path[path] - - return None - - def GetChildByRemoteObject(self, remote_object): - # This method is a little bit esoteric. Given a remote_object, which - # should be a PBXFileReference in another project file, this method will - # return this group's PBXReferenceProxy object serving as a local proxy - # for the remote PBXFileReference. - # - # This function might benefit from a dict optimization as GetChildByPath - # for some workloads, but profiling shows that it's not currently a - # problem. - if not 'children' in self._properties: - return None - - for child in self._properties['children']: - if not isinstance(child, PBXReferenceProxy): - continue - - container_proxy = child._properties['remoteRef'] - if container_proxy._properties['remoteGlobalIDString'] == remote_object: - return child - - return None - - def AddOrGetFileByPath(self, path, hierarchical): - """Returns an existing or new file reference corresponding to path. - - If hierarchical is True, this method will create or use the necessary - hierarchical group structure corresponding to path. Otherwise, it will - look in and create an item in the current group only. - - If an existing matching reference is found, it is returned, otherwise, a - new one will be created, added to the correct group, and returned. - - If path identifies a directory by virtue of carrying a trailing slash, - this method returns a PBXFileReference of "folder" type. If path - identifies a variant, by virtue of it identifying a file inside a directory - with an ".lproj" extension, this method returns a PBXVariantGroup - containing the variant named by path, and possibly other variants. For - all other paths, a "normal" PBXFileReference will be returned. - """ - - # Adding or getting a directory? Directories end with a trailing slash. - is_dir = False - if path.endswith('/'): - is_dir = True - path = posixpath.normpath(path) - if is_dir: - path = path + '/' - - # Adding or getting a variant? Variants are files inside directories - # with an ".lproj" extension. Xcode uses variants for localization. For - # a variant path/to/Language.lproj/MainMenu.nib, put a variant group named - # MainMenu.nib inside path/to, and give it a variant named Language. In - # this example, grandparent would be set to path/to and parent_root would - # be set to Language. - variant_name = None - parent = posixpath.dirname(path) - grandparent = posixpath.dirname(parent) - parent_basename = posixpath.basename(parent) - (parent_root, parent_ext) = posixpath.splitext(parent_basename) - if parent_ext == '.lproj': - variant_name = parent_root - if grandparent == '': - grandparent = None - - # Putting a directory inside a variant group is not currently supported. - assert not is_dir or variant_name is None - - path_split = path.split(posixpath.sep) - if len(path_split) == 1 or \ - ((is_dir or variant_name != None) and len(path_split) == 2) or \ - not hierarchical: - # The PBXFileReference or PBXVariantGroup will be added to or gotten from - # this PBXGroup, no recursion necessary. - if variant_name is None: - # Add or get a PBXFileReference. - file_ref = self.GetChildByPath(path) - if file_ref != None: - assert file_ref.__class__ == PBXFileReference - else: - file_ref = PBXFileReference({'path': path}) - self.AppendChild(file_ref) - else: - # Add or get a PBXVariantGroup. The variant group name is the same - # as the basename (MainMenu.nib in the example above). grandparent - # specifies the path to the variant group itself, and path_split[-2:] - # is the path of the specific variant relative to its group. - variant_group_name = posixpath.basename(path) - variant_group_ref = self.AddOrGetVariantGroupByNameAndPath( - variant_group_name, grandparent) - variant_path = posixpath.sep.join(path_split[-2:]) - variant_ref = variant_group_ref.GetChildByPath(variant_path) - if variant_ref != None: - assert variant_ref.__class__ == PBXFileReference - else: - variant_ref = PBXFileReference({'name': variant_name, - 'path': variant_path}) - variant_group_ref.AppendChild(variant_ref) - # The caller is interested in the variant group, not the specific - # variant file. - file_ref = variant_group_ref - return file_ref - else: - # Hierarchical recursion. Add or get a PBXGroup corresponding to the - # outermost path component, and then recurse into it, chopping off that - # path component. - next_dir = path_split[0] - group_ref = self.GetChildByPath(next_dir) - if group_ref != None: - assert group_ref.__class__ == PBXGroup - else: - group_ref = PBXGroup({'path': next_dir}) - self.AppendChild(group_ref) - return group_ref.AddOrGetFileByPath(posixpath.sep.join(path_split[1:]), - hierarchical) - - def AddOrGetVariantGroupByNameAndPath(self, name, path): - """Returns an existing or new PBXVariantGroup for name and path. - - If a PBXVariantGroup identified by the name and path arguments is already - present as a child of this object, it is returned. Otherwise, a new - PBXVariantGroup with the correct properties is created, added as a child, - and returned. - - This method will generally be called by AddOrGetFileByPath, which knows - when to create a variant group based on the structure of the pathnames - passed to it. - """ - - key = (name, path) - if key in self._variant_children_by_name_and_path: - variant_group_ref = self._variant_children_by_name_and_path[key] - assert variant_group_ref.__class__ == PBXVariantGroup - return variant_group_ref - - variant_group_properties = {'name': name} - if path != None: - variant_group_properties['path'] = path - variant_group_ref = PBXVariantGroup(variant_group_properties) - self.AppendChild(variant_group_ref) - - return variant_group_ref - - def TakeOverOnlyChild(self, recurse=False): - """If this PBXGroup has only one child and it's also a PBXGroup, take - it over by making all of its children this object's children. - - This function will continue to take over only children when those children - are groups. If there are three PBXGroups representing a, b, and c, with - c inside b and b inside a, and a and b have no other children, this will - result in a taking over both b and c, forming a PBXGroup for a/b/c. - - If recurse is True, this function will recurse into children and ask them - to collapse themselves by taking over only children as well. Assuming - an example hierarchy with files at a/b/c/d1, a/b/c/d2, and a/b/c/d3/e/f - (d1, d2, and f are files, the rest are groups), recursion will result in - a group for a/b/c containing a group for d3/e. - """ - - # At this stage, check that child class types are PBXGroup exactly, - # instead of using isinstance. The only subclass of PBXGroup, - # PBXVariantGroup, should not participate in reparenting in the same way: - # reparenting by merging different object types would be wrong. - while len(self._properties['children']) == 1 and \ - self._properties['children'][0].__class__ == PBXGroup: - # Loop to take over the innermost only-child group possible. - - child = self._properties['children'][0] - - # Assume the child's properties, including its children. Save a copy - # of this object's old properties, because they'll still be needed. - # This object retains its existing id and parent attributes. - old_properties = self._properties - self._properties = child._properties - self._children_by_path = child._children_by_path - - if not 'sourceTree' in self._properties or \ - self._properties['sourceTree'] == '': - # The child was relative to its parent. Fix up the path. Note that - # children with a sourceTree other than "" are not relative to - # their parents, so no path fix-up is needed in that case. - if 'path' in old_properties: - if 'path' in self._properties: - # Both the original parent and child have paths set. - self._properties['path'] = posixpath.join(old_properties['path'], - self._properties['path']) - else: - # Only the original parent has a path, use it. - self._properties['path'] = old_properties['path'] - if 'sourceTree' in old_properties: - # The original parent had a sourceTree set, use it. - self._properties['sourceTree'] = old_properties['sourceTree'] - - # If the original parent had a name set, keep using it. If the original - # parent didn't have a name but the child did, let the child's name - # live on. If the name attribute seems unnecessary now, get rid of it. - if 'name' in old_properties and old_properties['name'] != None and \ - old_properties['name'] != self.Name(): - self._properties['name'] = old_properties['name'] - if 'name' in self._properties and 'path' in self._properties and \ - self._properties['name'] == self._properties['path']: - del self._properties['name'] - - # Notify all children of their new parent. - for child in self._properties['children']: - child.parent = self - - # If asked to recurse, recurse. - if recurse: - for child in self._properties['children']: - if child.__class__ == PBXGroup: - child.TakeOverOnlyChild(recurse) - - def SortGroup(self): - self._properties['children'] = \ - sorted(self._properties['children'], cmp=lambda x,y: x.Compare(y)) - - # Recurse. - for child in self._properties['children']: - if isinstance(child, PBXGroup): - child.SortGroup() - - -class XCFileLikeElement(XCHierarchicalElement): - # Abstract base for objects that can be used as the fileRef property of - # PBXBuildFile. - - def PathHashables(self): - # A PBXBuildFile that refers to this object will call this method to - # obtain additional hashables specific to this XCFileLikeElement. Don't - # just use this object's hashables, they're not specific and unique enough - # on their own (without access to the parent hashables.) Instead, provide - # hashables that identify this object by path by getting its hashables as - # well as the hashables of ancestor XCHierarchicalElement objects. - - hashables = [] - xche = self - while xche != None and isinstance(xche, XCHierarchicalElement): - xche_hashables = xche.Hashables() - for index in xrange(0, len(xche_hashables)): - hashables.insert(index, xche_hashables[index]) - xche = xche.parent - return hashables - - -class XCContainerPortal(XCObject): - # Abstract base for objects that can be used as the containerPortal property - # of PBXContainerItemProxy. - pass - - -class XCRemoteObject(XCObject): - # Abstract base for objects that can be used as the remoteGlobalIDString - # property of PBXContainerItemProxy. - pass - - -class PBXFileReference(XCFileLikeElement, XCContainerPortal, XCRemoteObject): - _schema = XCFileLikeElement._schema.copy() - _schema.update({ - 'explicitFileType': [0, str, 0, 0], - 'lastKnownFileType': [0, str, 0, 0], - 'name': [0, str, 0, 0], - 'path': [0, str, 0, 1], - }) - - # Weird output rules for PBXFileReference. - _should_print_single_line = True - # super - _encode_transforms = XCFileLikeElement._alternate_encode_transforms - - def __init__(self, properties=None, id=None, parent=None): - # super - XCFileLikeElement.__init__(self, properties, id, parent) - if 'path' in self._properties and self._properties['path'].endswith('/'): - self._properties['path'] = self._properties['path'][:-1] - is_dir = True - else: - is_dir = False - - if 'path' in self._properties and \ - not 'lastKnownFileType' in self._properties and \ - not 'explicitFileType' in self._properties: - # TODO(mark): This is the replacement for a replacement for a quick hack. - # It is no longer incredibly sucky, but this list needs to be extended. - extension_map = { - 'a': 'archive.ar', - 'app': 'wrapper.application', - 'bdic': 'file', - 'bundle': 'wrapper.cfbundle', - 'c': 'sourcecode.c.c', - 'cc': 'sourcecode.cpp.cpp', - 'cpp': 'sourcecode.cpp.cpp', - 'css': 'text.css', - 'cxx': 'sourcecode.cpp.cpp', - 'dart': 'sourcecode', - 'dylib': 'compiled.mach-o.dylib', - 'framework': 'wrapper.framework', - 'gyp': 'sourcecode', - 'gypi': 'sourcecode', - 'h': 'sourcecode.c.h', - 'hxx': 'sourcecode.cpp.h', - 'icns': 'image.icns', - 'java': 'sourcecode.java', - 'js': 'sourcecode.javascript', - 'kext': 'wrapper.kext', - 'm': 'sourcecode.c.objc', - 'mm': 'sourcecode.cpp.objcpp', - 'nib': 'wrapper.nib', - 'o': 'compiled.mach-o.objfile', - 'pdf': 'image.pdf', - 'pl': 'text.script.perl', - 'plist': 'text.plist.xml', - 'pm': 'text.script.perl', - 'png': 'image.png', - 'py': 'text.script.python', - 'r': 'sourcecode.rez', - 'rez': 'sourcecode.rez', - 's': 'sourcecode.asm', - 'storyboard': 'file.storyboard', - 'strings': 'text.plist.strings', - 'swift': 'sourcecode.swift', - 'ttf': 'file', - 'xcassets': 'folder.assetcatalog', - 'xcconfig': 'text.xcconfig', - 'xcdatamodel': 'wrapper.xcdatamodel', - 'xcdatamodeld':'wrapper.xcdatamodeld', - 'xib': 'file.xib', - 'y': 'sourcecode.yacc', - } - - prop_map = { - 'dart': 'explicitFileType', - 'gyp': 'explicitFileType', - 'gypi': 'explicitFileType', - } - - if is_dir: - file_type = 'folder' - prop_name = 'lastKnownFileType' - else: - basename = posixpath.basename(self._properties['path']) - (root, ext) = posixpath.splitext(basename) - # Check the map using a lowercase extension. - # TODO(mark): Maybe it should try with the original case first and fall - # back to lowercase, in case there are any instances where case - # matters. There currently aren't. - if ext != '': - ext = ext[1:].lower() - - # TODO(mark): "text" is the default value, but "file" is appropriate - # for unrecognized files not containing text. Xcode seems to choose - # based on content. - file_type = extension_map.get(ext, 'text') - prop_name = prop_map.get(ext, 'lastKnownFileType') - - self._properties[prop_name] = file_type - - -class PBXVariantGroup(PBXGroup, XCFileLikeElement): - """PBXVariantGroup is used by Xcode to represent localizations.""" - # No additions to the schema relative to PBXGroup. - pass - - -# PBXReferenceProxy is also an XCFileLikeElement subclass. It is defined below -# because it uses PBXContainerItemProxy, defined below. - - -class XCBuildConfiguration(XCObject): - _schema = XCObject._schema.copy() - _schema.update({ - 'baseConfigurationReference': [0, PBXFileReference, 0, 0], - 'buildSettings': [0, dict, 0, 1, {}], - 'name': [0, str, 0, 1], - }) - - def HasBuildSetting(self, key): - return key in self._properties['buildSettings'] - - def GetBuildSetting(self, key): - return self._properties['buildSettings'][key] - - def SetBuildSetting(self, key, value): - # TODO(mark): If a list, copy? - self._properties['buildSettings'][key] = value - - def AppendBuildSetting(self, key, value): - if not key in self._properties['buildSettings']: - self._properties['buildSettings'][key] = [] - self._properties['buildSettings'][key].append(value) - - def DelBuildSetting(self, key): - if key in self._properties['buildSettings']: - del self._properties['buildSettings'][key] - - def SetBaseConfiguration(self, value): - self._properties['baseConfigurationReference'] = value - -class XCConfigurationList(XCObject): - # _configs is the default list of configurations. - _configs = [ XCBuildConfiguration({'name': 'Debug'}), - XCBuildConfiguration({'name': 'Release'}) ] - - _schema = XCObject._schema.copy() - _schema.update({ - 'buildConfigurations': [1, XCBuildConfiguration, 1, 1, _configs], - 'defaultConfigurationIsVisible': [0, int, 0, 1, 1], - 'defaultConfigurationName': [0, str, 0, 1, 'Release'], - }) - - def Name(self): - return 'Build configuration list for ' + \ - self.parent.__class__.__name__ + ' "' + self.parent.Name() + '"' - - def ConfigurationNamed(self, name): - """Convenience accessor to obtain an XCBuildConfiguration by name.""" - for configuration in self._properties['buildConfigurations']: - if configuration._properties['name'] == name: - return configuration - - raise KeyError(name) - - def DefaultConfiguration(self): - """Convenience accessor to obtain the default XCBuildConfiguration.""" - return self.ConfigurationNamed(self._properties['defaultConfigurationName']) - - def HasBuildSetting(self, key): - """Determines the state of a build setting in all XCBuildConfiguration - child objects. - - If all child objects have key in their build settings, and the value is the - same in all child objects, returns 1. - - If no child objects have the key in their build settings, returns 0. - - If some, but not all, child objects have the key in their build settings, - or if any children have different values for the key, returns -1. - """ - - has = None - value = None - for configuration in self._properties['buildConfigurations']: - configuration_has = configuration.HasBuildSetting(key) - if has is None: - has = configuration_has - elif has != configuration_has: - return -1 - - if configuration_has: - configuration_value = configuration.GetBuildSetting(key) - if value is None: - value = configuration_value - elif value != configuration_value: - return -1 - - if not has: - return 0 - - return 1 - - def GetBuildSetting(self, key): - """Gets the build setting for key. - - All child XCConfiguration objects must have the same value set for the - setting, or a ValueError will be raised. - """ - - # TODO(mark): This is wrong for build settings that are lists. The list - # contents should be compared (and a list copy returned?) - - value = None - for configuration in self._properties['buildConfigurations']: - configuration_value = configuration.GetBuildSetting(key) - if value is None: - value = configuration_value - else: - if value != configuration_value: - raise ValueError('Variant values for ' + key) - - return value - - def SetBuildSetting(self, key, value): - """Sets the build setting for key to value in all child - XCBuildConfiguration objects. - """ - - for configuration in self._properties['buildConfigurations']: - configuration.SetBuildSetting(key, value) - - def AppendBuildSetting(self, key, value): - """Appends value to the build setting for key, which is treated as a list, - in all child XCBuildConfiguration objects. - """ - - for configuration in self._properties['buildConfigurations']: - configuration.AppendBuildSetting(key, value) - - def DelBuildSetting(self, key): - """Deletes the build setting key from all child XCBuildConfiguration - objects. - """ - - for configuration in self._properties['buildConfigurations']: - configuration.DelBuildSetting(key) - - def SetBaseConfiguration(self, value): - """Sets the build configuration in all child XCBuildConfiguration objects. - """ - - for configuration in self._properties['buildConfigurations']: - configuration.SetBaseConfiguration(value) - - -class PBXBuildFile(XCObject): - _schema = XCObject._schema.copy() - _schema.update({ - 'fileRef': [0, XCFileLikeElement, 0, 1], - 'settings': [0, str, 0, 0], # hack, it's a dict - }) - - # Weird output rules for PBXBuildFile. - _should_print_single_line = True - _encode_transforms = XCObject._alternate_encode_transforms - - def Name(self): - # Example: "main.cc in Sources" - return self._properties['fileRef'].Name() + ' in ' + self.parent.Name() - - def Hashables(self): - # super - hashables = XCObject.Hashables(self) - - # It is not sufficient to just rely on Name() to get the - # XCFileLikeElement's name, because that is not a complete pathname. - # PathHashables returns hashables unique enough that no two - # PBXBuildFiles should wind up with the same set of hashables, unless - # someone adds the same file multiple times to the same target. That - # would be considered invalid anyway. - hashables.extend(self._properties['fileRef'].PathHashables()) - - return hashables - - -class XCBuildPhase(XCObject): - """Abstract base for build phase classes. Not represented in a project - file. - - Attributes: - _files_by_path: A dict mapping each path of a child in the files list by - path (keys) to the corresponding PBXBuildFile children (values). - _files_by_xcfilelikeelement: A dict mapping each XCFileLikeElement (keys) - to the corresponding PBXBuildFile children (values). - """ - - # TODO(mark): Some build phase types, like PBXShellScriptBuildPhase, don't - # actually have a "files" list. XCBuildPhase should not have "files" but - # another abstract subclass of it should provide this, and concrete build - # phase types that do have "files" lists should be derived from that new - # abstract subclass. XCBuildPhase should only provide buildActionMask and - # runOnlyForDeploymentPostprocessing, and not files or the various - # file-related methods and attributes. - - _schema = XCObject._schema.copy() - _schema.update({ - 'buildActionMask': [0, int, 0, 1, 0x7fffffff], - 'files': [1, PBXBuildFile, 1, 1, []], - 'runOnlyForDeploymentPostprocessing': [0, int, 0, 1, 0], - }) - - def __init__(self, properties=None, id=None, parent=None): - # super - XCObject.__init__(self, properties, id, parent) - - self._files_by_path = {} - self._files_by_xcfilelikeelement = {} - for pbxbuildfile in self._properties.get('files', []): - self._AddBuildFileToDicts(pbxbuildfile) - - def FileGroup(self, path): - # Subclasses must override this by returning a two-element tuple. The - # first item in the tuple should be the PBXGroup to which "path" should be - # added, either as a child or deeper descendant. The second item should - # be a boolean indicating whether files should be added into hierarchical - # groups or one single flat group. - raise NotImplementedError( - self.__class__.__name__ + ' must implement FileGroup') - - def _AddPathToDict(self, pbxbuildfile, path): - """Adds path to the dict tracking paths belonging to this build phase. - - If the path is already a member of this build phase, raises an exception. - """ - - if path in self._files_by_path: - raise ValueError('Found multiple build files with path ' + path) - self._files_by_path[path] = pbxbuildfile - - def _AddBuildFileToDicts(self, pbxbuildfile, path=None): - """Maintains the _files_by_path and _files_by_xcfilelikeelement dicts. - - If path is specified, then it is the path that is being added to the - phase, and pbxbuildfile must contain either a PBXFileReference directly - referencing that path, or it must contain a PBXVariantGroup that itself - contains a PBXFileReference referencing the path. - - If path is not specified, either the PBXFileReference's path or the paths - of all children of the PBXVariantGroup are taken as being added to the - phase. - - If the path is already present in the phase, raises an exception. - - If the PBXFileReference or PBXVariantGroup referenced by pbxbuildfile - are already present in the phase, referenced by a different PBXBuildFile - object, raises an exception. This does not raise an exception when - a PBXFileReference or PBXVariantGroup reappear and are referenced by the - same PBXBuildFile that has already introduced them, because in the case - of PBXVariantGroup objects, they may correspond to multiple paths that are - not all added simultaneously. When this situation occurs, the path needs - to be added to _files_by_path, but nothing needs to change in - _files_by_xcfilelikeelement, and the caller should have avoided adding - the PBXBuildFile if it is already present in the list of children. - """ - - xcfilelikeelement = pbxbuildfile._properties['fileRef'] - - paths = [] - if path != None: - # It's best when the caller provides the path. - if isinstance(xcfilelikeelement, PBXVariantGroup): - paths.append(path) - else: - # If the caller didn't provide a path, there can be either multiple - # paths (PBXVariantGroup) or one. - if isinstance(xcfilelikeelement, PBXVariantGroup): - for variant in xcfilelikeelement._properties['children']: - paths.append(variant.FullPath()) - else: - paths.append(xcfilelikeelement.FullPath()) - - # Add the paths first, because if something's going to raise, the - # messages provided by _AddPathToDict are more useful owing to its - # having access to a real pathname and not just an object's Name(). - for a_path in paths: - self._AddPathToDict(pbxbuildfile, a_path) - - # If another PBXBuildFile references this XCFileLikeElement, there's a - # problem. - if xcfilelikeelement in self._files_by_xcfilelikeelement and \ - self._files_by_xcfilelikeelement[xcfilelikeelement] != pbxbuildfile: - raise ValueError('Found multiple build files for ' + \ - xcfilelikeelement.Name()) - self._files_by_xcfilelikeelement[xcfilelikeelement] = pbxbuildfile - - def AppendBuildFile(self, pbxbuildfile, path=None): - # Callers should use this instead of calling - # AppendProperty('files', pbxbuildfile) directly because this function - # maintains the object's dicts. Better yet, callers can just call AddFile - # with a pathname and not worry about building their own PBXBuildFile - # objects. - self.AppendProperty('files', pbxbuildfile) - self._AddBuildFileToDicts(pbxbuildfile, path) - - def AddFile(self, path, settings=None): - (file_group, hierarchical) = self.FileGroup(path) - file_ref = file_group.AddOrGetFileByPath(path, hierarchical) - - if file_ref in self._files_by_xcfilelikeelement and \ - isinstance(file_ref, PBXVariantGroup): - # There's already a PBXBuildFile in this phase corresponding to the - # PBXVariantGroup. path just provides a new variant that belongs to - # the group. Add the path to the dict. - pbxbuildfile = self._files_by_xcfilelikeelement[file_ref] - self._AddBuildFileToDicts(pbxbuildfile, path) - else: - # Add a new PBXBuildFile to get file_ref into the phase. - if settings is None: - pbxbuildfile = PBXBuildFile({'fileRef': file_ref}) - else: - pbxbuildfile = PBXBuildFile({'fileRef': file_ref, 'settings': settings}) - self.AppendBuildFile(pbxbuildfile, path) - - -class PBXHeadersBuildPhase(XCBuildPhase): - # No additions to the schema relative to XCBuildPhase. - - def Name(self): - return 'Headers' - - def FileGroup(self, path): - return self.PBXProjectAncestor().RootGroupForPath(path) - - -class PBXResourcesBuildPhase(XCBuildPhase): - # No additions to the schema relative to XCBuildPhase. - - def Name(self): - return 'Resources' - - def FileGroup(self, path): - return self.PBXProjectAncestor().RootGroupForPath(path) - - -class PBXSourcesBuildPhase(XCBuildPhase): - # No additions to the schema relative to XCBuildPhase. - - def Name(self): - return 'Sources' - - def FileGroup(self, path): - return self.PBXProjectAncestor().RootGroupForPath(path) - - -class PBXFrameworksBuildPhase(XCBuildPhase): - # No additions to the schema relative to XCBuildPhase. - - def Name(self): - return 'Frameworks' - - def FileGroup(self, path): - (root, ext) = posixpath.splitext(path) - if ext != '': - ext = ext[1:].lower() - if ext == 'o': - # .o files are added to Xcode Frameworks phases, but conceptually aren't - # frameworks, they're more like sources or intermediates. Redirect them - # to show up in one of those other groups. - return self.PBXProjectAncestor().RootGroupForPath(path) - else: - return (self.PBXProjectAncestor().FrameworksGroup(), False) - - -class PBXShellScriptBuildPhase(XCBuildPhase): - _schema = XCBuildPhase._schema.copy() - _schema.update({ - 'inputPaths': [1, str, 0, 1, []], - 'name': [0, str, 0, 0], - 'outputPaths': [1, str, 0, 1, []], - 'shellPath': [0, str, 0, 1, '/bin/sh'], - 'shellScript': [0, str, 0, 1], - 'showEnvVarsInLog': [0, int, 0, 0], - }) - - def Name(self): - if 'name' in self._properties: - return self._properties['name'] - - return 'ShellScript' - - -class PBXCopyFilesBuildPhase(XCBuildPhase): - _schema = XCBuildPhase._schema.copy() - _schema.update({ - 'dstPath': [0, str, 0, 1], - 'dstSubfolderSpec': [0, int, 0, 1], - 'name': [0, str, 0, 0], - }) - - # path_tree_re matches "$(DIR)/path" or just "$(DIR)". Match group 1 is - # "DIR", match group 3 is "path" or None. - path_tree_re = re.compile('^\\$\\((.*)\\)(/(.*)|)$') - - # path_tree_to_subfolder maps names of Xcode variables to the associated - # dstSubfolderSpec property value used in a PBXCopyFilesBuildPhase object. - path_tree_to_subfolder = { - 'BUILT_FRAMEWORKS_DIR': 10, # Frameworks Directory - 'BUILT_PRODUCTS_DIR': 16, # Products Directory - # Other types that can be chosen via the Xcode UI. - # TODO(mark): Map Xcode variable names to these. - # : 1, # Wrapper - # : 6, # Executables: 6 - # : 7, # Resources - # : 15, # Java Resources - # : 11, # Shared Frameworks - # : 12, # Shared Support - # : 13, # PlugIns - } - - def Name(self): - if 'name' in self._properties: - return self._properties['name'] - - return 'CopyFiles' - - def FileGroup(self, path): - return self.PBXProjectAncestor().RootGroupForPath(path) - - def SetDestination(self, path): - """Set the dstSubfolderSpec and dstPath properties from path. - - path may be specified in the same notation used for XCHierarchicalElements, - specifically, "$(DIR)/path". - """ - - path_tree_match = self.path_tree_re.search(path) - if path_tree_match: - # Everything else needs to be relative to an Xcode variable. - path_tree = path_tree_match.group(1) - relative_path = path_tree_match.group(3) - - if path_tree in self.path_tree_to_subfolder: - subfolder = self.path_tree_to_subfolder[path_tree] - if relative_path is None: - relative_path = '' - else: - # The path starts with an unrecognized Xcode variable - # name like $(SRCROOT). Xcode will still handle this - # as an "absolute path" that starts with the variable. - subfolder = 0 - relative_path = path - elif path.startswith('/'): - # Special case. Absolute paths are in dstSubfolderSpec 0. - subfolder = 0 - relative_path = path[1:] - else: - raise ValueError('Can\'t use path %s in a %s' % \ - (path, self.__class__.__name__)) - - self._properties['dstPath'] = relative_path - self._properties['dstSubfolderSpec'] = subfolder - - -class PBXBuildRule(XCObject): - _schema = XCObject._schema.copy() - _schema.update({ - 'compilerSpec': [0, str, 0, 1], - 'filePatterns': [0, str, 0, 0], - 'fileType': [0, str, 0, 1], - 'isEditable': [0, int, 0, 1, 1], - 'outputFiles': [1, str, 0, 1, []], - 'script': [0, str, 0, 0], - }) - - def Name(self): - # Not very inspired, but it's what Xcode uses. - return self.__class__.__name__ - - def Hashables(self): - # super - hashables = XCObject.Hashables(self) - - # Use the hashables of the weak objects that this object refers to. - hashables.append(self._properties['fileType']) - if 'filePatterns' in self._properties: - hashables.append(self._properties['filePatterns']) - return hashables - - -class PBXContainerItemProxy(XCObject): - # When referencing an item in this project file, containerPortal is the - # PBXProject root object of this project file. When referencing an item in - # another project file, containerPortal is a PBXFileReference identifying - # the other project file. - # - # When serving as a proxy to an XCTarget (in this project file or another), - # proxyType is 1. When serving as a proxy to a PBXFileReference (in another - # project file), proxyType is 2. Type 2 is used for references to the - # producs of the other project file's targets. - # - # Xcode is weird about remoteGlobalIDString. Usually, it's printed without - # a comment, indicating that it's tracked internally simply as a string, but - # sometimes it's printed with a comment (usually when the object is initially - # created), indicating that it's tracked as a project file object at least - # sometimes. This module always tracks it as an object, but contains a hack - # to prevent it from printing the comment in the project file output. See - # _XCKVPrint. - _schema = XCObject._schema.copy() - _schema.update({ - 'containerPortal': [0, XCContainerPortal, 0, 1], - 'proxyType': [0, int, 0, 1], - 'remoteGlobalIDString': [0, XCRemoteObject, 0, 1], - 'remoteInfo': [0, str, 0, 1], - }) - - def __repr__(self): - props = self._properties - name = '%s.gyp:%s' % (props['containerPortal'].Name(), props['remoteInfo']) - return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self)) - - def Name(self): - # Admittedly not the best name, but it's what Xcode uses. - return self.__class__.__name__ - - def Hashables(self): - # super - hashables = XCObject.Hashables(self) - - # Use the hashables of the weak objects that this object refers to. - hashables.extend(self._properties['containerPortal'].Hashables()) - hashables.extend(self._properties['remoteGlobalIDString'].Hashables()) - return hashables - - -class PBXTargetDependency(XCObject): - # The "target" property accepts an XCTarget object, and obviously not - # NoneType. But XCTarget is defined below, so it can't be put into the - # schema yet. The definition of PBXTargetDependency can't be moved below - # XCTarget because XCTarget's own schema references PBXTargetDependency. - # Python doesn't deal well with this circular relationship, and doesn't have - # a real way to do forward declarations. To work around, the type of - # the "target" property is reset below, after XCTarget is defined. - # - # At least one of "name" and "target" is required. - _schema = XCObject._schema.copy() - _schema.update({ - 'name': [0, str, 0, 0], - 'target': [0, None.__class__, 0, 0], - 'targetProxy': [0, PBXContainerItemProxy, 1, 1], - }) - - def __repr__(self): - name = self._properties.get('name') or self._properties['target'].Name() - return '<%s %r at 0x%x>' % (self.__class__.__name__, name, id(self)) - - def Name(self): - # Admittedly not the best name, but it's what Xcode uses. - return self.__class__.__name__ - - def Hashables(self): - # super - hashables = XCObject.Hashables(self) - - # Use the hashables of the weak objects that this object refers to. - hashables.extend(self._properties['targetProxy'].Hashables()) - return hashables - - -class PBXReferenceProxy(XCFileLikeElement): - _schema = XCFileLikeElement._schema.copy() - _schema.update({ - 'fileType': [0, str, 0, 1], - 'path': [0, str, 0, 1], - 'remoteRef': [0, PBXContainerItemProxy, 1, 1], - }) - - -class XCTarget(XCRemoteObject): - # An XCTarget is really just an XCObject, the XCRemoteObject thing is just - # to allow PBXProject to be used in the remoteGlobalIDString property of - # PBXContainerItemProxy. - # - # Setting a "name" property at instantiation may also affect "productName", - # which may in turn affect the "PRODUCT_NAME" build setting in children of - # "buildConfigurationList". See __init__ below. - _schema = XCRemoteObject._schema.copy() - _schema.update({ - 'buildConfigurationList': [0, XCConfigurationList, 1, 1, - XCConfigurationList()], - 'buildPhases': [1, XCBuildPhase, 1, 1, []], - 'dependencies': [1, PBXTargetDependency, 1, 1, []], - 'name': [0, str, 0, 1], - 'productName': [0, str, 0, 1], - }) - - def __init__(self, properties=None, id=None, parent=None, - force_outdir=None, force_prefix=None, force_extension=None): - # super - XCRemoteObject.__init__(self, properties, id, parent) - - # Set up additional defaults not expressed in the schema. If a "name" - # property was supplied, set "productName" if it is not present. Also set - # the "PRODUCT_NAME" build setting in each configuration, but only if - # the setting is not present in any build configuration. - if 'name' in self._properties: - if not 'productName' in self._properties: - self.SetProperty('productName', self._properties['name']) - - if 'productName' in self._properties: - if 'buildConfigurationList' in self._properties: - configs = self._properties['buildConfigurationList'] - if configs.HasBuildSetting('PRODUCT_NAME') == 0: - configs.SetBuildSetting('PRODUCT_NAME', - self._properties['productName']) - - def AddDependency(self, other): - pbxproject = self.PBXProjectAncestor() - other_pbxproject = other.PBXProjectAncestor() - if pbxproject == other_pbxproject: - # Add a dependency to another target in the same project file. - container = PBXContainerItemProxy({'containerPortal': pbxproject, - 'proxyType': 1, - 'remoteGlobalIDString': other, - 'remoteInfo': other.Name()}) - dependency = PBXTargetDependency({'target': other, - 'targetProxy': container}) - self.AppendProperty('dependencies', dependency) - else: - # Add a dependency to a target in a different project file. - other_project_ref = \ - pbxproject.AddOrGetProjectReference(other_pbxproject)[1] - container = PBXContainerItemProxy({ - 'containerPortal': other_project_ref, - 'proxyType': 1, - 'remoteGlobalIDString': other, - 'remoteInfo': other.Name(), - }) - dependency = PBXTargetDependency({'name': other.Name(), - 'targetProxy': container}) - self.AppendProperty('dependencies', dependency) - - # Proxy all of these through to the build configuration list. - - def ConfigurationNamed(self, name): - return self._properties['buildConfigurationList'].ConfigurationNamed(name) - - def DefaultConfiguration(self): - return self._properties['buildConfigurationList'].DefaultConfiguration() - - def HasBuildSetting(self, key): - return self._properties['buildConfigurationList'].HasBuildSetting(key) - - def GetBuildSetting(self, key): - return self._properties['buildConfigurationList'].GetBuildSetting(key) - - def SetBuildSetting(self, key, value): - return self._properties['buildConfigurationList'].SetBuildSetting(key, \ - value) - - def AppendBuildSetting(self, key, value): - return self._properties['buildConfigurationList'].AppendBuildSetting(key, \ - value) - - def DelBuildSetting(self, key): - return self._properties['buildConfigurationList'].DelBuildSetting(key) - - -# Redefine the type of the "target" property. See PBXTargetDependency._schema -# above. -PBXTargetDependency._schema['target'][1] = XCTarget - - -class PBXNativeTarget(XCTarget): - # buildPhases is overridden in the schema to be able to set defaults. - # - # NOTE: Contrary to most objects, it is advisable to set parent when - # constructing PBXNativeTarget. A parent of an XCTarget must be a PBXProject - # object. A parent reference is required for a PBXNativeTarget during - # construction to be able to set up the target defaults for productReference, - # because a PBXBuildFile object must be created for the target and it must - # be added to the PBXProject's mainGroup hierarchy. - _schema = XCTarget._schema.copy() - _schema.update({ - 'buildPhases': [1, XCBuildPhase, 1, 1, - [PBXSourcesBuildPhase(), PBXFrameworksBuildPhase()]], - 'buildRules': [1, PBXBuildRule, 1, 1, []], - 'productReference': [0, PBXFileReference, 0, 1], - 'productType': [0, str, 0, 1], - }) - - # Mapping from Xcode product-types to settings. The settings are: - # filetype : used for explicitFileType in the project file - # prefix : the prefix for the file name - # suffix : the suffix for the file name - _product_filetypes = { - 'com.apple.product-type.application': ['wrapper.application', - '', '.app'], - 'com.apple.product-type.application.watchapp': ['wrapper.application', - '', '.app'], - 'com.apple.product-type.watchkit-extension': ['wrapper.app-extension', - '', '.appex'], - 'com.apple.product-type.app-extension': ['wrapper.app-extension', - '', '.appex'], - 'com.apple.product-type.bundle': ['wrapper.cfbundle', - '', '.bundle'], - 'com.apple.product-type.framework': ['wrapper.framework', - '', '.framework'], - 'com.apple.product-type.library.dynamic': ['compiled.mach-o.dylib', - 'lib', '.dylib'], - 'com.apple.product-type.library.static': ['archive.ar', - 'lib', '.a'], - 'com.apple.product-type.tool': ['compiled.mach-o.executable', - '', ''], - 'com.apple.product-type.bundle.unit-test': ['wrapper.cfbundle', - '', '.xctest'], - 'com.googlecode.gyp.xcode.bundle': ['compiled.mach-o.dylib', - '', '.so'], - 'com.apple.product-type.kernel-extension': ['wrapper.kext', - '', '.kext'], - } - - def __init__(self, properties=None, id=None, parent=None, - force_outdir=None, force_prefix=None, force_extension=None): - # super - XCTarget.__init__(self, properties, id, parent) - - if 'productName' in self._properties and \ - 'productType' in self._properties and \ - not 'productReference' in self._properties and \ - self._properties['productType'] in self._product_filetypes: - products_group = None - pbxproject = self.PBXProjectAncestor() - if pbxproject != None: - products_group = pbxproject.ProductsGroup() - - if products_group != None: - (filetype, prefix, suffix) = \ - self._product_filetypes[self._properties['productType']] - # Xcode does not have a distinct type for loadable modules that are - # pure BSD targets (not in a bundle wrapper). GYP allows such modules - # to be specified by setting a target type to loadable_module without - # having mac_bundle set. These are mapped to the pseudo-product type - # com.googlecode.gyp.xcode.bundle. - # - # By picking up this special type and converting it to a dynamic - # library (com.apple.product-type.library.dynamic) with fix-ups, - # single-file loadable modules can be produced. - # - # MACH_O_TYPE is changed to mh_bundle to produce the proper file type - # (as opposed to mh_dylib). In order for linking to succeed, - # DYLIB_CURRENT_VERSION and DYLIB_COMPATIBILITY_VERSION must be - # cleared. They are meaningless for type mh_bundle. - # - # Finally, the .so extension is forcibly applied over the default - # (.dylib), unless another forced extension is already selected. - # .dylib is plainly wrong, and .bundle is used by loadable_modules in - # bundle wrappers (com.apple.product-type.bundle). .so seems an odd - # choice because it's used as the extension on many other systems that - # don't distinguish between linkable shared libraries and non-linkable - # loadable modules, but there's precedent: Python loadable modules on - # Mac OS X use an .so extension. - if self._properties['productType'] == 'com.googlecode.gyp.xcode.bundle': - self._properties['productType'] = \ - 'com.apple.product-type.library.dynamic' - self.SetBuildSetting('MACH_O_TYPE', 'mh_bundle') - self.SetBuildSetting('DYLIB_CURRENT_VERSION', '') - self.SetBuildSetting('DYLIB_COMPATIBILITY_VERSION', '') - if force_extension is None: - force_extension = suffix[1:] - - if self._properties['productType'] == \ - 'com.apple.product-type-bundle.unit.test': - if force_extension is None: - force_extension = suffix[1:] - - if force_extension is not None: - # If it's a wrapper (bundle), set WRAPPER_EXTENSION. - # Extension override. - suffix = '.' + force_extension - if filetype.startswith('wrapper.'): - self.SetBuildSetting('WRAPPER_EXTENSION', force_extension) - else: - self.SetBuildSetting('EXECUTABLE_EXTENSION', force_extension) - - if filetype.startswith('compiled.mach-o.executable'): - product_name = self._properties['productName'] - product_name += suffix - suffix = '' - self.SetProperty('productName', product_name) - self.SetBuildSetting('PRODUCT_NAME', product_name) - - # Xcode handles most prefixes based on the target type, however there - # are exceptions. If a "BSD Dynamic Library" target is added in the - # Xcode UI, Xcode sets EXECUTABLE_PREFIX. This check duplicates that - # behavior. - if force_prefix is not None: - prefix = force_prefix - if filetype.startswith('wrapper.'): - self.SetBuildSetting('WRAPPER_PREFIX', prefix) - else: - self.SetBuildSetting('EXECUTABLE_PREFIX', prefix) - - if force_outdir is not None: - self.SetBuildSetting('TARGET_BUILD_DIR', force_outdir) - - # TODO(tvl): Remove the below hack. - # http://code.google.com/p/gyp/issues/detail?id=122 - - # Some targets include the prefix in the target_name. These targets - # really should just add a product_name setting that doesn't include - # the prefix. For example: - # target_name = 'libevent', product_name = 'event' - # This check cleans up for them. - product_name = self._properties['productName'] - prefix_len = len(prefix) - if prefix_len and (product_name[:prefix_len] == prefix): - product_name = product_name[prefix_len:] - self.SetProperty('productName', product_name) - self.SetBuildSetting('PRODUCT_NAME', product_name) - - ref_props = { - 'explicitFileType': filetype, - 'includeInIndex': 0, - 'path': prefix + product_name + suffix, - 'sourceTree': 'BUILT_PRODUCTS_DIR', - } - file_ref = PBXFileReference(ref_props) - products_group.AppendChild(file_ref) - self.SetProperty('productReference', file_ref) - - def GetBuildPhaseByType(self, type): - if not 'buildPhases' in self._properties: - return None - - the_phase = None - for phase in self._properties['buildPhases']: - if isinstance(phase, type): - # Some phases may be present in multiples in a well-formed project file, - # but phases like PBXSourcesBuildPhase may only be present singly, and - # this function is intended as an aid to GetBuildPhaseByType. Loop - # over the entire list of phases and assert if more than one of the - # desired type is found. - assert the_phase is None - the_phase = phase - - return the_phase - - def HeadersPhase(self): - headers_phase = self.GetBuildPhaseByType(PBXHeadersBuildPhase) - if headers_phase is None: - headers_phase = PBXHeadersBuildPhase() - - # The headers phase should come before the resources, sources, and - # frameworks phases, if any. - insert_at = len(self._properties['buildPhases']) - for index in xrange(0, len(self._properties['buildPhases'])): - phase = self._properties['buildPhases'][index] - if isinstance(phase, PBXResourcesBuildPhase) or \ - isinstance(phase, PBXSourcesBuildPhase) or \ - isinstance(phase, PBXFrameworksBuildPhase): - insert_at = index - break - - self._properties['buildPhases'].insert(insert_at, headers_phase) - headers_phase.parent = self - - return headers_phase - - def ResourcesPhase(self): - resources_phase = self.GetBuildPhaseByType(PBXResourcesBuildPhase) - if resources_phase is None: - resources_phase = PBXResourcesBuildPhase() - - # The resources phase should come before the sources and frameworks - # phases, if any. - insert_at = len(self._properties['buildPhases']) - for index in xrange(0, len(self._properties['buildPhases'])): - phase = self._properties['buildPhases'][index] - if isinstance(phase, PBXSourcesBuildPhase) or \ - isinstance(phase, PBXFrameworksBuildPhase): - insert_at = index - break - - self._properties['buildPhases'].insert(insert_at, resources_phase) - resources_phase.parent = self - - return resources_phase - - def SourcesPhase(self): - sources_phase = self.GetBuildPhaseByType(PBXSourcesBuildPhase) - if sources_phase is None: - sources_phase = PBXSourcesBuildPhase() - self.AppendProperty('buildPhases', sources_phase) - - return sources_phase - - def FrameworksPhase(self): - frameworks_phase = self.GetBuildPhaseByType(PBXFrameworksBuildPhase) - if frameworks_phase is None: - frameworks_phase = PBXFrameworksBuildPhase() - self.AppendProperty('buildPhases', frameworks_phase) - - return frameworks_phase - - def AddDependency(self, other): - # super - XCTarget.AddDependency(self, other) - - static_library_type = 'com.apple.product-type.library.static' - shared_library_type = 'com.apple.product-type.library.dynamic' - framework_type = 'com.apple.product-type.framework' - if isinstance(other, PBXNativeTarget) and \ - 'productType' in self._properties and \ - self._properties['productType'] != static_library_type and \ - 'productType' in other._properties and \ - (other._properties['productType'] == static_library_type or \ - ((other._properties['productType'] == shared_library_type or \ - other._properties['productType'] == framework_type) and \ - ((not other.HasBuildSetting('MACH_O_TYPE')) or - other.GetBuildSetting('MACH_O_TYPE') != 'mh_bundle'))): - - file_ref = other.GetProperty('productReference') - - pbxproject = self.PBXProjectAncestor() - other_pbxproject = other.PBXProjectAncestor() - if pbxproject != other_pbxproject: - other_project_product_group = \ - pbxproject.AddOrGetProjectReference(other_pbxproject)[0] - file_ref = other_project_product_group.GetChildByRemoteObject(file_ref) - - self.FrameworksPhase().AppendProperty('files', - PBXBuildFile({'fileRef': file_ref})) - - -class PBXAggregateTarget(XCTarget): - pass - - -class PBXProject(XCContainerPortal): - # A PBXProject is really just an XCObject, the XCContainerPortal thing is - # just to allow PBXProject to be used in the containerPortal property of - # PBXContainerItemProxy. - """ - - Attributes: - path: "sample.xcodeproj". TODO(mark) Document me! - _other_pbxprojects: A dictionary, keyed by other PBXProject objects. Each - value is a reference to the dict in the - projectReferences list associated with the keyed - PBXProject. - """ - - _schema = XCContainerPortal._schema.copy() - _schema.update({ - 'attributes': [0, dict, 0, 0], - 'buildConfigurationList': [0, XCConfigurationList, 1, 1, - XCConfigurationList()], - 'compatibilityVersion': [0, str, 0, 1, 'Xcode 3.2'], - 'hasScannedForEncodings': [0, int, 0, 1, 1], - 'mainGroup': [0, PBXGroup, 1, 1, PBXGroup()], - 'projectDirPath': [0, str, 0, 1, ''], - 'projectReferences': [1, dict, 0, 0], - 'projectRoot': [0, str, 0, 1, ''], - 'targets': [1, XCTarget, 1, 1, []], - }) - - def __init__(self, properties=None, id=None, parent=None, path=None): - self.path = path - self._other_pbxprojects = {} - # super - return XCContainerPortal.__init__(self, properties, id, parent) - - def Name(self): - name = self.path - if name[-10:] == '.xcodeproj': - name = name[:-10] - return posixpath.basename(name) - - def Path(self): - return self.path - - def Comment(self): - return 'Project object' - - def Children(self): - # super - children = XCContainerPortal.Children(self) - - # Add children that the schema doesn't know about. Maybe there's a more - # elegant way around this, but this is the only case where we need to own - # objects in a dictionary (that is itself in a list), and three lines for - # a one-off isn't that big a deal. - if 'projectReferences' in self._properties: - for reference in self._properties['projectReferences']: - children.append(reference['ProductGroup']) - - return children - - def PBXProjectAncestor(self): - return self - - def _GroupByName(self, name): - if not 'mainGroup' in self._properties: - self.SetProperty('mainGroup', PBXGroup()) - - main_group = self._properties['mainGroup'] - group = main_group.GetChildByName(name) - if group is None: - group = PBXGroup({'name': name}) - main_group.AppendChild(group) - - return group - - # SourceGroup and ProductsGroup are created by default in Xcode's own - # templates. - def SourceGroup(self): - return self._GroupByName('Source') - - def ProductsGroup(self): - return self._GroupByName('Products') - - # IntermediatesGroup is used to collect source-like files that are generated - # by rules or script phases and are placed in intermediate directories such - # as DerivedSources. - def IntermediatesGroup(self): - return self._GroupByName('Intermediates') - - # FrameworksGroup and ProjectsGroup are top-level groups used to collect - # frameworks and projects. - def FrameworksGroup(self): - return self._GroupByName('Frameworks') - - def ProjectsGroup(self): - return self._GroupByName('Projects') - - def RootGroupForPath(self, path): - """Returns a PBXGroup child of this object to which path should be added. - - This method is intended to choose between SourceGroup and - IntermediatesGroup on the basis of whether path is present in a source - directory or an intermediates directory. For the purposes of this - determination, any path located within a derived file directory such as - PROJECT_DERIVED_FILE_DIR is treated as being in an intermediates - directory. - - The returned value is a two-element tuple. The first element is the - PBXGroup, and the second element specifies whether that group should be - organized hierarchically (True) or as a single flat list (False). - """ - - # TODO(mark): make this a class variable and bind to self on call? - # Also, this list is nowhere near exhaustive. - # INTERMEDIATE_DIR and SHARED_INTERMEDIATE_DIR are used by - # gyp.generator.xcode. There should probably be some way for that module - # to push the names in, rather than having to hard-code them here. - source_tree_groups = { - 'DERIVED_FILE_DIR': (self.IntermediatesGroup, True), - 'INTERMEDIATE_DIR': (self.IntermediatesGroup, True), - 'PROJECT_DERIVED_FILE_DIR': (self.IntermediatesGroup, True), - 'SHARED_INTERMEDIATE_DIR': (self.IntermediatesGroup, True), - } - - (source_tree, path) = SourceTreeAndPathFromPath(path) - if source_tree != None and source_tree in source_tree_groups: - (group_func, hierarchical) = source_tree_groups[source_tree] - group = group_func() - return (group, hierarchical) - - # TODO(mark): make additional choices based on file extension. - - return (self.SourceGroup(), True) - - def AddOrGetFileInRootGroup(self, path): - """Returns a PBXFileReference corresponding to path in the correct group - according to RootGroupForPath's heuristics. - - If an existing PBXFileReference for path exists, it will be returned. - Otherwise, one will be created and returned. - """ - - (group, hierarchical) = self.RootGroupForPath(path) - return group.AddOrGetFileByPath(path, hierarchical) - - def RootGroupsTakeOverOnlyChildren(self, recurse=False): - """Calls TakeOverOnlyChild for all groups in the main group.""" - - for group in self._properties['mainGroup']._properties['children']: - if isinstance(group, PBXGroup): - group.TakeOverOnlyChild(recurse) - - def SortGroups(self): - # Sort the children of the mainGroup (like "Source" and "Products") - # according to their defined order. - self._properties['mainGroup']._properties['children'] = \ - sorted(self._properties['mainGroup']._properties['children'], - cmp=lambda x,y: x.CompareRootGroup(y)) - - # Sort everything else by putting group before files, and going - # alphabetically by name within sections of groups and files. SortGroup - # is recursive. - for group in self._properties['mainGroup']._properties['children']: - if not isinstance(group, PBXGroup): - continue - - if group.Name() == 'Products': - # The Products group is a special case. Instead of sorting - # alphabetically, sort things in the order of the targets that - # produce the products. To do this, just build up a new list of - # products based on the targets. - products = [] - for target in self._properties['targets']: - if not isinstance(target, PBXNativeTarget): - continue - product = target._properties['productReference'] - # Make sure that the product is already in the products group. - assert product in group._properties['children'] - products.append(product) - - # Make sure that this process doesn't miss anything that was already - # in the products group. - assert len(products) == len(group._properties['children']) - group._properties['children'] = products - else: - group.SortGroup() - - def AddOrGetProjectReference(self, other_pbxproject): - """Add a reference to another project file (via PBXProject object) to this - one. - - Returns [ProductGroup, ProjectRef]. ProductGroup is a PBXGroup object in - this project file that contains a PBXReferenceProxy object for each - product of each PBXNativeTarget in the other project file. ProjectRef is - a PBXFileReference to the other project file. - - If this project file already references the other project file, the - existing ProductGroup and ProjectRef are returned. The ProductGroup will - still be updated if necessary. - """ - - if not 'projectReferences' in self._properties: - self._properties['projectReferences'] = [] - - product_group = None - project_ref = None - - if not other_pbxproject in self._other_pbxprojects: - # This project file isn't yet linked to the other one. Establish the - # link. - product_group = PBXGroup({'name': 'Products'}) - - # ProductGroup is strong. - product_group.parent = self - - # There's nothing unique about this PBXGroup, and if left alone, it will - # wind up with the same set of hashables as all other PBXGroup objects - # owned by the projectReferences list. Add the hashables of the - # remote PBXProject that it's related to. - product_group._hashables.extend(other_pbxproject.Hashables()) - - # The other project reports its path as relative to the same directory - # that this project's path is relative to. The other project's path - # is not necessarily already relative to this project. Figure out the - # pathname that this project needs to use to refer to the other one. - this_path = posixpath.dirname(self.Path()) - projectDirPath = self.GetProperty('projectDirPath') - if projectDirPath: - if posixpath.isabs(projectDirPath[0]): - this_path = projectDirPath - else: - this_path = posixpath.join(this_path, projectDirPath) - other_path = gyp.common.RelativePath(other_pbxproject.Path(), this_path) - - # ProjectRef is weak (it's owned by the mainGroup hierarchy). - project_ref = PBXFileReference({ - 'lastKnownFileType': 'wrapper.pb-project', - 'path': other_path, - 'sourceTree': 'SOURCE_ROOT', - }) - self.ProjectsGroup().AppendChild(project_ref) - - ref_dict = {'ProductGroup': product_group, 'ProjectRef': project_ref} - self._other_pbxprojects[other_pbxproject] = ref_dict - self.AppendProperty('projectReferences', ref_dict) - - # Xcode seems to sort this list case-insensitively - self._properties['projectReferences'] = \ - sorted(self._properties['projectReferences'], cmp=lambda x,y: - cmp(x['ProjectRef'].Name().lower(), - y['ProjectRef'].Name().lower())) - else: - # The link already exists. Pull out the relevnt data. - project_ref_dict = self._other_pbxprojects[other_pbxproject] - product_group = project_ref_dict['ProductGroup'] - project_ref = project_ref_dict['ProjectRef'] - - self._SetUpProductReferences(other_pbxproject, product_group, project_ref) - - inherit_unique_symroot = self._AllSymrootsUnique(other_pbxproject, False) - targets = other_pbxproject.GetProperty('targets') - if all(self._AllSymrootsUnique(t, inherit_unique_symroot) for t in targets): - dir_path = project_ref._properties['path'] - product_group._hashables.extend(dir_path) - - return [product_group, project_ref] - - def _AllSymrootsUnique(self, target, inherit_unique_symroot): - # Returns True if all configurations have a unique 'SYMROOT' attribute. - # The value of inherit_unique_symroot decides, if a configuration is assumed - # to inherit a unique 'SYMROOT' attribute from its parent, if it doesn't - # define an explicit value for 'SYMROOT'. - symroots = self._DefinedSymroots(target) - for s in self._DefinedSymroots(target): - if (s is not None and not self._IsUniqueSymrootForTarget(s) or - s is None and not inherit_unique_symroot): - return False - return True if symroots else inherit_unique_symroot - - def _DefinedSymroots(self, target): - # Returns all values for the 'SYMROOT' attribute defined in all - # configurations for this target. If any configuration doesn't define the - # 'SYMROOT' attribute, None is added to the returned set. If all - # configurations don't define the 'SYMROOT' attribute, an empty set is - # returned. - config_list = target.GetProperty('buildConfigurationList') - symroots = set() - for config in config_list.GetProperty('buildConfigurations'): - setting = config.GetProperty('buildSettings') - if 'SYMROOT' in setting: - symroots.add(setting['SYMROOT']) - else: - symroots.add(None) - if len(symroots) == 1 and None in symroots: - return set() - return symroots - - def _IsUniqueSymrootForTarget(self, symroot): - # This method returns True if all configurations in target contain a - # 'SYMROOT' attribute that is unique for the given target. A value is - # unique, if the Xcode macro '$SRCROOT' appears in it in any form. - uniquifier = ['$SRCROOT', '$(SRCROOT)'] - if any(x in symroot for x in uniquifier): - return True - return False - - def _SetUpProductReferences(self, other_pbxproject, product_group, - project_ref): - # TODO(mark): This only adds references to products in other_pbxproject - # when they don't exist in this pbxproject. Perhaps it should also - # remove references from this pbxproject that are no longer present in - # other_pbxproject. Perhaps it should update various properties if they - # change. - for target in other_pbxproject._properties['targets']: - if not isinstance(target, PBXNativeTarget): - continue - - other_fileref = target._properties['productReference'] - if product_group.GetChildByRemoteObject(other_fileref) is None: - # Xcode sets remoteInfo to the name of the target and not the name - # of its product, despite this proxy being a reference to the product. - container_item = PBXContainerItemProxy({ - 'containerPortal': project_ref, - 'proxyType': 2, - 'remoteGlobalIDString': other_fileref, - 'remoteInfo': target.Name() - }) - # TODO(mark): Does sourceTree get copied straight over from the other - # project? Can the other project ever have lastKnownFileType here - # instead of explicitFileType? (Use it if so?) Can path ever be - # unset? (I don't think so.) Can other_fileref have name set, and - # does it impact the PBXReferenceProxy if so? These are the questions - # that perhaps will be answered one day. - reference_proxy = PBXReferenceProxy({ - 'fileType': other_fileref._properties['explicitFileType'], - 'path': other_fileref._properties['path'], - 'sourceTree': other_fileref._properties['sourceTree'], - 'remoteRef': container_item, - }) - - product_group.AppendChild(reference_proxy) - - def SortRemoteProductReferences(self): - # For each remote project file, sort the associated ProductGroup in the - # same order that the targets are sorted in the remote project file. This - # is the sort order used by Xcode. - - def CompareProducts(x, y, remote_products): - # x and y are PBXReferenceProxy objects. Go through their associated - # PBXContainerItem to get the remote PBXFileReference, which will be - # present in the remote_products list. - x_remote = x._properties['remoteRef']._properties['remoteGlobalIDString'] - y_remote = y._properties['remoteRef']._properties['remoteGlobalIDString'] - x_index = remote_products.index(x_remote) - y_index = remote_products.index(y_remote) - - # Use the order of each remote PBXFileReference in remote_products to - # determine the sort order. - return cmp(x_index, y_index) - - for other_pbxproject, ref_dict in self._other_pbxprojects.iteritems(): - # Build up a list of products in the remote project file, ordered the - # same as the targets that produce them. - remote_products = [] - for target in other_pbxproject._properties['targets']: - if not isinstance(target, PBXNativeTarget): - continue - remote_products.append(target._properties['productReference']) - - # Sort the PBXReferenceProxy children according to the list of remote - # products. - product_group = ref_dict['ProductGroup'] - product_group._properties['children'] = sorted( - product_group._properties['children'], - cmp=lambda x, y, rp=remote_products: CompareProducts(x, y, rp)) - - -class XCProjectFile(XCObject): - _schema = XCObject._schema.copy() - _schema.update({ - 'archiveVersion': [0, int, 0, 1, 1], - 'classes': [0, dict, 0, 1, {}], - 'objectVersion': [0, int, 0, 1, 46], - 'rootObject': [0, PBXProject, 1, 1], - }) - - def ComputeIDs(self, recursive=True, overwrite=True, hash=None): - # Although XCProjectFile is implemented here as an XCObject, it's not a - # proper object in the Xcode sense, and it certainly doesn't have its own - # ID. Pass through an attempt to update IDs to the real root object. - if recursive: - self._properties['rootObject'].ComputeIDs(recursive, overwrite, hash) - - def Print(self, file=sys.stdout): - self.VerifyHasRequiredProperties() - - # Add the special "objects" property, which will be caught and handled - # separately during printing. This structure allows a fairly standard - # loop do the normal printing. - self._properties['objects'] = {} - self._XCPrint(file, 0, '// !$*UTF8*$!\n') - if self._should_print_single_line: - self._XCPrint(file, 0, '{ ') - else: - self._XCPrint(file, 0, '{\n') - for property, value in sorted(self._properties.iteritems(), - cmp=lambda x, y: cmp(x, y)): - if property == 'objects': - self._PrintObjects(file) - else: - self._XCKVPrint(file, 1, property, value) - self._XCPrint(file, 0, '}\n') - del self._properties['objects'] - - def _PrintObjects(self, file): - if self._should_print_single_line: - self._XCPrint(file, 0, 'objects = {') - else: - self._XCPrint(file, 1, 'objects = {\n') - - objects_by_class = {} - for object in self.Descendants(): - if object == self: - continue - class_name = object.__class__.__name__ - if not class_name in objects_by_class: - objects_by_class[class_name] = [] - objects_by_class[class_name].append(object) - - for class_name in sorted(objects_by_class): - self._XCPrint(file, 0, '\n') - self._XCPrint(file, 0, '/* Begin ' + class_name + ' section */\n') - for object in sorted(objects_by_class[class_name], - cmp=lambda x, y: cmp(x.id, y.id)): - object.Print(file) - self._XCPrint(file, 0, '/* End ' + class_name + ' section */\n') - - if self._should_print_single_line: - self._XCPrint(file, 0, '}; ') - else: - self._XCPrint(file, 1, '};\n') diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py deleted file mode 100644 index 5de848158d289..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/pylib/gyp/xml_fix.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (c) 2011 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. - -"""Applies a fix to CR LF TAB handling in xml.dom. - -Fixes this: http://code.google.com/p/chromium/issues/detail?id=76293 -Working around this: http://bugs.python.org/issue5752 -TODO(bradnelson): Consider dropping this when we drop XP support. -""" - - -import xml.dom.minidom - - -def _Replacement_write_data(writer, data, is_attrib=False): - """Writes datachars to writer.""" - data = data.replace("&", "&").replace("<", "<") - data = data.replace("\"", """).replace(">", ">") - if is_attrib: - data = data.replace( - "\r", " ").replace( - "\n", " ").replace( - "\t", " ") - writer.write(data) - - -def _Replacement_writexml(self, writer, indent="", addindent="", newl=""): - # indent = current indentation - # addindent = indentation to add to higher levels - # newl = newline string - writer.write(indent+"<" + self.tagName) - - attrs = self._get_attributes() - a_names = attrs.keys() - a_names.sort() - - for a_name in a_names: - writer.write(" %s=\"" % a_name) - _Replacement_write_data(writer, attrs[a_name].value, is_attrib=True) - writer.write("\"") - if self.childNodes: - writer.write(">%s" % newl) - for node in self.childNodes: - node.writexml(writer, indent + addindent, addindent, newl) - writer.write("%s%s" % (indent, self.tagName, newl)) - else: - writer.write("/>%s" % newl) - - -class XmlFix(object): - """Object to manage temporary patching of xml.dom.minidom.""" - - def __init__(self): - # Preserve current xml.dom.minidom functions. - self.write_data = xml.dom.minidom._write_data - self.writexml = xml.dom.minidom.Element.writexml - # Inject replacement versions of a function and a method. - xml.dom.minidom._write_data = _Replacement_write_data - xml.dom.minidom.Element.writexml = _Replacement_writexml - - def Cleanup(self): - if self.write_data: - xml.dom.minidom._write_data = self.write_data - xml.dom.minidom.Element.writexml = self.writexml - self.write_data = None - - def __del__(self): - self.Cleanup() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples deleted file mode 100755 index 804b618998747..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples +++ /dev/null @@ -1,81 +0,0 @@ -#!/usr/bin/python - -# Copyright (c) 2009 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. - -import os.path -import shutil -import sys - - -gyps = [ - 'app/app.gyp', - 'base/base.gyp', - 'build/temp_gyp/googleurl.gyp', - 'build/all.gyp', - 'build/common.gypi', - 'build/external_code.gypi', - 'chrome/test/security_tests/security_tests.gyp', - 'chrome/third_party/hunspell/hunspell.gyp', - 'chrome/chrome.gyp', - 'media/media.gyp', - 'net/net.gyp', - 'printing/printing.gyp', - 'sdch/sdch.gyp', - 'skia/skia.gyp', - 'testing/gmock.gyp', - 'testing/gtest.gyp', - 'third_party/bzip2/bzip2.gyp', - 'third_party/icu38/icu38.gyp', - 'third_party/libevent/libevent.gyp', - 'third_party/libjpeg/libjpeg.gyp', - 'third_party/libpng/libpng.gyp', - 'third_party/libxml/libxml.gyp', - 'third_party/libxslt/libxslt.gyp', - 'third_party/lzma_sdk/lzma_sdk.gyp', - 'third_party/modp_b64/modp_b64.gyp', - 'third_party/npapi/npapi.gyp', - 'third_party/sqlite/sqlite.gyp', - 'third_party/zlib/zlib.gyp', - 'v8/tools/gyp/v8.gyp', - 'webkit/activex_shim/activex_shim.gyp', - 'webkit/activex_shim_dll/activex_shim_dll.gyp', - 'webkit/build/action_csspropertynames.py', - 'webkit/build/action_cssvaluekeywords.py', - 'webkit/build/action_jsconfig.py', - 'webkit/build/action_makenames.py', - 'webkit/build/action_maketokenizer.py', - 'webkit/build/action_useragentstylesheets.py', - 'webkit/build/rule_binding.py', - 'webkit/build/rule_bison.py', - 'webkit/build/rule_gperf.py', - 'webkit/tools/test_shell/test_shell.gyp', - 'webkit/webkit.gyp', -] - - -def Main(argv): - if len(argv) != 3 or argv[1] not in ['push', 'pull']: - print 'Usage: %s push/pull PATH_TO_CHROME' % argv[0] - return 1 - - path_to_chrome = argv[2] - - for g in gyps: - chrome_file = os.path.join(path_to_chrome, g) - local_file = os.path.join(os.path.dirname(argv[0]), os.path.split(g)[1]) - if argv[1] == 'push': - print 'Copying %s to %s' % (local_file, chrome_file) - shutil.copyfile(local_file, chrome_file) - elif argv[1] == 'pull': - print 'Copying %s to %s' % (chrome_file, local_file) - shutil.copyfile(chrome_file, local_file) - else: - assert False - - return 0 - - -if __name__ == '__main__': - sys.exit(Main(sys.argv)) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples.bat b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples.bat deleted file mode 100644 index 778d9c90f0606..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/samples/samples.bat +++ /dev/null @@ -1,5 +0,0 @@ -@rem Copyright (c) 2009 Google Inc. All rights reserved. -@rem Use of this source code is governed by a BSD-style license that can be -@rem found in the LICENSE file. - -@python %~dp0/samples %* diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/setup.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/setup.py deleted file mode 100755 index 75a42558d8026..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/setup.py +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2009 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. - -from setuptools import setup - -setup( - name='gyp', - version='0.1', - description='Generate Your Projects', - author='Chromium Authors', - author_email='chromium-dev@googlegroups.com', - url='http://code.google.com/p/gyp', - package_dir = {'': 'pylib'}, - packages=['gyp', 'gyp.generator'], - entry_points = {'console_scripts': ['gyp=gyp:script_main'] } -) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/README b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/README deleted file mode 100644 index 712e4efbb7a06..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/README +++ /dev/null @@ -1,15 +0,0 @@ -pretty_vcproj: - Usage: pretty_vcproj.py "c:\path\to\vcproj.vcproj" [key1=value1] [key2=value2] - - They key/value pair are used to resolve vsprops name. - - For example, if I want to diff the base.vcproj project: - - pretty_vcproj.py z:\dev\src-chrome\src\base\build\base.vcproj "$(SolutionDir)=z:\dev\src-chrome\src\chrome\\" "$(CHROMIUM_BUILD)=" "$(CHROME_BUILD_TYPE)=" > orignal.txt - pretty_vcproj.py z:\dev\src-chrome\src\base\base_gyp.vcproj "$(SolutionDir)=z:\dev\src-chrome\src\chrome\\" "$(CHROMIUM_BUILD)=" "$(CHROME_BUILD_TYPE)=" > gyp.txt - - And you can use your favorite diff tool to see the changes. - - Note: In the case of base.vcproj, the original vcproj is one level up the generated one. - I suggest you do a search and replace for '"..\' and replace it with '"' in original.txt - before you perform the diff. \ No newline at end of file diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/README b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/README deleted file mode 100644 index 2492a2c2f8f17..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/README +++ /dev/null @@ -1,5 +0,0 @@ -Specifications contains syntax formatters for Xcode 3. These do not appear to be supported yet on Xcode 4. To use these with Xcode 3 please install both the gyp.pbfilespec and gyp.xclangspec files in - -~/Library/Application Support/Developer/Shared/Xcode/Specifications/ - -and restart Xcode. \ No newline at end of file diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.pbfilespec b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.pbfilespec deleted file mode 100644 index 85e2e268a51b7..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.pbfilespec +++ /dev/null @@ -1,27 +0,0 @@ -/* - gyp.pbfilespec - GYP source file spec for Xcode 3 - - There is not much documentation available regarding the format - of .pbfilespec files. As a starting point, see for instance the - outdated documentation at: - http://maxao.free.fr/xcode-plugin-interface/specifications.html - and the files in: - /Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources/ - - Place this file in directory: - ~/Library/Application Support/Developer/Shared/Xcode/Specifications/ -*/ - -( - { - Identifier = sourcecode.gyp; - BasedOn = sourcecode; - Name = "GYP Files"; - Extensions = ("gyp", "gypi"); - MIMETypes = ("text/gyp"); - Language = "xcode.lang.gyp"; - IsTextFile = YES; - IsSourceFile = YES; - } -) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.xclangspec b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.xclangspec deleted file mode 100644 index 3b3506d319e0f..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/Xcode/Specifications/gyp.xclangspec +++ /dev/null @@ -1,226 +0,0 @@ -/* - Copyright (c) 2011 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. - - gyp.xclangspec - GYP language specification for Xcode 3 - - There is not much documentation available regarding the format - of .xclangspec files. As a starting point, see for instance the - outdated documentation at: - http://maxao.free.fr/xcode-plugin-interface/specifications.html - and the files in: - /Developer/Library/PrivateFrameworks/XcodeEdit.framework/Versions/A/Resources/ - - Place this file in directory: - ~/Library/Application Support/Developer/Shared/Xcode/Specifications/ -*/ - -( - - { - Identifier = "xcode.lang.gyp.keyword"; - Syntax = { - Words = ( - "and", - "or", - " (caar gyp-parse-history) target-point) - (setq gyp-parse-history (cdr gyp-parse-history)))) - -(defun gyp-parse-point () - "The point of the last parse state added by gyp-parse-to." - (caar gyp-parse-history)) - -(defun gyp-parse-sections () - "A list of section symbols holding at the last parse state point." - (cdar gyp-parse-history)) - -(defun gyp-inside-dictionary-p () - "Predicate returning true if the parser is inside a dictionary." - (not (eq (cadar gyp-parse-history) 'list))) - -(defun gyp-add-parse-history (point sections) - "Add parse state SECTIONS to the parse history at POINT so that parsing can be - resumed instantly." - (while (>= (caar gyp-parse-history) point) - (setq gyp-parse-history (cdr gyp-parse-history))) - (setq gyp-parse-history (cons (cons point sections) gyp-parse-history))) - -(defun gyp-parse-to (target-point) - "Parses from (point) to TARGET-POINT adding the parse state information to - gyp-parse-state-history. Parsing stops if TARGET-POINT is reached or if a - string literal has been parsed. Returns nil if no further parsing can be - done, otherwise returns the position of the start of a parsed string, leaving - the point at the end of the string." - (let ((parsing t) - string-start) - (while parsing - (setq string-start nil) - ;; Parse up to a character that starts a sexp, or if the nesting - ;; level decreases. - (let ((state (parse-partial-sexp (gyp-parse-point) - target-point - -1 - t)) - (sections (gyp-parse-sections))) - (if (= (nth 0 state) -1) - (setq sections (cdr sections)) ; pop out a level - (cond ((looking-at-p "['\"]") ; a string - (setq string-start (point)) - (goto-char (scan-sexps (point) 1)) - (if (gyp-inside-dictionary-p) - ;; Look for sections inside a dictionary - (let ((section (gyp-section-name - (buffer-substring-no-properties - (+ 1 string-start) - (- (point) 1))))) - (setq sections (cons section (cdr sections))))) - ;; Stop after the string so it can be fontified. - (setq target-point (point))) - ((looking-at-p "{") - ;; Inside a dictionary. Increase nesting. - (forward-char 1) - (setq sections (cons 'unknown sections))) - ((looking-at-p "\\[") - ;; Inside a list. Increase nesting - (forward-char 1) - (setq sections (cons 'list sections))) - ((not (eobp)) - ;; other - (forward-char 1)))) - (gyp-add-parse-history (point) sections) - (setq parsing (< (point) target-point)))) - string-start)) - -(defun gyp-section-at-point () - "Transform the last parse state, which is a list of nested sections and return - the section symbol that should be used to determine font-lock information for - the string. Can return nil indicating the string should not have any attached - section." - (let ((sections (gyp-parse-sections))) - (cond - ((eq (car sections) 'conditions) - ;; conditions can occur in a variables section, but we still want to - ;; highlight it as a keyword. - nil) - ((and (eq (car sections) 'list) - (eq (cadr sections) 'list)) - ;; conditions and sources can have items in [[ ]] - (caddr sections)) - (t (cadr sections))))) - -(defun gyp-section-match (limit) - "Parse from (point) to LIMIT returning by means of match data what was - matched. The group of the match indicates what style font-lock should apply. - See also `gyp-add-font-lock-keywords'." - (gyp-invalidate-parse-states-after (point)) - (let ((group nil) - (string-start t)) - (while (and (< (point) limit) - (not group) - string-start) - (setq string-start (gyp-parse-to limit)) - (if string-start - (setq group (case (gyp-section-at-point) - ('dependencies 1) - ('variables 2) - ('conditions 2) - ('sources 3) - ('defines 4) - (nil nil))))) - (if group - (progn - ;; Set the match data to indicate to the font-lock mechanism the - ;; highlighting to be performed. - (set-match-data (append (list string-start (point)) - (make-list (* (1- group) 2) nil) - (list (1+ string-start) (1- (point))))) - t)))) - -;;; Please see http://code.google.com/p/gyp/wiki/GypLanguageSpecification for -;;; canonical list of keywords. -(defun gyp-add-font-lock-keywords () - "Add gyp-mode keywords to font-lock mechanism." - ;; TODO(jknotten): Move all the keyword highlighting into gyp-section-match - ;; so that we can do the font-locking in a single font-lock pass. - (font-lock-add-keywords - nil - (list - ;; Top-level keywords - (list (concat "['\"]\\(" - (regexp-opt (list "action" "action_name" "actions" "cflags" - "cflags_cc" "conditions" "configurations" - "copies" "defines" "dependencies" "destination" - "direct_dependent_settings" - "export_dependent_settings" "extension" "files" - "include_dirs" "includes" "inputs" "ldflags" "libraries" - "link_settings" "mac_bundle" "message" - "msvs_external_rule" "outputs" "product_name" - "process_outputs_as_sources" "rules" "rule_name" - "sources" "suppress_wildcard" - "target_conditions" "target_defaults" - "target_defines" "target_name" "toolsets" - "targets" "type" "variables" "xcode_settings")) - "[!/+=]?\\)") 1 'font-lock-keyword-face t) - ;; Type of target - (list (concat "['\"]\\(" - (regexp-opt (list "loadable_module" "static_library" - "shared_library" "executable" "none")) - "\\)") 1 'font-lock-type-face t) - (list "\\(?:target\\|action\\)_name['\"]\\s-*:\\s-*['\"]\\([^ '\"]*\\)" 1 - 'font-lock-function-name-face t) - (list 'gyp-section-match - (list 1 'font-lock-function-name-face t t) ; dependencies - (list 2 'font-lock-variable-name-face t t) ; variables, conditions - (list 3 'font-lock-constant-face t t) ; sources - (list 4 'font-lock-preprocessor-face t t)) ; preprocessor - ;; Variable expansion - (list "<@?(\\([^\n )]+\\))" 1 'font-lock-variable-name-face t) - ;; Command expansion - (list " "%s"' % (src, dst) - - print '}' - - -def main(): - if len(sys.argv) < 2: - print >>sys.stderr, __doc__ - print >>sys.stderr - print >>sys.stderr, 'usage: %s target1 target2...' % (sys.argv[0]) - return 1 - - edges = LoadEdges('dump.json', sys.argv[1:]) - - WriteGraph(edges) - return 0 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_gyp.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_gyp.py deleted file mode 100755 index c51d35872cce6..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_gyp.py +++ /dev/null @@ -1,155 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2012 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. - -"""Pretty-prints the contents of a GYP file.""" - -import sys -import re - - -# Regex to remove comments when we're counting braces. -COMMENT_RE = re.compile(r'\s*#.*') - -# Regex to remove quoted strings when we're counting braces. -# It takes into account quoted quotes, and makes sure that the quotes match. -# NOTE: It does not handle quotes that span more than one line, or -# cases where an escaped quote is preceeded by an escaped backslash. -QUOTE_RE_STR = r'(?P[\'"])(.*?)(? 0: - after = True - - # This catches the special case of a closing brace having something - # other than just whitespace ahead of it -- we don't want to - # unindent that until after this line is printed so it stays with - # the previous indentation level. - if cnt < 0 and closing_prefix_re.match(stripline): - after = True - return (cnt, after) - - -def prettyprint_input(lines): - """Does the main work of indenting the input based on the brace counts.""" - indent = 0 - basic_offset = 2 - last_line = "" - for line in lines: - if COMMENT_RE.match(line): - print line - else: - line = line.strip('\r\n\t ') # Otherwise doesn't strip \r on Unix. - if len(line) > 0: - (brace_diff, after) = count_braces(line) - if brace_diff != 0: - if after: - print " " * (basic_offset * indent) + line - indent += brace_diff - else: - indent += brace_diff - print " " * (basic_offset * indent) + line - else: - print " " * (basic_offset * indent) + line - else: - print "" - last_line = line - - -def main(): - if len(sys.argv) > 1: - data = open(sys.argv[1]).read().splitlines() - else: - data = sys.stdin.read().splitlines() - # Split up the double braces. - lines = split_double_braces(data) - - # Indent and print the output. - prettyprint_input(lines) - return 0 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_sln.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_sln.py deleted file mode 100755 index ca8cf4ad3fb83..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_sln.py +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2012 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. - -"""Prints the information in a sln file in a diffable way. - - It first outputs each projects in alphabetical order with their - dependencies. - - Then it outputs a possible build order. -""" - -__author__ = 'nsylvain (Nicolas Sylvain)' - -import os -import re -import sys -import pretty_vcproj - -def BuildProject(project, built, projects, deps): - # if all dependencies are done, we can build it, otherwise we try to build the - # dependency. - # This is not infinite-recursion proof. - for dep in deps[project]: - if dep not in built: - BuildProject(dep, built, projects, deps) - print project - built.append(project) - -def ParseSolution(solution_file): - # All projects, their clsid and paths. - projects = dict() - - # A list of dependencies associated with a project. - dependencies = dict() - - # Regular expressions that matches the SLN format. - # The first line of a project definition. - begin_project = re.compile(r'^Project\("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942' - r'}"\) = "(.*)", "(.*)", "(.*)"$') - # The last line of a project definition. - end_project = re.compile('^EndProject$') - # The first line of a dependency list. - begin_dep = re.compile( - r'ProjectSection\(ProjectDependencies\) = postProject$') - # The last line of a dependency list. - end_dep = re.compile('EndProjectSection$') - # A line describing a dependency. - dep_line = re.compile(' *({.*}) = ({.*})$') - - in_deps = False - solution = open(solution_file) - for line in solution: - results = begin_project.search(line) - if results: - # Hack to remove icu because the diff is too different. - if results.group(1).find('icu') != -1: - continue - # We remove "_gyp" from the names because it helps to diff them. - current_project = results.group(1).replace('_gyp', '') - projects[current_project] = [results.group(2).replace('_gyp', ''), - results.group(3), - results.group(2)] - dependencies[current_project] = [] - continue - - results = end_project.search(line) - if results: - current_project = None - continue - - results = begin_dep.search(line) - if results: - in_deps = True - continue - - results = end_dep.search(line) - if results: - in_deps = False - continue - - results = dep_line.search(line) - if results and in_deps and current_project: - dependencies[current_project].append(results.group(1)) - continue - - # Change all dependencies clsid to name instead. - for project in dependencies: - # For each dependencies in this project - new_dep_array = [] - for dep in dependencies[project]: - # Look for the project name matching this cldis - for project_info in projects: - if projects[project_info][1] == dep: - new_dep_array.append(project_info) - dependencies[project] = sorted(new_dep_array) - - return (projects, dependencies) - -def PrintDependencies(projects, deps): - print "---------------------------------------" - print "Dependencies for all projects" - print "---------------------------------------" - print "-- --" - - for (project, dep_list) in sorted(deps.items()): - print "Project : %s" % project - print "Path : %s" % projects[project][0] - if dep_list: - for dep in dep_list: - print " - %s" % dep - print "" - - print "-- --" - -def PrintBuildOrder(projects, deps): - print "---------------------------------------" - print "Build order " - print "---------------------------------------" - print "-- --" - - built = [] - for (project, _) in sorted(deps.items()): - if project not in built: - BuildProject(project, built, projects, deps) - - print "-- --" - -def PrintVCProj(projects): - - for project in projects: - print "-------------------------------------" - print "-------------------------------------" - print project - print project - print project - print "-------------------------------------" - print "-------------------------------------" - - project_path = os.path.abspath(os.path.join(os.path.dirname(sys.argv[1]), - projects[project][2])) - - pretty = pretty_vcproj - argv = [ '', - project_path, - '$(SolutionDir)=%s\\' % os.path.dirname(sys.argv[1]), - ] - argv.extend(sys.argv[3:]) - pretty.main(argv) - -def main(): - # check if we have exactly 1 parameter. - if len(sys.argv) < 2: - print 'Usage: %s "c:\\path\\to\\project.sln"' % sys.argv[0] - return 1 - - (projects, deps) = ParseSolution(sys.argv[1]) - PrintDependencies(projects, deps) - PrintBuildOrder(projects, deps) - - if '--recursive' in sys.argv: - PrintVCProj(projects) - return 0 - - -if __name__ == '__main__': - sys.exit(main()) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_vcproj.py b/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_vcproj.py deleted file mode 100755 index 6099bd7cc4d8c..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/gyp/tools/pretty_vcproj.py +++ /dev/null @@ -1,329 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2012 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. - -"""Make the format of a vcproj really pretty. - - This script normalize and sort an xml. It also fetches all the properties - inside linked vsprops and include them explicitly in the vcproj. - - It outputs the resulting xml to stdout. -""" - -__author__ = 'nsylvain (Nicolas Sylvain)' - -import os -import sys - -from xml.dom.minidom import parse -from xml.dom.minidom import Node - -REPLACEMENTS = dict() -ARGUMENTS = None - - -class CmpTuple(object): - """Compare function between 2 tuple.""" - def __call__(self, x, y): - return cmp(x[0], y[0]) - - -class CmpNode(object): - """Compare function between 2 xml nodes.""" - - def __call__(self, x, y): - def get_string(node): - node_string = "node" - node_string += node.nodeName - if node.nodeValue: - node_string += node.nodeValue - - if node.attributes: - # We first sort by name, if present. - node_string += node.getAttribute("Name") - - all_nodes = [] - for (name, value) in node.attributes.items(): - all_nodes.append((name, value)) - - all_nodes.sort(CmpTuple()) - for (name, value) in all_nodes: - node_string += name - node_string += value - - return node_string - - return cmp(get_string(x), get_string(y)) - - -def PrettyPrintNode(node, indent=0): - if node.nodeType == Node.TEXT_NODE: - if node.data.strip(): - print '%s%s' % (' '*indent, node.data.strip()) - return - - if node.childNodes: - node.normalize() - # Get the number of attributes - attr_count = 0 - if node.attributes: - attr_count = node.attributes.length - - # Print the main tag - if attr_count == 0: - print '%s<%s>' % (' '*indent, node.nodeName) - else: - print '%s<%s' % (' '*indent, node.nodeName) - - all_attributes = [] - for (name, value) in node.attributes.items(): - all_attributes.append((name, value)) - all_attributes.sort(CmpTuple()) - for (name, value) in all_attributes: - print '%s %s="%s"' % (' '*indent, name, value) - print '%s>' % (' '*indent) - if node.nodeValue: - print '%s %s' % (' '*indent, node.nodeValue) - - for sub_node in node.childNodes: - PrettyPrintNode(sub_node, indent=indent+2) - print '%s' % (' '*indent, node.nodeName) - - -def FlattenFilter(node): - """Returns a list of all the node and sub nodes.""" - node_list = [] - - if (node.attributes and - node.getAttribute('Name') == '_excluded_files'): - # We don't add the "_excluded_files" filter. - return [] - - for current in node.childNodes: - if current.nodeName == 'Filter': - node_list.extend(FlattenFilter(current)) - else: - node_list.append(current) - - return node_list - - -def FixFilenames(filenames, current_directory): - new_list = [] - for filename in filenames: - if filename: - for key in REPLACEMENTS: - filename = filename.replace(key, REPLACEMENTS[key]) - os.chdir(current_directory) - filename = filename.strip('"\' ') - if filename.startswith('$'): - new_list.append(filename) - else: - new_list.append(os.path.abspath(filename)) - return new_list - - -def AbsoluteNode(node): - """Makes all the properties we know about in this node absolute.""" - if node.attributes: - for (name, value) in node.attributes.items(): - if name in ['InheritedPropertySheets', 'RelativePath', - 'AdditionalIncludeDirectories', - 'IntermediateDirectory', 'OutputDirectory', - 'AdditionalLibraryDirectories']: - # We want to fix up these paths - path_list = value.split(';') - new_list = FixFilenames(path_list, os.path.dirname(ARGUMENTS[1])) - node.setAttribute(name, ';'.join(new_list)) - if not value: - node.removeAttribute(name) - - -def CleanupVcproj(node): - """For each sub node, we call recursively this function.""" - for sub_node in node.childNodes: - AbsoluteNode(sub_node) - CleanupVcproj(sub_node) - - # Normalize the node, and remove all extranous whitespaces. - for sub_node in node.childNodes: - if sub_node.nodeType == Node.TEXT_NODE: - sub_node.data = sub_node.data.replace("\r", "") - sub_node.data = sub_node.data.replace("\n", "") - sub_node.data = sub_node.data.rstrip() - - # Fix all the semicolon separated attributes to be sorted, and we also - # remove the dups. - if node.attributes: - for (name, value) in node.attributes.items(): - sorted_list = sorted(value.split(';')) - unique_list = [] - for i in sorted_list: - if not unique_list.count(i): - unique_list.append(i) - node.setAttribute(name, ';'.join(unique_list)) - if not value: - node.removeAttribute(name) - - if node.childNodes: - node.normalize() - - # For each node, take a copy, and remove it from the list. - node_array = [] - while node.childNodes and node.childNodes[0]: - # Take a copy of the node and remove it from the list. - current = node.childNodes[0] - node.removeChild(current) - - # If the child is a filter, we want to append all its children - # to this same list. - if current.nodeName == 'Filter': - node_array.extend(FlattenFilter(current)) - else: - node_array.append(current) - - - # Sort the list. - node_array.sort(CmpNode()) - - # Insert the nodes in the correct order. - for new_node in node_array: - # But don't append empty tool node. - if new_node.nodeName == 'Tool': - if new_node.attributes and new_node.attributes.length == 1: - # This one was empty. - continue - if new_node.nodeName == 'UserMacro': - continue - node.appendChild(new_node) - - -def GetConfiguationNodes(vcproj): - #TODO(nsylvain): Find a better way to navigate the xml. - nodes = [] - for node in vcproj.childNodes: - if node.nodeName == "Configurations": - for sub_node in node.childNodes: - if sub_node.nodeName == "Configuration": - nodes.append(sub_node) - - return nodes - - -def GetChildrenVsprops(filename): - dom = parse(filename) - if dom.documentElement.attributes: - vsprops = dom.documentElement.getAttribute('InheritedPropertySheets') - return FixFilenames(vsprops.split(';'), os.path.dirname(filename)) - return [] - -def SeekToNode(node1, child2): - # A text node does not have properties. - if child2.nodeType == Node.TEXT_NODE: - return None - - # Get the name of the current node. - current_name = child2.getAttribute("Name") - if not current_name: - # There is no name. We don't know how to merge. - return None - - # Look through all the nodes to find a match. - for sub_node in node1.childNodes: - if sub_node.nodeName == child2.nodeName: - name = sub_node.getAttribute("Name") - if name == current_name: - return sub_node - - # No match. We give up. - return None - - -def MergeAttributes(node1, node2): - # No attributes to merge? - if not node2.attributes: - return - - for (name, value2) in node2.attributes.items(): - # Don't merge the 'Name' attribute. - if name == 'Name': - continue - value1 = node1.getAttribute(name) - if value1: - # The attribute exist in the main node. If it's equal, we leave it - # untouched, otherwise we concatenate it. - if value1 != value2: - node1.setAttribute(name, ';'.join([value1, value2])) - else: - # The attribute does nto exist in the main node. We append this one. - node1.setAttribute(name, value2) - - # If the attribute was a property sheet attributes, we remove it, since - # they are useless. - if name == 'InheritedPropertySheets': - node1.removeAttribute(name) - - -def MergeProperties(node1, node2): - MergeAttributes(node1, node2) - for child2 in node2.childNodes: - child1 = SeekToNode(node1, child2) - if child1: - MergeProperties(child1, child2) - else: - node1.appendChild(child2.cloneNode(True)) - - -def main(argv): - """Main function of this vcproj prettifier.""" - global ARGUMENTS - ARGUMENTS = argv - - # check if we have exactly 1 parameter. - if len(argv) < 2: - print ('Usage: %s "c:\\path\\to\\vcproj.vcproj" [key1=value1] ' - '[key2=value2]' % argv[0]) - return 1 - - # Parse the keys - for i in range(2, len(argv)): - (key, value) = argv[i].split('=') - REPLACEMENTS[key] = value - - # Open the vcproj and parse the xml. - dom = parse(argv[1]) - - # First thing we need to do is find the Configuration Node and merge them - # with the vsprops they include. - for configuration_node in GetConfiguationNodes(dom.documentElement): - # Get the property sheets associated with this configuration. - vsprops = configuration_node.getAttribute('InheritedPropertySheets') - - # Fix the filenames to be absolute. - vsprops_list = FixFilenames(vsprops.strip().split(';'), - os.path.dirname(argv[1])) - - # Extend the list of vsprops with all vsprops contained in the current - # vsprops. - for current_vsprops in vsprops_list: - vsprops_list.extend(GetChildrenVsprops(current_vsprops)) - - # Now that we have all the vsprops, we need to merge them. - for current_vsprops in vsprops_list: - MergeProperties(configuration_node, - parse(current_vsprops).documentElement) - - # Now that everything is merged, we need to cleanup the xml. - CleanupVcproj(dom.documentElement) - - # Finally, we use the prett xml function to print the vcproj back to the - # user. - #print dom.toprettyxml(newl="\n") - PrettyPrintNode(dom.documentElement) - return 0 - - -if __name__ == '__main__': - sys.exit(main(sys.argv)) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/Find-VS2017.cs b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/Find-VS2017.cs deleted file mode 100644 index 6e7429b771385..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/Find-VS2017.cs +++ /dev/null @@ -1,273 +0,0 @@ -// Copyright 2017 - Refael Ackermann -// Distributed under MIT style license -// See accompanying file LICENSE at https://github.com/node4good/windows-autoconf - -// Usage: -// powershell -ExecutionPolicy Unrestricted -Version "2.0" -Command "&{Add-Type -Path Find-VS2017.cs; [VisualStudioConfiguration.Main]::Query()}" -using System; -using System.Text; -using System.Runtime.InteropServices; - -namespace VisualStudioConfiguration -{ - [Flags] - public enum InstanceState : uint - { - None = 0, - Local = 1, - Registered = 2, - NoRebootRequired = 4, - NoErrors = 8, - Complete = 4294967295, - } - - [Guid("6380BCFF-41D3-4B2E-8B2E-BF8A6810C848")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComImport] - public interface IEnumSetupInstances - { - - void Next([MarshalAs(UnmanagedType.U4), In] int celt, - [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.Interface), Out] ISetupInstance[] rgelt, - [MarshalAs(UnmanagedType.U4)] out int pceltFetched); - - void Skip([MarshalAs(UnmanagedType.U4), In] int celt); - - void Reset(); - - [return: MarshalAs(UnmanagedType.Interface)] - IEnumSetupInstances Clone(); - } - - [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComImport] - public interface ISetupConfiguration - { - } - - [Guid("26AAB78C-4A60-49D6-AF3B-3C35BC93365D")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComImport] - public interface ISetupConfiguration2 : ISetupConfiguration - { - - [return: MarshalAs(UnmanagedType.Interface)] - IEnumSetupInstances EnumInstances(); - - [return: MarshalAs(UnmanagedType.Interface)] - ISetupInstance GetInstanceForCurrentProcess(); - - [return: MarshalAs(UnmanagedType.Interface)] - ISetupInstance GetInstanceForPath([MarshalAs(UnmanagedType.LPWStr), In] string path); - - [return: MarshalAs(UnmanagedType.Interface)] - IEnumSetupInstances EnumAllInstances(); - } - - [Guid("B41463C3-8866-43B5-BC33-2B0676F7F42E")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComImport] - public interface ISetupInstance - { - } - - [Guid("89143C9A-05AF-49B0-B717-72E218A2185C")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComImport] - public interface ISetupInstance2 : ISetupInstance - { - [return: MarshalAs(UnmanagedType.BStr)] - string GetInstanceId(); - - [return: MarshalAs(UnmanagedType.Struct)] - System.Runtime.InteropServices.ComTypes.FILETIME GetInstallDate(); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetInstallationName(); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetInstallationPath(); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetInstallationVersion(); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetDisplayName([MarshalAs(UnmanagedType.U4), In] int lcid); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetDescription([MarshalAs(UnmanagedType.U4), In] int lcid); - - [return: MarshalAs(UnmanagedType.BStr)] - string ResolvePath([MarshalAs(UnmanagedType.LPWStr), In] string pwszRelativePath); - - [return: MarshalAs(UnmanagedType.U4)] - InstanceState GetState(); - - [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] - ISetupPackageReference[] GetPackages(); - - ISetupPackageReference GetProduct(); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetProductPath(); - - [return: MarshalAs(UnmanagedType.VariantBool)] - bool IsLaunchable(); - - [return: MarshalAs(UnmanagedType.VariantBool)] - bool IsComplete(); - - [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_UNKNOWN)] - ISetupPropertyStore GetProperties(); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetEnginePath(); - } - - [Guid("DA8D8A16-B2B6-4487-A2F1-594CCCCD6BF5")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComImport] - public interface ISetupPackageReference - { - - [return: MarshalAs(UnmanagedType.BStr)] - string GetId(); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetVersion(); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetChip(); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetLanguage(); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetBranch(); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetType(); - - [return: MarshalAs(UnmanagedType.BStr)] - string GetUniqueId(); - - [return: MarshalAs(UnmanagedType.VariantBool)] - bool GetIsExtension(); - } - - [Guid("c601c175-a3be-44bc-91f6-4568d230fc83")] - [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] - [ComImport] - public interface ISetupPropertyStore - { - - [return: MarshalAs(UnmanagedType.SafeArray, SafeArraySubType = VarEnum.VT_BSTR)] - string[] GetNames(); - - object GetValue([MarshalAs(UnmanagedType.LPWStr), In] string pwszName); - } - - [Guid("42843719-DB4C-46C2-8E7C-64F1816EFD5B")] - [CoClass(typeof(SetupConfigurationClass))] - [ComImport] - public interface SetupConfiguration : ISetupConfiguration2, ISetupConfiguration - { - } - - [Guid("177F0C4A-1CD3-4DE7-A32C-71DBBB9FA36D")] - [ClassInterface(ClassInterfaceType.None)] - [ComImport] - public class SetupConfigurationClass - { - } - - public static class Main - { - public static void Query() - { - ISetupConfiguration query = new SetupConfiguration(); - ISetupConfiguration2 query2 = (ISetupConfiguration2)query; - IEnumSetupInstances e = query2.EnumAllInstances(); - - int pceltFetched; - ISetupInstance2[] rgelt = new ISetupInstance2[1]; - StringBuilder log = new StringBuilder(); - while (true) - { - e.Next(1, rgelt, out pceltFetched); - if (pceltFetched <= 0) - { - Console.WriteLine(String.Format("{{\"log\":\"{0}\"}}", log.ToString())); - return; - } - if (CheckInstance(rgelt[0], ref log)) - return; - } - } - - private static bool CheckInstance(ISetupInstance2 setupInstance2, ref StringBuilder log) - { - // Visual Studio Community 2017 component directory: - // https://www.visualstudio.com/en-us/productinfo/vs2017-install-product-Community.workloads - - string path = setupInstance2.GetInstallationPath().Replace("\\", "\\\\"); - log.Append(String.Format("Found installation at: {0}\\n", path)); - - bool hasMSBuild = false; - bool hasVCTools = false; - uint Win10SDKVer = 0; - bool hasWin8SDK = false; - - foreach (ISetupPackageReference package in setupInstance2.GetPackages()) - { - const string Win10SDKPrefix = "Microsoft.VisualStudio.Component.Windows10SDK."; - - string id = package.GetId(); - if (id == "Microsoft.VisualStudio.VC.MSBuild.Base") - hasMSBuild = true; - else if (id == "Microsoft.VisualStudio.Component.VC.Tools.x86.x64") - hasVCTools = true; - else if (id.StartsWith(Win10SDKPrefix)) { - string[] parts = id.Substring(Win10SDKPrefix.Length).Split('.'); - if (parts.Length > 1 && parts[1] != "Desktop") - continue; - uint foundSdkVer; - if (UInt32.TryParse(parts[0], out foundSdkVer)) - Win10SDKVer = Math.Max(Win10SDKVer, foundSdkVer); - } else if (id == "Microsoft.VisualStudio.Component.Windows81SDK") - hasWin8SDK = true; - else - continue; - - log.Append(String.Format(" - Found {0}\\n", id)); - } - - if (!hasMSBuild) - log.Append(" - Missing Visual Studio C++ core features (Microsoft.VisualStudio.VC.MSBuild.Base)\\n"); - if (!hasVCTools) - log.Append(" - Missing VC++ 2017 v141 toolset (x86,x64) (Microsoft.VisualStudio.Component.VC.Tools.x86.x64)\\n"); - if ((Win10SDKVer == 0) && (!hasWin8SDK)) - log.Append(" - Missing a Windows SDK (Microsoft.VisualStudio.Component.Windows10SDK.* or Microsoft.VisualStudio.Component.Windows81SDK)\\n"); - - if (hasMSBuild && hasVCTools) - { - if (Win10SDKVer > 0) - { - log.Append(" - Using this installation with Windows 10 SDK"/*\\n*/); - Console.WriteLine(String.Format("{{\"log\":\"{0}\",\"path\":\"{1}\",\"sdk\":\"10.0.{2}.0\"}}", log.ToString(), path, Win10SDKVer)); - return true; - } - else if (hasWin8SDK) - { - log.Append(" - Using this installation with Windows 8.1 SDK"/*\\n*/); - Console.WriteLine(String.Format("{{\"log\":\"{0}\",\"path\":\"{1}\",\"sdk\":\"8.1\"}}", log.ToString(), path)); - return true; - } - } - - log.Append(" - Some required components are missing, not using this installation\\n"); - return false; - } - } -} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/build.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/build.js deleted file mode 100644 index 2f8e14c37429d..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/build.js +++ /dev/null @@ -1,270 +0,0 @@ - -module.exports = exports = build - -/** - * Module dependencies. - */ - -var fs = require('graceful-fs') - , rm = require('rimraf') - , path = require('path') - , glob = require('glob') - , log = require('npmlog') - , which = require('which') - , exec = require('child_process').exec - , processRelease = require('./process-release') - , win = process.platform === 'win32' - -exports.usage = 'Invokes `' + (win ? 'msbuild' : 'make') + '` and builds the module' - -function build (gyp, argv, callback) { - var platformMake = 'make' - if (process.platform === 'aix') { - platformMake = 'gmake' - } else if (process.platform.indexOf('bsd') !== -1) { - platformMake = 'gmake' - } else if (win && argv.length > 0) { - argv = argv.map(function(target) { - return '/t:' + target - }) - } - - var release = processRelease(argv, gyp, process.version, process.release) - , makeCommand = gyp.opts.make || process.env.MAKE || platformMake - , command = win ? 'msbuild' : makeCommand - , buildDir = path.resolve('build') - , configPath = path.resolve(buildDir, 'config.gypi') - , jobs = gyp.opts.jobs || process.env.JOBS - , buildType - , config - , arch - , nodeDir - - loadConfigGypi() - - /** - * Load the "config.gypi" file that was generated during "configure". - */ - - function loadConfigGypi () { - fs.readFile(configPath, 'utf8', function (err, data) { - if (err) { - if (err.code == 'ENOENT') { - callback(new Error('You must run `node-gyp configure` first!')) - } else { - callback(err) - } - return - } - config = JSON.parse(data.replace(/\#.+\n/, '')) - - // get the 'arch', 'buildType', and 'nodeDir' vars from the config - buildType = config.target_defaults.default_configuration - arch = config.variables.target_arch - nodeDir = config.variables.nodedir - - if ('debug' in gyp.opts) { - buildType = gyp.opts.debug ? 'Debug' : 'Release' - } - if (!buildType) { - buildType = 'Release' - } - - log.verbose('build type', buildType) - log.verbose('architecture', arch) - log.verbose('node dev dir', nodeDir) - - if (win) { - findSolutionFile() - } else { - doWhich() - } - }) - } - - /** - * On Windows, find the first build/*.sln file. - */ - - function findSolutionFile () { - glob('build/*.sln', function (err, files) { - if (err) return callback(err) - if (files.length === 0) { - return callback(new Error('Could not find *.sln file. Did you run "configure"?')) - } - guessedSolution = files[0] - log.verbose('found first Solution file', guessedSolution) - doWhich() - }) - } - - /** - * Uses node-which to locate the msbuild / make executable. - */ - - function doWhich () { - // First make sure we have the build command in the PATH - which(command, function (err, execPath) { - if (err) { - if (win && /not found/.test(err.message)) { - // On windows and no 'msbuild' found. Let's guess where it is - findMsbuild() - } else { - // Some other error or 'make' not found on Unix, report that to the user - callback(err) - } - return - } - log.verbose('`which` succeeded for `' + command + '`', execPath) - doBuild() - }) - } - - /** - * Search for the location of "msbuild.exe" file on Windows. - */ - - function findMsbuild () { - if (config.variables.msbuild_path) { - command = config.variables.msbuild_path - log.verbose('using MSBuild:', command) - doBuild() - return - } - - log.verbose('could not find "msbuild.exe" in PATH - finding location in registry') - var notfoundErr = 'Can\'t find "msbuild.exe". Do you have Microsoft Visual Studio C++ 2008+ installed?' - var cmd = 'reg query "HKLM\\Software\\Microsoft\\MSBuild\\ToolsVersions" /s' - if (process.arch !== 'ia32') - cmd += ' /reg:32' - exec(cmd, function (err, stdout, stderr) { - if (err) { - return callback(new Error(err.message + '\n' + notfoundErr)) - } - var reVers = /ToolsVersions\\([^\\]+)$/i - , rePath = /\r\n[ \t]+MSBuildToolsPath[ \t]+REG_SZ[ \t]+([^\r]+)/i - , msbuilds = [] - , r - , msbuildPath - stdout.split('\r\n\r\n').forEach(function(l) { - if (!l) return - l = l.trim() - if (r = reVers.exec(l.substring(0, l.indexOf('\r\n')))) { - var ver = parseFloat(r[1], 10) - if (ver >= 3.5) { - if (r = rePath.exec(l)) { - msbuilds.push({ - version: ver, - path: r[1] - }) - } - } - } - }) - msbuilds.sort(function (x, y) { - return (x.version < y.version ? -1 : 1) - }) - ;(function verifyMsbuild () { - if (!msbuilds.length) return callback(new Error(notfoundErr)) - msbuildPath = path.resolve(msbuilds.pop().path, 'msbuild.exe') - fs.stat(msbuildPath, function (err, stat) { - if (err) { - if (err.code == 'ENOENT') { - if (msbuilds.length) { - return verifyMsbuild() - } else { - callback(new Error(notfoundErr)) - } - } else { - callback(err) - } - return - } - command = msbuildPath - doBuild() - }) - })() - }) - } - - - /** - * Actually spawn the process and compile the module. - */ - - function doBuild () { - - // Enable Verbose build - var verbose = log.levels[log.level] <= log.levels.verbose - if (!win && verbose) { - argv.push('V=1') - } - if (win && !verbose) { - argv.push('/clp:Verbosity=minimal') - } - - if (win) { - // Turn off the Microsoft logo on Windows - argv.push('/nologo') - } - - // Specify the build type, Release by default - if (win) { - var archLower = arch.toLowerCase() - var p = archLower === 'x64' ? 'x64' : - (archLower === 'arm' ? 'ARM' : 'Win32') - argv.push('/p:Configuration=' + buildType + ';Platform=' + p) - if (jobs) { - var j = parseInt(jobs, 10) - if (!isNaN(j) && j > 0) { - argv.push('/m:' + j) - } else if (jobs.toUpperCase() === 'MAX') { - argv.push('/m:' + require('os').cpus().length) - } - } - } else { - argv.push('BUILDTYPE=' + buildType) - // Invoke the Makefile in the 'build' dir. - argv.push('-C') - argv.push('build') - if (jobs) { - var j = parseInt(jobs, 10) - if (!isNaN(j) && j > 0) { - argv.push('--jobs') - argv.push(j) - } else if (jobs.toUpperCase() === 'MAX') { - argv.push('--jobs') - argv.push(require('os').cpus().length) - } - } - } - - if (win) { - // did the user specify their own .sln file? - var hasSln = argv.some(function (arg) { - return path.extname(arg) == '.sln' - }) - if (!hasSln) { - argv.unshift(gyp.opts.solution || guessedSolution) - } - } - - var proc = gyp.spawn(command, argv) - proc.on('exit', onExit) - } - - /** - * Invoked after the make/msbuild command exits. - */ - - function onExit (code, signal) { - if (code !== 0) { - return callback(new Error('`' + command + '` failed with exit code: ' + code)) - } - if (signal) { - return callback(new Error('`' + command + '` got signal: ' + signal)) - } - callback() - } - -} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/clean.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/clean.js deleted file mode 100644 index e69164d45afcc..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/clean.js +++ /dev/null @@ -1,22 +0,0 @@ - -module.exports = exports = clean - -exports.usage = 'Removes any generated build files and the "out" dir' - -/** - * Module dependencies. - */ - -var rm = require('rimraf') -var log = require('npmlog') - - -function clean (gyp, argv, callback) { - - // Remove the 'build' dir - var buildDir = 'build' - - log.verbose('clean', 'removing "%s" directory', buildDir) - rm(buildDir, callback) - -} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/configure.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/configure.js deleted file mode 100644 index 35e6787d1f3e3..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/configure.js +++ /dev/null @@ -1,524 +0,0 @@ -module.exports = exports = configure -module.exports.test = { - PythonFinder: PythonFinder, - findAccessibleSync: findAccessibleSync, - findPython: findPython, -} - -/** - * Module dependencies. - */ - -var fs = require('graceful-fs') - , path = require('path') - , log = require('npmlog') - , osenv = require('osenv') - , which = require('which') - , semver = require('semver') - , mkdirp = require('mkdirp') - , cp = require('child_process') - , extend = require('util')._extend - , processRelease = require('./process-release') - , win = process.platform === 'win32' - , findNodeDirectory = require('./find-node-directory') - , msgFormat = require('util').format -if (win) - var findVS2017 = require('./find-vs2017') - -exports.usage = 'Generates ' + (win ? 'MSVC project files' : 'a Makefile') + ' for the current module' - -function configure (gyp, argv, callback) { - - var python = gyp.opts.python || process.env.PYTHON || 'python2' - , buildDir = path.resolve('build') - , configNames = [ 'config.gypi', 'common.gypi' ] - , configs = [] - , nodeDir - , release = processRelease(argv, gyp, process.version, process.release) - - findPython(python, function (err, found) { - if (err) { - callback(err) - } else { - python = found - getNodeDir() - } - }) - - function getNodeDir () { - - // 'python' should be set by now - process.env.PYTHON = python - - if (gyp.opts.nodedir) { - // --nodedir was specified. use that for the dev files - nodeDir = gyp.opts.nodedir.replace(/^~/, osenv.home()) - - log.verbose('get node dir', 'compiling against specified --nodedir dev files: %s', nodeDir) - createBuildDir() - - } else { - // if no --nodedir specified, ensure node dependencies are installed - if ('v' + release.version !== process.version) { - // if --target was given, then determine a target version to compile for - log.verbose('get node dir', 'compiling against --target node version: %s', release.version) - } else { - // if no --target was specified then use the current host node version - log.verbose('get node dir', 'no --target version specified, falling back to host node version: %s', release.version) - } - - if (!release.semver) { - // could not parse the version string with semver - return callback(new Error('Invalid version number: ' + release.version)) - } - - // If the tarball option is set, always remove and reinstall the headers - // into devdir. Otherwise only install if they're not already there. - gyp.opts.ensure = gyp.opts.tarball ? false : true - - gyp.commands.install([ release.version ], function (err, version) { - if (err) return callback(err) - log.verbose('get node dir', 'target node version installed:', release.versionDir) - nodeDir = path.resolve(gyp.devDir, release.versionDir) - createBuildDir() - }) - } - } - - function createBuildDir () { - log.verbose('build dir', 'attempting to create "build" dir: %s', buildDir) - mkdirp(buildDir, function (err, isNew) { - if (err) return callback(err) - log.verbose('build dir', '"build" dir needed to be created?', isNew) - if (win && (!gyp.opts.msvs_version || gyp.opts.msvs_version === '2017')) { - findVS2017(function (err, vsSetup) { - if (err) { - log.verbose('Not using VS2017:', err.message) - createConfigFile() - } else { - createConfigFile(null, vsSetup) - } - }) - } else { - createConfigFile() - } - }) - } - - function createConfigFile (err, vsSetup) { - if (err) return callback(err) - - var configFilename = 'config.gypi' - var configPath = path.resolve(buildDir, configFilename) - - log.verbose('build/' + configFilename, 'creating config file') - - var config = process.config || {} - , defaults = config.target_defaults - , variables = config.variables - - // default "config.variables" - if (!variables) variables = config.variables = {} - - // default "config.defaults" - if (!defaults) defaults = config.target_defaults = {} - - // don't inherit the "defaults" from node's `process.config` object. - // doing so could cause problems in cases where the `node` executable was - // compiled on a different machine (with different lib/include paths) than - // the machine where the addon is being built to - defaults.cflags = [] - defaults.defines = [] - defaults.include_dirs = [] - defaults.libraries = [] - - // set the default_configuration prop - if ('debug' in gyp.opts) { - defaults.default_configuration = gyp.opts.debug ? 'Debug' : 'Release' - } - if (!defaults.default_configuration) { - defaults.default_configuration = 'Release' - } - - // set the target_arch variable - variables.target_arch = gyp.opts.arch || process.arch || 'ia32' - - // set the node development directory - variables.nodedir = nodeDir - - // disable -T "thin" static archives by default - variables.standalone_static_library = gyp.opts.thin ? 0 : 1 - - if (vsSetup) { - // GYP doesn't (yet) have support for VS2017, so we force it to VS2015 - // to avoid pulling a floating patch that has not landed upstream. - // Ref: https://chromium-review.googlesource.com/#/c/433540/ - gyp.opts.msvs_version = '2015' - process.env['GYP_MSVS_VERSION'] = 2015 - process.env['GYP_MSVS_OVERRIDE_PATH'] = vsSetup.path - defaults['msbuild_toolset'] = 'v141' - defaults['msvs_windows_target_platform_version'] = vsSetup.sdk - variables['msbuild_path'] = path.join(vsSetup.path, 'MSBuild', '15.0', - 'Bin', 'MSBuild.exe') - } - - // loop through the rest of the opts and add the unknown ones as variables. - // this allows for module-specific configure flags like: - // - // $ node-gyp configure --shared-libxml2 - Object.keys(gyp.opts).forEach(function (opt) { - if (opt === 'argv') return - if (opt in gyp.configDefs) return - variables[opt.replace(/-/g, '_')] = gyp.opts[opt] - }) - - // ensures that any boolean values from `process.config` get stringified - function boolsToString (k, v) { - if (typeof v === 'boolean') - return String(v) - return v - } - - log.silly('build/' + configFilename, config) - - // now write out the config.gypi file to the build/ dir - var prefix = '# Do not edit. File was generated by node-gyp\'s "configure" step' - , json = JSON.stringify(config, boolsToString, 2) - log.verbose('build/' + configFilename, 'writing out config file: %s', configPath) - configs.push(configPath) - fs.writeFile(configPath, [prefix, json, ''].join('\n'), findConfigs) - } - - function findConfigs (err) { - if (err) return callback(err) - var name = configNames.shift() - if (!name) return runGyp() - var fullPath = path.resolve(name) - log.verbose(name, 'checking for gypi file: %s', fullPath) - fs.stat(fullPath, function (err, stat) { - if (err) { - if (err.code == 'ENOENT') { - findConfigs() // check next gypi filename - } else { - callback(err) - } - } else { - log.verbose(name, 'found gypi file') - configs.push(fullPath) - findConfigs() - } - }) - } - - function runGyp (err) { - if (err) return callback(err) - - if (!~argv.indexOf('-f') && !~argv.indexOf('--format')) { - if (win) { - log.verbose('gyp', 'gyp format was not specified; forcing "msvs"') - // force the 'make' target for non-Windows - argv.push('-f', 'msvs') - } else { - log.verbose('gyp', 'gyp format was not specified; forcing "make"') - // force the 'make' target for non-Windows - argv.push('-f', 'make') - } - } - - function hasMsvsVersion () { - return argv.some(function (arg) { - return arg.indexOf('msvs_version') === 0 - }) - } - - if (win && !hasMsvsVersion()) { - if ('msvs_version' in gyp.opts) { - argv.push('-G', 'msvs_version=' + gyp.opts.msvs_version) - } else { - argv.push('-G', 'msvs_version=auto') - } - } - - // include all the ".gypi" files that were found - configs.forEach(function (config) { - argv.push('-I', config) - }) - - // For AIX and z/OS we need to set up the path to the exports file - // which contains the symbols needed for linking. - var node_exp_file = undefined - if (process.platform === 'aix' || process.platform === 'os390') { - var ext = process.platform === 'aix' ? 'exp' : 'x' - var node_root_dir = findNodeDirectory() - var candidates = undefined - if (process.platform === 'aix') { - candidates = ['include/node/node', - 'out/Release/node', - 'out/Debug/node', - 'node' - ].map(function(file) { - return file + '.' + ext - }) - } else { - candidates = ['out/Release/obj.target/libnode', - 'out/Debug/obj.target/libnode', - 'lib/libnode' - ].map(function(file) { - return file + '.' + ext - }) - } - var logprefix = 'find exports file' - node_exp_file = findAccessibleSync(logprefix, node_root_dir, candidates) - if (node_exp_file !== undefined) { - log.verbose(logprefix, 'Found exports file: %s', node_exp_file) - } else { - var msg = msgFormat('Could not find node.%s file in %s', ext, node_root_dir) - log.error(logprefix, 'Could not find exports file') - return callback(new Error(msg)) - } - } - - // this logic ported from the old `gyp_addon` python file - var gyp_script = path.resolve(__dirname, '..', 'gyp', 'gyp_main.py') - var addon_gypi = path.resolve(__dirname, '..', 'addon.gypi') - var common_gypi = path.resolve(nodeDir, 'include/node/common.gypi') - fs.stat(common_gypi, function (err, stat) { - if (err) - common_gypi = path.resolve(nodeDir, 'common.gypi') - - var output_dir = 'build' - if (win) { - // Windows expects an absolute path - output_dir = buildDir - } - var nodeGypDir = path.resolve(__dirname, '..') - var nodeLibFile = path.join(nodeDir, - !gyp.opts.nodedir ? '<(target_arch)' : '$(Configuration)', - release.name + '.lib') - - argv.push('-I', addon_gypi) - argv.push('-I', common_gypi) - argv.push('-Dlibrary=shared_library') - argv.push('-Dvisibility=default') - argv.push('-Dnode_root_dir=' + nodeDir) - if (process.platform === 'aix' || process.platform === 'os390') { - argv.push('-Dnode_exp_file=' + node_exp_file) - } - argv.push('-Dnode_gyp_dir=' + nodeGypDir) - argv.push('-Dnode_lib_file=' + nodeLibFile) - argv.push('-Dmodule_root_dir=' + process.cwd()) - argv.push('-Dnode_engine=' + - (gyp.opts.node_engine || process.jsEngine || 'v8')) - argv.push('--depth=.') - argv.push('--no-parallel') - - // tell gyp to write the Makefile/Solution files into output_dir - argv.push('--generator-output', output_dir) - - // tell make to write its output into the same dir - argv.push('-Goutput_dir=.') - - // enforce use of the "binding.gyp" file - argv.unshift('binding.gyp') - - // execute `gyp` from the current target nodedir - argv.unshift(gyp_script) - - // make sure python uses files that came with this particular node package - var pypath = [path.join(__dirname, '..', 'gyp', 'pylib')] - if (process.env.PYTHONPATH) { - pypath.push(process.env.PYTHONPATH) - } - process.env.PYTHONPATH = pypath.join(win ? ';' : ':') - - var cp = gyp.spawn(python, argv) - cp.on('exit', onCpExit) - }) - } - - /** - * Called when the `gyp` child process exits. - */ - - function onCpExit (code, signal) { - if (code !== 0) { - callback(new Error('`gyp` failed with exit code: ' + code)) - } else { - // we're done - callback() - } - } - -} - -/** - * Returns the first file or directory from an array of candidates that is - * readable by the current user, or undefined if none of the candidates are - * readable. - */ -function findAccessibleSync (logprefix, dir, candidates) { - for (var next = 0; next < candidates.length; next++) { - var candidate = path.resolve(dir, candidates[next]) - try { - var fd = fs.openSync(candidate, 'r') - } catch (e) { - // this candidate was not found or not readable, do nothing - log.silly(logprefix, 'Could not open %s: %s', candidate, e.message) - continue - } - fs.closeSync(fd) - log.silly(logprefix, 'Found readable %s', candidate) - return candidate - } - - return undefined -} - -function PythonFinder(python, callback) { - this.callback = callback - this.python = python -} - -PythonFinder.prototype = { - checkPythonLauncherDepth: 0, - env: process.env, - execFile: cp.execFile, - log: log, - resolve: path.win32 && path.win32.resolve || path.resolve, - stat: fs.stat, - which: which, - win: win, - - checkPython: function checkPython () { - this.log.verbose('check python', - 'checking for Python executable "%s" in the PATH', - this.python) - this.which(this.python, function (err, execPath) { - if (err) { - this.log.verbose('`which` failed', this.python, err) - if (this.python === 'python2') { - this.python = 'python' - return this.checkPython() - } - if (this.win) { - this.checkPythonLauncher() - } else { - this.failNoPython() - } - } else { - this.log.verbose('`which` succeeded', this.python, execPath) - // Found the `python` executable, and from now on we use it explicitly. - // This solves #667 and #750 (`execFile` won't run batch files - // (*.cmd, and *.bat)) - this.python = execPath - this.checkPythonVersion() - } - }.bind(this)) - }, - - // Distributions of Python on Windows by default install with the "py.exe" - // Python launcher which is more likely to exist than the Python executable - // being in the $PATH. - // Because the Python launcher supports all versions of Python, we have to - // explicitly request a Python 2 version. This is done by supplying "-2" as - // the first command line argument. Since "py.exe -2" would be an invalid - // executable for "execFile", we have to use the launcher to figure out - // where the actual "python.exe" executable is located. - checkPythonLauncher: function checkPythonLauncher () { - this.checkPythonLauncherDepth += 1 - - this.log.verbose( - 'could not find "' + this.python + '". checking python launcher') - var env = extend({}, this.env) - env.TERM = 'dumb' - - var launcherArgs = ['-2', '-c', 'import sys; print sys.executable'] - this.execFile('py.exe', launcherArgs, { env: env }, function (err, stdout) { - if (err) { - this.guessPython() - } else { - this.python = stdout.trim() - this.log.verbose('check python launcher', - 'python executable found: %j', - this.python) - this.checkPythonVersion() - } - this.checkPythonLauncherDepth -= 1 - }.bind(this)) - }, - - checkPythonVersion: function checkPythonVersion () { - var args = ['-c', 'import sys; print "%s.%s.%s" % sys.version_info[:3];'] - var env = extend({}, this.env) - env.TERM = 'dumb' - - this.execFile(this.python, args, { env: env }, function (err, stdout) { - if (err) { - return this.callback(err) - } - this.log.verbose('check python version', - '`%s -c "' + args[1] + '"` returned: %j', - this.python, stdout) - var version = stdout.trim() - var range = semver.Range('>=2.5.0 <3.0.0') - var valid = false - try { - valid = range.test(version) - } catch (e) { - this.log.silly('range.test() error', e) - } - if (valid) { - this.callback(null, this.python) - } else if (this.win && this.checkPythonLauncherDepth === 0) { - this.checkPythonLauncher() - } else { - this.failPythonVersion(version) - } - }.bind(this)) - }, - - failNoPython: function failNoPython () { - var errmsg = - 'Can\'t find Python executable "' + this.python + - '", you can set the PYTHON env variable.' - this.callback(new Error(errmsg)) - }, - - failPythonVersion: function failPythonVersion (badVersion) { - var errmsg = - 'Python executable "' + this.python + - '" is v' + badVersion + ', which is not supported by gyp.\n' + - 'You can pass the --python switch to point to ' + - 'Python >= v2.5.0 & < 3.0.0.' - this.callback(new Error(errmsg)) - }, - - // Called on Windows when "python" isn't available in the current $PATH. - // We are going to check if "%SystemDrive%\python27\python.exe" exists. - guessPython: function guessPython () { - this.log.verbose('could not find "' + this.python + '". guessing location') - var rootDir = this.env.SystemDrive || 'C:\\' - if (rootDir[rootDir.length - 1] !== '\\') { - rootDir += '\\' - } - var pythonPath = this.resolve(rootDir, 'Python27', 'python.exe') - this.log.verbose('ensuring that file exists:', pythonPath) - this.stat(pythonPath, function (err, stat) { - if (err) { - if (err.code == 'ENOENT') { - this.failNoPython() - } else { - this.callback(err) - } - return - } - this.python = pythonPath - this.checkPythonVersion() - }.bind(this)) - }, -} - -function findPython (python, callback) { - var finder = new PythonFinder(python, callback) - finder.checkPython() -} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-node-directory.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-node-directory.js deleted file mode 100644 index 3aee8a109ae28..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-node-directory.js +++ /dev/null @@ -1,61 +0,0 @@ -var path = require('path') - , log = require('npmlog') - -function findNodeDirectory(scriptLocation, processObj) { - // set dirname and process if not passed in - // this facilitates regression tests - if (scriptLocation === undefined) { - scriptLocation = __dirname - } - if (processObj === undefined) { - processObj = process - } - - // Have a look to see what is above us, to try and work out where we are - npm_parent_directory = path.join(scriptLocation, '../../../..') - log.verbose('node-gyp root', 'npm_parent_directory is ' - + path.basename(npm_parent_directory)) - node_root_dir = "" - - log.verbose('node-gyp root', 'Finding node root directory') - if (path.basename(npm_parent_directory) === 'deps') { - // We are in a build directory where this script lives in - // deps/npm/node_modules/node-gyp/lib - node_root_dir = path.join(npm_parent_directory, '..') - log.verbose('node-gyp root', 'in build directory, root = ' - + node_root_dir) - } else if (path.basename(npm_parent_directory) === 'node_modules') { - // We are in a node install directory where this script lives in - // lib/node_modules/npm/node_modules/node-gyp/lib or - // node_modules/npm/node_modules/node-gyp/lib depending on the - // platform - if (processObj.platform === 'win32') { - node_root_dir = path.join(npm_parent_directory, '..') - } else { - node_root_dir = path.join(npm_parent_directory, '../..') - } - log.verbose('node-gyp root', 'in install directory, root = ' - + node_root_dir) - } else { - // We don't know where we are, try working it out from the location - // of the node binary - var node_dir = path.dirname(processObj.execPath) - var directory_up = path.basename(node_dir) - if (directory_up === 'bin') { - node_root_dir = path.join(node_dir, '..') - } else if (directory_up === 'Release' || directory_up === 'Debug') { - // If we are a recently built node, and the directory structure - // is that of a repository. If we are on Windows then we only need - // to go one level up, everything else, two - if (processObj.platform === 'win32') { - node_root_dir = path.join(node_dir, '..') - } else { - node_root_dir = path.join(node_dir, '../..') - } - } - // Else return the default blank, "". - } - return node_root_dir -} - -module.exports = findNodeDirectory diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-vs2017.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-vs2017.js deleted file mode 100644 index ad46ceaf88c98..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/find-vs2017.js +++ /dev/null @@ -1,46 +0,0 @@ -var log = require('npmlog') - , execFile = require('child_process').execFile - , path = require('path') - -function findVS2017(callback) { - var ps = path.join(process.env.SystemRoot, 'System32', 'WindowsPowerShell', - 'v1.0', 'powershell.exe') - var csFile = path.join(__dirname, 'Find-VS2017.cs') - var psArgs = ['-ExecutionPolicy', 'Unrestricted', '-NoProfile', - '-Command', '&{Add-Type -Path \'' + csFile + '\';' + - '[VisualStudioConfiguration.Main]::Query()}'] - - log.silly('find vs2017', 'Running', ps, psArgs) - var child = execFile(ps, psArgs, { encoding: 'utf8' }, - function (err, stdout, stderr) { - log.silly('find vs2017', 'PS err:', err) - log.silly('find vs2017', 'PS stdout:', stdout) - log.silly('find vs2017', 'PS stderr:', stderr) - - if (err) - return callback(new Error('Could not use PowerShell to find VS2017')) - - var vsSetup - try { - vsSetup = JSON.parse(stdout) - } catch (e) { - log.silly('find vs2017', e) - return callback(new Error('Could not use PowerShell to find VS2017')) - } - log.silly('find vs2017', 'vsSetup:', vsSetup) - - if (vsSetup && vsSetup.log) - log.verbose('find vs2017', vsSetup.log.trimRight()) - - if (!vsSetup || !vsSetup.path || !vsSetup.sdk) { - return callback(new Error('No usable installation of VS2017 found')) - } - - log.verbose('find vs2017', 'using installation:', vsSetup.path) - callback(null, { "path": vsSetup.path, "sdk": vsSetup.sdk }) - }) - - child.stdin.end() -} - -module.exports = findVS2017 diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/install.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/install.js deleted file mode 100644 index cb84972e18325..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/install.js +++ /dev/null @@ -1,475 +0,0 @@ -module.exports = exports = function (gyp, argv, callback) { - return install(fs, gyp, argv, callback) -} - -module.exports.test = { - download: download, - install: install, - readCAFile: readCAFile, -} - -exports.usage = 'Install node development files for the specified node version.' - -/** - * Module dependencies. - */ - -var fs = require('graceful-fs') - , osenv = require('osenv') - , tar = require('tar') - , rm = require('rimraf') - , path = require('path') - , crypto = require('crypto') - , zlib = require('zlib') - , log = require('npmlog') - , semver = require('semver') - , fstream = require('fstream') - , request = require('request') - , mkdir = require('mkdirp') - , processRelease = require('./process-release') - , win = process.platform == 'win32' - -function install (fs, gyp, argv, callback) { - - var release = processRelease(argv, gyp, process.version, process.release) - - // ensure no double-callbacks happen - function cb (err) { - if (cb.done) return - cb.done = true - if (err) { - log.warn('install', 'got an error, rolling back install') - // roll-back the install if anything went wrong - gyp.commands.remove([ release.versionDir ], function (err2) { - callback(err) - }) - } else { - callback(null, release.version) - } - } - - // Determine which node dev files version we are installing - log.verbose('install', 'input version string %j', release.version) - - if (!release.semver) { - // could not parse the version string with semver - return callback(new Error('Invalid version number: ' + release.version)) - } - - if (semver.lt(release.version, '0.8.0')) { - return callback(new Error('Minimum target version is `0.8.0` or greater. Got: ' + release.version)) - } - - // 0.x.y-pre versions are not published yet and cannot be installed. Bail. - if (release.semver.prerelease[0] === 'pre') { - log.verbose('detected "pre" node version', release.version) - if (gyp.opts.nodedir) { - log.verbose('--nodedir flag was passed; skipping install', gyp.opts.nodedir) - callback() - } else { - callback(new Error('"pre" versions of node cannot be installed, use the --nodedir flag instead')) - } - return - } - - // flatten version into String - log.verbose('install', 'installing version: %s', release.versionDir) - - // the directory where the dev files will be installed - var devDir = path.resolve(gyp.devDir, release.versionDir) - - // If '--ensure' was passed, then don't *always* install the version; - // check if it is already installed, and only install when needed - if (gyp.opts.ensure) { - log.verbose('install', '--ensure was passed, so won\'t reinstall if already installed') - fs.stat(devDir, function (err, stat) { - if (err) { - if (err.code == 'ENOENT') { - log.verbose('install', 'version not already installed, continuing with install', release.version) - go() - } else if (err.code == 'EACCES') { - eaccesFallback(err) - } else { - cb(err) - } - return - } - log.verbose('install', 'version is already installed, need to check "installVersion"') - var installVersionFile = path.resolve(devDir, 'installVersion') - fs.readFile(installVersionFile, 'ascii', function (err, ver) { - if (err && err.code != 'ENOENT') { - return cb(err) - } - var installVersion = parseInt(ver, 10) || 0 - log.verbose('got "installVersion"', installVersion) - log.verbose('needs "installVersion"', gyp.package.installVersion) - if (installVersion < gyp.package.installVersion) { - log.verbose('install', 'version is no good; reinstalling') - go() - } else { - log.verbose('install', 'version is good') - cb() - } - }) - }) - } else { - go() - } - - function getContentSha(res, callback) { - var shasum = crypto.createHash('sha256') - 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) - - // first create the dir for the node dev files - mkdir(devDir, function (err, created) { - if (err) { - if (err.code == 'EACCES') { - eaccesFallback(err) - } else { - cb(err) - } - return - } - - if (created) { - log.verbose('created nodedir', created) - } - - // now download the node tarball - var tarPath = gyp.opts.tarball - var 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 () { - var name = this.path.substring(devDir.length + 1) - var isValid = valid(name) - if (name === '' && this.type === 'Directory') { - // the first directory entry is ok - return true - } - if (isValid) { - log.verbose('extracted file from tarball', name) - extractCount++ - } else { - // invalid - log.silly('ignoring from tarball', name) - } - return isValid - } - - gunzip.on('error', cb) - extracter.on('error', cb) - extracter.on('end', afterTarball) - - // download the tarball, gunzip and extract! - - if (tarPath) { - var input = fs.createReadStream(tarPath) - input.pipe(gunzip).pipe(extracter) - return - } - - try { - var req = download(gyp, process.env, release.tarballUrl) - } catch (e) { - return cb(e) - } - - // something went wrong downloading the tarball? - req.on('error', function (err) { - if (err.code === 'ENOTFOUND') { - return cb(new Error('This is most likely not a problem with node-gyp or the package itself and\n' + - 'is related to network connectivity. In most cases you are behind a proxy or have bad \n' + - 'network settings.')) - } - badDownload = true - cb(err) - }) - - req.on('close', function () { - if (extractCount === 0) { - cb(new Error('Connection closed while downloading tarball file')) - } - }) - - req.on('response', function (res) { - if (res.statusCode !== 200) { - badDownload = true - cb(new Error(res.statusCode + ' response downloading ' + release.tarballUrl)) - return - } - // content checksum - getContentSha(res, function (_, checksum) { - var filename = path.basename(release.tarballUrl).trim() - contentShasums[filename] = checksum - log.verbose('content checksum', filename, checksum) - }) - - // start unzipping and untaring - req.pipe(gunzip).pipe(extracter) - }) - - // invoked after the tarball has finished being extracted - function afterTarball () { - if (badDownload) return - if (extractCount === 0) { - return cb(new Error('There was a fatal problem while downloading/extracting the tarball')) - } - log.verbose('tarball', 'done parsing tarball') - var async = 0 - - if (win) { - // need to download node.lib - async++ - downloadNodeLib(deref) - } - - // write the "installVersion" file - async++ - var installVersionPath = path.resolve(devDir, 'installVersion') - fs.writeFile(installVersionPath, gyp.package.installVersion + '\n', deref) - - // Only download SHASUMS.txt if not using tarPath override - if (!tarPath) { - // download SHASUMS.txt - async++ - downloadShasums(deref) - } - - if (async === 0) { - // no async tasks required - cb() - } - - function deref (err) { - if (err) return cb(err) - - async-- - if (!async) { - log.verbose('download contents checksum', JSON.stringify(contentShasums)) - // check content shasums - for (var k in contentShasums) { - log.verbose('validating download checksum for ' + k, '(%s == %s)', contentShasums[k], expectShasums[k]) - if (contentShasums[k] !== expectShasums[k]) { - cb(new Error(k + ' local checksum ' + contentShasums[k] + ' not match remote ' + expectShasums[k])) - return - } - } - cb() - } - } - } - - function downloadShasums(done) { - log.verbose('check download content checksum, need to download `SHASUMS256.txt`...') - var shasumsPath = path.resolve(devDir, 'SHASUMS256.txt') - - log.verbose('checksum url', release.shasumsUrl) - try { - var req = download(gyp, process.env, release.shasumsUrl) - } catch (e) { - return cb(e) - } - - req.on('error', done) - req.on('response', function (res) { - if (res.statusCode !== 200) { - done(new Error(res.statusCode + ' status code downloading checksum')) - 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('checksum data', JSON.stringify(expectShasums)) - done() - }) - }) - } - - function downloadNodeLib (done) { - log.verbose('on Windows; need to download `' + release.name + '.lib`...') - var dir32 = path.resolve(devDir, 'ia32') - , dir64 = path.resolve(devDir, 'x64') - , libPath32 = path.resolve(dir32, release.name + '.lib') - , libPath64 = path.resolve(dir64, release.name + '.lib') - - log.verbose('32-bit ' + release.name + '.lib dir', dir32) - log.verbose('64-bit ' + release.name + '.lib dir', dir64) - log.verbose('`' + release.name + '.lib` 32-bit url', release.libUrl32) - log.verbose('`' + release.name + '.lib` 64-bit url', release.libUrl64) - - var async = 2 - mkdir(dir32, function (err) { - if (err) return done(err) - log.verbose('streaming 32-bit ' + release.name + '.lib to:', libPath32) - - try { - var req = download(gyp, process.env, release.libUrl32, cb) - } catch (e) { - return cb(e) - } - - req.on('error', done) - req.on('response', function (res) { - if (res.statusCode !== 200) { - done(new Error(res.statusCode + ' status code downloading 32-bit ' + release.name + '.lib')) - return - } - - getContentSha(res, function (_, checksum) { - contentShasums[release.libPath32] = checksum - log.verbose('content checksum', release.libPath32, checksum) - }) - - var ws = fs.createWriteStream(libPath32) - ws.on('error', cb) - req.pipe(ws) - }) - req.on('end', function () { - --async || done() - }) - }) - mkdir(dir64, function (err) { - if (err) return done(err) - log.verbose('streaming 64-bit ' + release.name + '.lib to:', libPath64) - - try { - var req = download(gyp, process.env, release.libUrl64, cb) - } catch (e) { - return cb(e) - } - - req.on('error', done) - req.on('response', function (res) { - if (res.statusCode !== 200) { - done(new Error(res.statusCode + ' status code downloading 64-bit ' + release.name + '.lib')) - return - } - - getContentSha(res, function (_, checksum) { - contentShasums[release.libPath64] = checksum - log.verbose('content checksum', release.libPath64, checksum) - }) - - var ws = fs.createWriteStream(libPath64) - ws.on('error', cb) - req.pipe(ws) - }) - req.on('end', function () { - --async || done() - }) - }) - } // downloadNodeLib() - - }) // mkdir() - - } // go() - - /** - * Checks if a given filename is "valid" for this installation. - */ - - function valid (file) { - // header files - var extname = path.extname(file); - return extname === '.h' || extname === '.gypi'; - } - - /** - * The EACCES fallback is a workaround for npm's `sudo` behavior, where - * it drops the permissions before invoking any child processes (like - * node-gyp). So what happens is the "nobody" user doesn't have - * permission to create the dev dir. As a fallback, make the tmpdir() be - * the dev dir for this installation. This is not ideal, but at least - * the compilation will succeed... - */ - - function eaccesFallback (err) { - var noretry = '--node_gyp_internal_noretry' - if (-1 !== argv.indexOf(noretry)) return cb(err) - var tmpdir = osenv.tmpdir() - gyp.devDir = path.resolve(tmpdir, '.node-gyp') - log.warn('EACCES', 'user "%s" does not have permission to access the dev dir "%s"', osenv.user(), devDir) - log.warn('EACCES', 'attempting to reinstall using temporary dev dir "%s"', gyp.devDir) - if (process.cwd() == tmpdir) { - log.verbose('tmpdir == cwd', 'automatically will remove dev files after to save disk space') - gyp.todo.push({ name: 'remove', args: argv }) - } - gyp.commands.install([noretry].concat(argv), cb) - } - -} - -function download (gyp, env, url) { - log.http('GET', url) - - var requestOpts = { - uri: url - , headers: { - 'User-Agent': 'node-gyp v' + gyp.version + ' (node ' + process.version + ')' - } - } - - var cafile = gyp.opts.cafile - if (cafile) { - requestOpts.ca = readCAFile(cafile) - } - - // basic support for a proxy server - var proxyUrl = gyp.opts.proxy - || env.http_proxy - || env.HTTP_PROXY - || env.npm_config_proxy - if (proxyUrl) { - if (/^https?:\/\//i.test(proxyUrl)) { - log.verbose('download', 'using proxy url: "%s"', proxyUrl) - requestOpts.proxy = proxyUrl - } else { - log.warn('download', 'ignoring invalid "proxy" config setting: "%s"', proxyUrl) - } - } - - var req = request(requestOpts) - req.on('response', function (res) { - log.http(res.statusCode, url) - }) - - return req -} - -function readCAFile (filename) { - // The CA file can contain multiple certificates so split on certificate - // boundaries. [\S\s]*? is used to match everything including newlines. - var ca = fs.readFileSync(filename, 'utf8') - var re = /(-----BEGIN CERTIFICATE-----[\S\s]*?-----END CERTIFICATE-----)/g - return ca.match(re) -} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/list.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/list.js deleted file mode 100644 index 9d680a56a434a..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/list.js +++ /dev/null @@ -1,33 +0,0 @@ - -module.exports = exports = list - -exports.usage = 'Prints a listing of the currently installed node development files' - -/** - * Module dependencies. - */ - -var fs = require('graceful-fs') - , path = require('path') - , log = require('npmlog') - -function list (gyp, args, callback) { - - var devDir = gyp.devDir - log.verbose('list', 'using node-gyp dir:', devDir) - - // readdir() the node-gyp dir - fs.readdir(devDir, onreaddir) - - function onreaddir (err, versions) { - if (err && err.code != 'ENOENT') { - return callback(err) - } - if (Array.isArray(versions)) { - versions = versions.filter(function (v) { return v != 'current' }) - } else { - versions = [] - } - callback(null, versions) - } -} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/node-gyp.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/node-gyp.js deleted file mode 100644 index a841161e32eec..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/node-gyp.js +++ /dev/null @@ -1,216 +0,0 @@ - -/** - * Module exports. - */ - -module.exports = exports = gyp - -/** - * Module dependencies. - */ - -var fs = require('graceful-fs') - , path = require('path') - , nopt = require('nopt') - , log = require('npmlog') - , child_process = require('child_process') - , EE = require('events').EventEmitter - , inherits = require('util').inherits - , commands = [ - // Module build commands - 'build' - , 'clean' - , 'configure' - , 'rebuild' - // Development Header File management commands - , 'install' - , 'list' - , 'remove' - ] - , aliases = { - 'ls': 'list' - , 'rm': 'remove' - } - -// differentiate node-gyp's logs from npm's -log.heading = 'gyp' - -/** - * The `gyp` function. - */ - -function gyp () { - return new Gyp() -} - -function Gyp () { - var self = this - - this.devDir = '' - this.commands = {} - - commands.forEach(function (command) { - self.commands[command] = function (argv, callback) { - log.verbose('command', command, argv) - return require('./' + command)(self, argv, callback) - } - }) -} -inherits(Gyp, EE) -exports.Gyp = Gyp -var proto = Gyp.prototype - -/** - * Export the contents of the package.json. - */ - -proto.package = require('../package') - -/** - * nopt configuration definitions - */ - -proto.configDefs = { - help: Boolean // everywhere - , arch: String // 'configure' - , cafile: String // 'install' - , debug: Boolean // 'build' - , directory: String // bin - , make: String // 'build' - , msvs_version: String // 'configure' - , ensure: Boolean // 'install' - , solution: String // 'build' (windows only) - , proxy: String // 'install' - , devdir: String // everywhere - , nodedir: String // 'configure' - , loglevel: String // everywhere - , python: String // 'configure' - , 'dist-url': String // 'install' - , 'tarball': String // 'install' - , jobs: String // 'build' - , thin: String // 'configure' -} - -/** - * nopt shorthands - */ - -proto.shorthands = { - release: '--no-debug' - , C: '--directory' - , debug: '--debug' - , j: '--jobs' - , silly: '--loglevel=silly' - , verbose: '--loglevel=verbose' - , silent: '--loglevel=silent' -} - -/** - * expose the command aliases for the bin file to use. - */ - -proto.aliases = aliases - -/** - * Parses the given argv array and sets the 'opts', - * 'argv' and 'command' properties. - */ - -proto.parseArgv = function parseOpts (argv) { - this.opts = nopt(this.configDefs, this.shorthands, argv) - this.argv = this.opts.argv.remain.slice() - - var commands = this.todo = [] - - // create a copy of the argv array with aliases mapped - argv = this.argv.map(function (arg) { - // is this an alias? - if (arg in this.aliases) { - arg = this.aliases[arg] - } - return arg - }, this) - - // process the mapped args into "command" objects ("name" and "args" props) - argv.slice().forEach(function (arg) { - if (arg in this.commands) { - var args = argv.splice(0, argv.indexOf(arg)) - argv.shift() - if (commands.length > 0) { - commands[commands.length - 1].args = args - } - commands.push({ name: arg, args: [] }) - } - }, this) - if (commands.length > 0) { - commands[commands.length - 1].args = argv.splice(0) - } - - // support for inheriting config env variables from npm - var npm_config_prefix = 'npm_config_' - Object.keys(process.env).forEach(function (name) { - if (name.indexOf(npm_config_prefix) !== 0) return - var val = process.env[name] - if (name === npm_config_prefix + 'loglevel') { - log.level = val - } else { - // add the user-defined options to the config - name = name.substring(npm_config_prefix.length) - // gyp@741b7f1 enters an infinite loop when it encounters - // zero-length options so ensure those don't get through. - if (name) this.opts[name] = val - } - }, this) - - if (this.opts.loglevel) { - log.level = this.opts.loglevel - } - log.resume() -} - -/** - * Spawns a child process and emits a 'spawn' event. - */ - -proto.spawn = function spawn (command, args, opts) { - if (!opts) opts = {} - if (!opts.silent && !opts.stdio) { - opts.stdio = [ 0, 1, 2 ] - } - var cp = child_process.spawn(command, args, opts) - log.info('spawn', command) - log.info('spawn args', args) - return cp -} - -/** - * Returns the usage instructions for node-gyp. - */ - -proto.usage = function usage () { - var str = [ - '' - , ' Usage: node-gyp [options]' - , '' - , ' where is one of:' - , commands.map(function (c) { - return ' - ' + c + ' - ' + require('./' + c).usage - }).join('\n') - , '' - , 'node-gyp@' + this.version + ' ' + path.resolve(__dirname, '..') - , 'node@' + process.versions.node - ].join('\n') - return str -} - -/** - * Version number getter. - */ - -Object.defineProperty(proto, 'version', { - get: function () { - return this.package.version - } - , enumerable: true -}) - diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/process-release.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/process-release.js deleted file mode 100644 index 0d177f1c93e4d..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/process-release.js +++ /dev/null @@ -1,155 +0,0 @@ -var semver = require('semver') - , url = require('url') - , path = require('path') - , log = require('npmlog') - - // versions where -headers.tar.gz started shipping - , headersTarballRange = '>= 3.0.0 || ~0.12.10 || ~0.10.42' - , bitsre = /\/win-(x86|x64)\// - , bitsreV3 = /\/win-(x86|ia32|x64)\// // io.js v3.x.x shipped with "ia32" but should - // have been "x86" - -// Captures all the logic required to determine download URLs, local directory and -// file names. Inputs come from command-line switches (--target, --dist-url), -// `process.version` and `process.release` where it exists. -function processRelease (argv, gyp, defaultVersion, defaultRelease) { - var version = (semver.valid(argv[0]) && argv[0]) || gyp.opts.target || defaultVersion - , versionSemver = semver.parse(version) - , overrideDistUrl = gyp.opts['dist-url'] || gyp.opts.disturl - , isDefaultVersion - , isIojs - , name - , distBaseUrl - , baseUrl - , libUrl32 - , libUrl64 - , tarballUrl - , canGetHeaders - - if (!versionSemver) { - // not a valid semver string, nothing we can do - return { version: version } - } - // flatten version into String - version = versionSemver.version - - // defaultVersion should come from process.version so ought to be valid semver - isDefaultVersion = version === semver.parse(defaultVersion).version - - // can't use process.release if we're using --target=x.y.z - if (!isDefaultVersion) - defaultRelease = null - - if (defaultRelease) { - // v3 onward, has process.release - name = defaultRelease.name.replace(/io\.js/, 'iojs') // remove the '.' for directory naming purposes - isIojs = name === 'iojs' - } else { - // old node or alternative --target= - // semver.satisfies() doesn't like prerelease tags so test major directly - isIojs = versionSemver.major >= 1 && versionSemver.major < 4 - name = isIojs ? 'iojs' : 'node' - } - - // check for the nvm.sh standard mirror env variables - if (!overrideDistUrl) { - if (isIojs) { - if (process.env.IOJS_ORG_MIRROR) { - overrideDistUrl = process.env.IOJS_ORG_MIRROR - } else if (process.env.NVM_IOJS_ORG_MIRROR) {// remove on next semver-major - overrideDistUrl = process.env.NVM_IOJS_ORG_MIRROR - log.warn('download', - 'NVM_IOJS_ORG_MIRROR is deprecated and will be removed in node-gyp v4, ' + - 'please use IOJS_ORG_MIRROR') - } - } else { - if (process.env.NODEJS_ORG_MIRROR) { - overrideDistUrl = process.env.NODEJS_ORG_MIRROR - } else if (process.env.NVM_NODEJS_ORG_MIRROR) {// remove on next semver-major - overrideDistUrl = process.env.NVM_NODEJS_ORG_MIRROR - log.warn('download', - 'NVM_NODEJS_ORG_MIRROR is deprecated and will be removed in node-gyp v4, ' + - 'please use NODEJS_ORG_MIRROR') - } - } - } - - if (overrideDistUrl) - log.verbose('download', 'using dist-url', overrideDistUrl) - - if (overrideDistUrl) - distBaseUrl = overrideDistUrl.replace(/\/+$/, '') - else - distBaseUrl = isIojs ? 'https://iojs.org/download/release' : 'https://nodejs.org/dist' - distBaseUrl += '/v' + version + '/' - - // new style, based on process.release so we have a lot of the data we need - if (defaultRelease && defaultRelease.headersUrl && !overrideDistUrl) { - baseUrl = url.resolve(defaultRelease.headersUrl, './') - libUrl32 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || distBaseUrl, 'x86', versionSemver.major) - libUrl64 = resolveLibUrl(name, defaultRelease.libUrl || baseUrl || distBaseUrl, 'x64', versionSemver.major) - - return { - version: version, - semver: versionSemver, - name: name, - baseUrl: baseUrl, - tarballUrl: defaultRelease.headersUrl, - shasumsUrl: url.resolve(baseUrl, 'SHASUMS256.txt'), - versionDir: (name !== 'node' ? name + '-' : '') + version, - libUrl32: libUrl32, - libUrl64: libUrl64, - libPath32: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrl32).path)), - libPath64: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrl64).path)) - } - } - - // older versions without process.release are captured here and we have to make - // a lot of assumptions, additionally if you --target=x.y.z then we can't use the - // current process.release - - baseUrl = distBaseUrl - libUrl32 = resolveLibUrl(name, baseUrl, 'x86', versionSemver.major) - libUrl64 = resolveLibUrl(name, baseUrl, 'x64', versionSemver.major) - // making the bold assumption that anything with a version number >3.0.0 will - // have a *-headers.tar.gz file in its dist location, even some frankenstein - // custom version - canGetHeaders = semver.satisfies(versionSemver, headersTarballRange) - tarballUrl = url.resolve(baseUrl, name + '-v' + version + (canGetHeaders ? '-headers' : '') + '.tar.gz') - - return { - version: version, - semver: versionSemver, - name: name, - baseUrl: baseUrl, - tarballUrl: tarballUrl, - shasumsUrl: url.resolve(baseUrl, 'SHASUMS256.txt'), - versionDir: (name !== 'node' ? name + '-' : '') + version, - libUrl32: libUrl32, - libUrl64: libUrl64, - libPath32: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrl32).path)), - libPath64: normalizePath(path.relative(url.parse(baseUrl).path, url.parse(libUrl64).path)) - } -} - -function normalizePath (p) { - return path.normalize(p).replace(/\\/g, '/') -} - -function resolveLibUrl (name, defaultUrl, arch, versionMajor) { - var base = url.resolve(defaultUrl, './') - , hasLibUrl = bitsre.test(defaultUrl) || (versionMajor === 3 && bitsreV3.test(defaultUrl)) - - if (!hasLibUrl) { - // let's assume it's a baseUrl then - if (versionMajor >= 1) - return url.resolve(base, 'win-' + arch +'/' + name + '.lib') - // prior to io.js@1.0.0 32-bit node.lib lives in /, 64-bit lives in /x64/ - return url.resolve(base, (arch === 'x64' ? 'x64/' : '') + name + '.lib') - } - - // else we have a proper url to a .lib, just make sure it's the right arch - return defaultUrl.replace(versionMajor === 3 ? bitsreV3 : bitsre, '/win-' + arch + '/') -} - -module.exports = processRelease diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/rebuild.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/rebuild.js deleted file mode 100644 index 4c6f472aa7c07..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/rebuild.js +++ /dev/null @@ -1,14 +0,0 @@ - -module.exports = exports = rebuild - -exports.usage = 'Runs "clean", "configure" and "build" all at once' - -function rebuild (gyp, argv, callback) { - - gyp.todo.push( - { name: 'clean', args: [] } - , { name: 'configure', args: argv } - , { name: 'build', args: [] } - ) - process.nextTick(callback) -} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/remove.js b/node_modules/npm-lifecycle/node_modules/node-gyp/lib/remove.js deleted file mode 100644 index eb80981b88feb..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/lib/remove.js +++ /dev/null @@ -1,52 +0,0 @@ - -module.exports = exports = remove - -exports.usage = 'Removes the node development files for the specified version' - -/** - * Module dependencies. - */ - -var fs = require('fs') - , rm = require('rimraf') - , path = require('path') - , log = require('npmlog') - , semver = require('semver') - -function remove (gyp, argv, callback) { - - var devDir = gyp.devDir - log.verbose('remove', 'using node-gyp dir:', devDir) - - // get the user-specified version to remove - var version = argv[0] || gyp.opts.target - log.verbose('remove', 'removing target version:', version) - - if (!version) { - return callback(new Error('You must specify a version number to remove. Ex: "' + process.version + '"')) - } - - var versionSemver = semver.parse(version) - if (versionSemver) { - // flatten the version Array into a String - version = versionSemver.version - } - - var versionPath = path.resolve(gyp.devDir, version) - log.verbose('remove', 'removing development files for version:', version) - - // first check if its even installed - fs.stat(versionPath, function (err, stat) { - if (err) { - if (err.code == 'ENOENT') { - callback(null, 'version was already uninstalled: ' + version) - } else { - callback(err) - } - return - } - // Go ahead and delete the dir - rm(versionPath, callback) - }) - -} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/package.json b/node_modules/npm-lifecycle/node_modules/node-gyp/package.json deleted file mode 100644 index 6a1cda10d52a4..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/package.json +++ /dev/null @@ -1,85 +0,0 @@ -{ - "_from": "node-gyp@^3.8.0", - "_id": "node-gyp@3.8.0", - "_inBundle": false, - "_integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", - "_location": "/npm-lifecycle/node-gyp", - "_phantomChildren": {}, - "_requested": { - "type": "range", - "registry": true, - "raw": "node-gyp@^3.8.0", - "name": "node-gyp", - "escapedName": "node-gyp", - "rawSpec": "^3.8.0", - "saveSpec": null, - "fetchSpec": "^3.8.0" - }, - "_requiredBy": [ - "/npm-lifecycle" - ], - "_resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "_shasum": "540304261c330e80d0d5edce253a68cb3964218c", - "_spec": "node-gyp@^3.8.0", - "_where": "/home/hugh/Development/github.com/npm/cli/node_modules/npm-lifecycle", - "author": { - "name": "Nathan Rajlich", - "email": "nathan@tootallnate.net", - "url": "http://tootallnate.net" - }, - "bin": { - "node-gyp": "./bin/node-gyp.js" - }, - "bugs": { - "url": "https://github.com/nodejs/node-gyp/issues" - }, - "bundleDependencies": false, - "dependencies": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - }, - "deprecated": false, - "description": "Node.js native addon build tool", - "devDependencies": { - "bindings": "~1.2.1", - "nan": "^2.0.0", - "require-inject": "~1.3.0", - "tape": "~4.2.0" - }, - "engines": { - "node": ">= 0.8.0" - }, - "homepage": "https://github.com/nodejs/node-gyp#readme", - "installVersion": 9, - "keywords": [ - "native", - "addon", - "module", - "c", - "c++", - "bindings", - "gyp" - ], - "license": "MIT", - "main": "./lib/node-gyp.js", - "name": "node-gyp", - "preferGlobal": true, - "repository": { - "type": "git", - "url": "git://github.com/nodejs/node-gyp.git" - }, - "scripts": { - "test": "tape test/test-*" - }, - "version": "3.8.0" -} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/src/win_delay_load_hook.cc b/node_modules/npm-lifecycle/node_modules/node-gyp/src/win_delay_load_hook.cc deleted file mode 100644 index e75954b605101..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/src/win_delay_load_hook.cc +++ /dev/null @@ -1,36 +0,0 @@ -/* - * When this file is linked to a DLL, it sets up a delay-load hook that - * intervenes when the DLL is trying to load 'node.exe' or 'iojs.exe' - * dynamically. Instead of trying to locate the .exe file it'll just return - * a handle to the process image. - * - * This allows compiled addons to work when node.exe or iojs.exe is renamed. - */ - -#ifdef _MSC_VER - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include - -#include -#include - -static FARPROC WINAPI load_exe_hook(unsigned int event, DelayLoadInfo* info) { - HMODULE m; - if (event != dliNotePreLoadLibrary) - return NULL; - - if (_stricmp(info->szDll, "iojs.exe") != 0 && - _stricmp(info->szDll, "node.exe") != 0) - return NULL; - - m = GetModuleHandle(NULL); - return (FARPROC) m; -} - -decltype(__pfnDliNotifyHook2) __pfnDliNotifyHook2 = load_exe_hook; - -#endif diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/docker.sh b/node_modules/npm-lifecycle/node_modules/node-gyp/test/docker.sh deleted file mode 100755 index ac21aa8d75c98..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/docker.sh +++ /dev/null @@ -1,164 +0,0 @@ -#!/bin/bash - -#set -e - -test_node_versions="0.8.28 0.10.40 0.12.7 4.3.0 5.6.0" -test_iojs_versions="1.8.4 2.4.0 3.3.0" - -myuid=$(id -u) -mygid=$(id -g) -__dirname="$(CDPATH= cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -dot_node_gyp=${__dirname}/.node-gyp/ - -# borrows from https://github.com/rvagg/dnt/ - -# Simple setup function for a container: -# setup_container(image id, base image, commands to run to set up) -setup_container() { - local container_id="$1" - local base_container="$2" - local run_cmd="$3" - - # Does this image exist? If yes, ignore - docker inspect "$container_id" &> /dev/null - if [[ $? -eq 0 ]]; then - echo "Found existing container [$container_id]" - else - # No such image, so make it - echo "Did not find container [$container_id], creating..." - docker run -i $base_container /bin/bash -c "$run_cmd" - sleep 2 - docker commit $(docker ps -l -q) $container_id - fi -} - -# Run tests inside each of the versioned containers, copy cwd into npm's copy of node-gyp -# so it'll be invoked by npm when a compile is needed -# run_tests(version, test-commands) -run_tests() { - local version="$1" - local run_cmd="$2" - - run_cmd="rsync -aAXx --delete --exclude .git --exclude build /node-gyp-src/ /usr/lib/node_modules/npm/node_modules/node-gyp/; - /bin/su -s /bin/bash node-gyp -c 'cd && ${run_cmd}'" - - rm -rf $dot_node_gyp - mkdir $dot_node_gyp - - docker run \ - --rm -i \ - -v ~/.npm/:/node-gyp/.npm/ \ - -v ${dot_node_gyp}:/node-gyp/.node-gyp/ \ - -v $(pwd):/node-gyp-src/:ro \ - node-gyp-test/${version} /bin/bash -c "${run_cmd}" -} - -# A base image with build tools and a user account -setup_container "node-gyp-test/base" "ubuntu:14.04" " - adduser --gecos node-gyp --home /node-gyp/ --disabled-login node-gyp --uid $myuid && - echo "node-gyp:node-gyp" | chpasswd && - apt-get update && - apt-get install -y build-essential python git rsync curl -" - -# An image on top of the base containing clones of repos we want to use for testing -setup_container "node-gyp-test/clones" "node-gyp-test/base" " - cd /node-gyp/ && git clone https://github.com/justmoon/node-bignum.git && - cd /node-gyp/ && git clone https://github.com/bnoordhuis/node-buffertools.git && - chown -R node-gyp.node-gyp /node-gyp/ -" - -# An image for each of the node versions we want to test with that version installed and the latest npm -for v in $test_node_versions; do - setup_container "node-gyp-test/${v}" "node-gyp-test/clones" " - curl -sL https://nodejs.org/dist/v${v}/node-v${v}-linux-x64.tar.gz | tar -zxv --strip-components=1 -C /usr/ && - npm install npm@latest -g && - node -v && npm -v - " -done - -# An image for each of the io.js versions we want to test with that version installed and the latest npm -for v in $test_iojs_versions; do - setup_container "node-gyp-test/${v}" "node-gyp-test/clones" " - curl -sL https://iojs.org/dist/v${v}/iojs-v${v}-linux-x64.tar.gz | tar -zxv --strip-components=1 -C /usr/ && - npm install npm@latest -g && - node -v && npm -v - " -done - -# Run the tests for all of the test images we've created, -# we should see node-gyp doing its download, configure and run thing -# _NOTE: bignum doesn't compile on 0.8 currently so it'll fail for that version only_ -for v in $test_node_versions $test_iojs_versions; do - run_tests $v " - cd node-buffertools && npm install --loglevel=info && npm test && cd - " - # removed for now, too noisy: cd node-bignum && npm install --loglevel=info && npm test -done - -# Test use of --target=x.y.z to compile against alternate versions -test_download_node_version() { - local run_with_ver="$1" - local expected_dir="$2" - local expected_ver="$3" - run_tests $run_with_ver "cd node-buffertools && npm install --loglevel=info --target=${expected_ver}" - local node_ver=$(cat "${dot_node_gyp}${expected_dir}/node_version.h" | grep '#define NODE_\w*_VERSION [0-9]*$') - node_ver=$(echo $node_ver | sed 's/#define NODE_[A-Z]*_VERSION //g' | sed 's/ /./g') - if [ "X$(echo $node_ver)" != "X${expected_ver}" ]; then - echo "Did not download v${expected_ver} using --target, instead got: $(echo $node_ver)" - exit 1 - fi - echo "Verified correct download of [v${node_ver}]" -} - -test_download_node_version "0.12.7" "0.10.30/src" "0.10.30" -test_download_node_version "3.3.0" "iojs-1.8.4/src" "1.8.4" -# should download the headers file -test_download_node_version "3.3.0" "iojs-3.3.0/include/node" "3.3.0" -test_download_node_version "4.3.0" "4.3.0/include/node" "4.3.0" -test_download_node_version "5.6.0" "5.6.0/include/node" "5.6.0" - -# TODO: test --dist-url by starting up a localhost server and serving up tarballs - -# testing --dist-url, using simple-proxy.js to make localhost work as a distribution -# point for tarballs -# we can test whether it uses the proxy because after 2 connections the proxy will -# die and therefore should not be running at the end of the test, `nc` can tell us this -run_tests "3.3.0" " - (node /node-gyp-src/test/simple-proxy.js 8080 /foobar/ https://iojs.org/dist/ &) && - cd node-buffertools && - /node-gyp-src/bin/node-gyp.js --loglevel=info --dist-url=http://localhost:8080/foobar/ rebuild && - nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\" -" - -# REMOVE after next semver-major -run_tests "3.3.0" " - (node /node-gyp-src/test/simple-proxy.js 8080 /doobar/ https://iojs.org/dist/ &) && - cd node-buffertools && - NVM_IOJS_ORG_MIRROR=http://localhost:8080/doobar/ /node-gyp-src/bin/node-gyp.js --loglevel=info rebuild && - nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\" -" - -# REMOVE after next semver-major -run_tests "0.12.7" " - (node /node-gyp-src/test/simple-proxy.js 8080 /boombar/ https://nodejs.org/dist/ &) && - cd node-buffertools && - NVM_NODEJS_ORG_MIRROR=http://localhost:8080/boombar/ /node-gyp-src/bin/node-gyp.js --loglevel=info rebuild && - nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\" -" - -run_tests "3.3.0" " - (node /node-gyp-src/test/simple-proxy.js 8080 /doobar/ https://iojs.org/dist/ &) && - cd node-buffertools && - IOJS_ORG_MIRROR=http://localhost:8080/doobar/ /node-gyp-src/bin/node-gyp.js --loglevel=info rebuild && - nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\" -" - -run_tests "0.12.7" " - (node /node-gyp-src/test/simple-proxy.js 8080 /boombar/ https://nodejs.org/dist/ &) && - cd node-buffertools && - NODEJS_ORG_MIRROR=http://localhost:8080/boombar/ /node-gyp-src/bin/node-gyp.js --loglevel=info rebuild && - nc -z localhost 8080 && echo -e \"\\n\\n\\033[31mFAILED TO USE LOCAL PROXY\\033[39m\\n\\n\" -" - -rm -rf $dot_node_gyp diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca-bundle.crt b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca-bundle.crt deleted file mode 100644 index fb1dea98a78c8..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca-bundle.crt +++ /dev/null @@ -1,40 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDJjCCAg4CAhnOMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNVBAYTAlVTMQswCQYD -VQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQU3Ryb25n -TG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRowGAYDVQQDDBFjYS5zdHJv -bmdsb29wLmNvbTAeFw0xNTEyMDgyMzM1MzNaFw00MzA0MjQyMzM1MzNaMBkxFzAV -BgNVBAMMDnN0cm9uZ2xvb3AuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAwOYI7OZ2FX/YjRgLZoDQlbPc5UZXU/j0e1wwiJNPtPEax9Y5Uoza0Pnt -Ikzkc2SfvQ+IJrhXo385tI0W5juuqbHnE7UrjUuPjUX6NHevkxcs/flmjan5wnZM -cPsGhH71WDuUEEflvZihf2Se2x+xgZtMhc5XGmVmRuZFYKvkgUhA2/w8/QrK+jPT -n9QRJxZjWNh2RBdC1B7u4jffSmOSUljYFH1I2eTeY+Rdi6YUIYSU9gEoZxsv3Tia -SomfMF5jt2Mouo6MzA+IhLvvFjcrcph1Qxgi9RkfdCMMd+Ipm9YWELkyG1bDRpQy -0iyHD4gvVsAqz1Y2KdRSdc3Kt+nTqwIDAQABoxkwFzAVBgNVHREEDjAMhwQAAAAA -hwR/AAABMA0GCSqGSIb3DQEBBQUAA4IBAQAhy4J0hML3NgmDRHdL5/iTucBe22Mf -jJjg2aifD1S187dHm+Il4qZNO2plWwAhN0h704f+8wpsaALxUvBIu6nvlvcMP5PH -jGN5JLe2Km3UaPvYOQU2SgacLilu+uBcIo2JSHLV6O7ziqUj5Gior6YxDLCtEZie -Ea8aX5/YjuACtEMJ1JjRqjgkM66XAoUe0E8onOK3FgTIO3tGoTJwRp0zS50pFuP0 -PsZtT04ck6mmXEXXknNoAyBCvPypfms9OHqcUIW9fiQnrGbS/Ri4QSQYj0DtFk/1 -na4fY1gf3zTHxH8259b/TOOaPfTnCEsOQtjUrWNR4xhmVZ+HJy4yytUW ------END CERTIFICATE----- ------BEGIN CERTIFICATE----- -MIIDbzCCAlcCAmm6MA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAlVTMQswCQYD -VQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQU3Ryb25n -TG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRowGAYDVQQDDBFjYS5zdHJv -bmdsb29wLmNvbTAeFw0xNTEyMDgyMzM1MzNaFw00MzA0MjQyMzM1MzNaMH0xCzAJ -BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZ -MBcGA1UECgwQU3Ryb25nTG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRow -GAYDVQQDDBFjYS5zdHJvbmdsb29wLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBANfj86jkvvYDjHBgiqWhk9Cj+bqiMq3MqnV0CBO4iuK33Fo6XssE -H+yVdXlIBFbFe6t655MdBVOR2Sfj7WqNh96vhu6PyDHiwcQlTaiLU6nhIed1J4Wv -lvnJHFmp8Wbtx5AgLT4UYu03ftvXEl2DLi3vhSL2tRM1ebXHB/KPbRWkb25DPX0P -foOHot3f2dgNe2x6kponf7E/QDmAu3s7Nlkfh+ryDhgGU7wocXEhXbprNqRqOGNo -xbXgUI+/9XDxYT/7Gn5LF/fPjtN+aB0SKMnTsDhprVlZie83mlqJ46fOOrR+vrsQ -mi/1m/TadrARtZoIExC/cQRdVM05EK4tUa8CAwEAATANBgkqhkiG9w0BAQsFAAOC -AQEAQ7k5WhyhDTIGYCNzRnrMHWSzGqa1y4tJMW06wafJNRqTm1cthq1ibc6Hfq5a -K10K0qMcgauRTfQ1MWrVCTW/KnJ1vkhiTOH+RvxapGn84gSaRmV6KZen0+gMsgae -KEGe/3Hn+PmDVV+PTamHgPACfpTww38WHIe/7Ce9gHfG7MZ8cKHNZhDy0IAYPln+ -YRwMLd7JNQffHAbWb2CE1mcea4H/12U8JZW5tHCF6y9V+7IuDzqwIrLKcW3lG17n -VUG6ODF/Ryqn3V5X+TL91YyXi6c34y34IpC7MQDV/67U7+5Bp5CfeDPWW2wVSrW+ -uGZtfEvhbNm6m2i4UNmpCXxUZQ== ------END CERTIFICATE----- diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca.crt b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca.crt deleted file mode 100644 index 9d2755a74f6cd..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/ca.crt +++ /dev/null @@ -1,21 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDbzCCAlcCAmm6MA0GCSqGSIb3DQEBCwUAMH0xCzAJBgNVBAYTAlVTMQswCQYD -VQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQU3Ryb25n -TG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRowGAYDVQQDDBFjYS5zdHJv -bmdsb29wLmNvbTAeFw0xNTEyMDgyMzM1MzNaFw00MzA0MjQyMzM1MzNaMH0xCzAJ -BgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZ -MBcGA1UECgwQU3Ryb25nTG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRow -GAYDVQQDDBFjYS5zdHJvbmdsb29wLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEP -ADCCAQoCggEBANfj86jkvvYDjHBgiqWhk9Cj+bqiMq3MqnV0CBO4iuK33Fo6XssE -H+yVdXlIBFbFe6t655MdBVOR2Sfj7WqNh96vhu6PyDHiwcQlTaiLU6nhIed1J4Wv -lvnJHFmp8Wbtx5AgLT4UYu03ftvXEl2DLi3vhSL2tRM1ebXHB/KPbRWkb25DPX0P -foOHot3f2dgNe2x6kponf7E/QDmAu3s7Nlkfh+ryDhgGU7wocXEhXbprNqRqOGNo -xbXgUI+/9XDxYT/7Gn5LF/fPjtN+aB0SKMnTsDhprVlZie83mlqJ46fOOrR+vrsQ -mi/1m/TadrARtZoIExC/cQRdVM05EK4tUa8CAwEAATANBgkqhkiG9w0BAQsFAAOC -AQEAQ7k5WhyhDTIGYCNzRnrMHWSzGqa1y4tJMW06wafJNRqTm1cthq1ibc6Hfq5a -K10K0qMcgauRTfQ1MWrVCTW/KnJ1vkhiTOH+RvxapGn84gSaRmV6KZen0+gMsgae -KEGe/3Hn+PmDVV+PTamHgPACfpTww38WHIe/7Ce9gHfG7MZ8cKHNZhDy0IAYPln+ -YRwMLd7JNQffHAbWb2CE1mcea4H/12U8JZW5tHCF6y9V+7IuDzqwIrLKcW3lG17n -VUG6ODF/Ryqn3V5X+TL91YyXi6c34y34IpC7MQDV/67U7+5Bp5CfeDPWW2wVSrW+ -uGZtfEvhbNm6m2i4UNmpCXxUZQ== ------END CERTIFICATE----- diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.crt b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.crt deleted file mode 100644 index fe13bb96c599c..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.crt +++ /dev/null @@ -1,19 +0,0 @@ ------BEGIN CERTIFICATE----- -MIIDJjCCAg4CAhnOMA0GCSqGSIb3DQEBBQUAMH0xCzAJBgNVBAYTAlVTMQswCQYD -VQQIDAJDQTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEZMBcGA1UECgwQU3Ryb25n -TG9vcCwgSW5jLjESMBAGA1UECwwJU3Ryb25nT3BzMRowGAYDVQQDDBFjYS5zdHJv -bmdsb29wLmNvbTAeFw0xNTEyMDgyMzM1MzNaFw00MzA0MjQyMzM1MzNaMBkxFzAV -BgNVBAMMDnN0cm9uZ2xvb3AuY29tMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB -CgKCAQEAwOYI7OZ2FX/YjRgLZoDQlbPc5UZXU/j0e1wwiJNPtPEax9Y5Uoza0Pnt -Ikzkc2SfvQ+IJrhXo385tI0W5juuqbHnE7UrjUuPjUX6NHevkxcs/flmjan5wnZM -cPsGhH71WDuUEEflvZihf2Se2x+xgZtMhc5XGmVmRuZFYKvkgUhA2/w8/QrK+jPT -n9QRJxZjWNh2RBdC1B7u4jffSmOSUljYFH1I2eTeY+Rdi6YUIYSU9gEoZxsv3Tia -SomfMF5jt2Mouo6MzA+IhLvvFjcrcph1Qxgi9RkfdCMMd+Ipm9YWELkyG1bDRpQy -0iyHD4gvVsAqz1Y2KdRSdc3Kt+nTqwIDAQABoxkwFzAVBgNVHREEDjAMhwQAAAAA -hwR/AAABMA0GCSqGSIb3DQEBBQUAA4IBAQAhy4J0hML3NgmDRHdL5/iTucBe22Mf -jJjg2aifD1S187dHm+Il4qZNO2plWwAhN0h704f+8wpsaALxUvBIu6nvlvcMP5PH -jGN5JLe2Km3UaPvYOQU2SgacLilu+uBcIo2JSHLV6O7ziqUj5Gior6YxDLCtEZie -Ea8aX5/YjuACtEMJ1JjRqjgkM66XAoUe0E8onOK3FgTIO3tGoTJwRp0zS50pFuP0 -PsZtT04ck6mmXEXXknNoAyBCvPypfms9OHqcUIW9fiQnrGbS/Ri4QSQYj0DtFk/1 -na4fY1gf3zTHxH8259b/TOOaPfTnCEsOQtjUrWNR4xhmVZ+HJy4yytUW ------END CERTIFICATE----- diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.key b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.key deleted file mode 100644 index f8227f4c0c2d4..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/server.key +++ /dev/null @@ -1,28 +0,0 @@ ------BEGIN PRIVATE KEY----- -MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDA5gjs5nYVf9iN -GAtmgNCVs9zlRldT+PR7XDCIk0+08RrH1jlSjNrQ+e0iTORzZJ+9D4gmuFejfzm0 -jRbmO66psecTtSuNS4+NRfo0d6+TFyz9+WaNqfnCdkxw+waEfvVYO5QQR+W9mKF/ -ZJ7bH7GBm0yFzlcaZWZG5kVgq+SBSEDb/Dz9Csr6M9Of1BEnFmNY2HZEF0LUHu7i -N99KY5JSWNgUfUjZ5N5j5F2LphQhhJT2AShnGy/dOJpKiZ8wXmO3Yyi6jozMD4iE -u+8WNytymHVDGCL1GR90Iwx34imb1hYQuTIbVsNGlDLSLIcPiC9WwCrPVjYp1FJ1 -zcq36dOrAgMBAAECggEACg60Xm2xsHNG/ixHw+NpfLSxCr89JGKxlJD88tIDcOK1 -S8AOoxA3BHhTddteeenALmJV7fbkkuC6SICmtgBcnfppmuxyRd6vsGT6o6ut2tR1 -gxRy1WYMYKg8WhOshlH8RspscODeyKDhorvDUJd5cNGBDuTwQ68PwxiUe3La6iac -EVQoKohg9EmRIhMF1i8I00zXE8p3XENrlTc491ipc+gLPIP5vtqHyQztEUkZHkWd -dXbs+n1hGCr+4FxrphGYEW80HINzmume7dGChr8nvF4ZZcuWW13DJuNim6pQno1i -hM8VdXm8XphLh0XEGI5OCfu/CetkBILZRXKltZk6AQKBgQDoBqJzRlp7regYNU4q -usfS+43tPNaJ0o4DIzcLawqpmK/B/cZStzHl14Sm62BVkKV6cnWAJPeLkENPMFoV -7Q7wLZBJxpPzqXkpeiDkKN4Wovca891Rffne5Sz6IDB5mOxMjfKIEPd5RkmB5Lkp -qQLwm3YJ2AJcLagG/Gi1DFDRAQKBgQDU1G9T43Mjke6TXG0u7gCSb+VwyDRsrvJA -u2vy6+MANRc1EEF31YLmTKOU5XxUmhtIu7TUbgPoNi0HuRFXx4Zul3BPlAosLMJv -kNQbA/9d0YQAfSgTsploN5CX65dLZ4ejIzVgDZREzpIBWTze6YZTA2DT5iOIet84 -DD5DujY4qwKBgG0PuUo/9oYOD3tZiv1wwD5+uY6auykbTF9TLStzzBY9y9d+hrsY -mx6zOAoRtz1g+TdeF7b9KVJzo//T9XQ68nuYnyreaWrt7SK+4jj8sK+pOEd1+0Cz -20CXLpX/jWmKpP+y9R5aA0kA7cpdjV90rwoTuN8Vpr5XQ5TNDhaTzGUBAoGABYig -fGXlkH8y3NICZL37ddNC+/O4qTrDQbudyusnM9ItkEuj6CG9DY/gkPaGjQyUuQdo -ZD2YDGmcMh81vDqL3ERDv03yFcP0KkJxwWIRObdA32JhsGFsa7FGKS0O+f7vH+bC -dITl3gQg97gCRSl9PJtR4TCSq/HF7Acld01YK5ECgYEAwLFB5JIuxrowJe74cCMP -n5Rwuc8vWdOsg+ytvQTv0/hVCdzcaLet6YvagnWTWaU7PUwTFxZs/mLQ9CAWVutK -IRzs/GWxGFjH5xotDaJdDDzSdQye4tUqvUVxv7zzzsVycCPBYFkyRQ8Tmr5FLtUJ -Cl48TZ6J8Rx5avjdtOw3QC8= ------END PRIVATE KEY----- diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/test-charmap.py b/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/test-charmap.py deleted file mode 100644 index d9fa6fb25e6c6..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/fixtures/test-charmap.py +++ /dev/null @@ -1,22 +0,0 @@ -import sys -import locale - -reload(sys) - -def main(): - encoding = locale.getdefaultlocale()[1] - if not encoding: - return False - - sys.setdefaultencoding(encoding) - textmap = { - 'cp936': u'\u4e2d\u6587', - 'cp1252': u'Lat\u012Bna', - 'cp932': u'\u306b\u307b\u3093\u3054' - } - if textmap.has_key(encoding): - print textmap[encoding] - return True - -if __name__ == '__main__': - print main() diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/process-exec-sync.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/process-exec-sync.js deleted file mode 100644 index 859cbc1f6fe2b..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/process-exec-sync.js +++ /dev/null @@ -1,138 +0,0 @@ -'use strict' - -var fs = require('graceful-fs') -var child_process = require('child_process') - -if (!String.prototype.startsWith) { - String.prototype.startsWith = function(search, pos) { - return this.substr(!pos || pos < 0 ? 0 : +pos, search.length) === search - } -} - -function processExecSync(file, args, options) { - var child, error, timeout, tmpdir, command, quote - command = makeCommand(file, args) - - /* - this function emulates child_process.execSync for legacy node <= 0.10.x - derived from https://github.com/gvarsanyi/sync-exec/blob/master/js/sync-exec.js - */ - - options = options || {} - // init timeout - timeout = Date.now() + options.timeout - // init tmpdir - var os_temp_base = '/tmp' - var os = determine_os() - os_temp_base = '/tmp' - - if (process.env.TMP) { - os_temp_base = process.env.TMP - } - - if (os_temp_base[os_temp_base.length - 1] !== '/') { - os_temp_base += '/' - } - - tmpdir = os_temp_base + 'processExecSync.' + Date.now() + Math.random() - fs.mkdirSync(tmpdir) - - // init command - if (os === 'linux') { - command = '(' + command + ' > ' + tmpdir + '/stdout 2> ' + tmpdir + - '/stderr); echo $? > ' + tmpdir + '/status' - } else { - command = '(' + command + ' > ' + tmpdir + '/stdout 2> ' + tmpdir + - '/stderr) | echo %errorlevel% > ' + tmpdir + '/status | exit' - } - - // init child - child = child_process.exec(command, options) - - var maxTry = 100000 // increases the test time by 6 seconds on win-2016-node-0.10 - var tryCount = 0 - while (tryCount < maxTry) { - try { - var x = fs.readFileSync(tmpdir + '/status') - if (x.toString() === '0') { - break - } - } catch (ignore) {} - tryCount++ - if (Date.now() > timeout) { - error = child - break - } - } - - ['stdout', 'stderr', 'status'].forEach(function (file) { - child[file] = fs.readFileSync(tmpdir + '/' + file, options.encoding) - setTimeout(unlinkFile, 500, tmpdir + '/' + file) - }) - - child.status = Number(child.status) - if (child.status !== 0) { - error = child - } - - try { - fs.rmdirSync(tmpdir) - } catch (ignore) {} - if (error) { - throw error - } - return child.stdout -} - -function makeCommand(file, args) { - var command, quote - command = file - if (args.length > 0) { - for(var i in args) { - command = command + ' ' - if (args[i][0] === '-') { - command = command + args[i] - } else { - if (!quote) { - command = command + '\"' - quote = true - } - command = command + args[i] - if (quote) { - if (args.length === (parseInt(i) + 1)) { - command = command + '\"' - } - } - } - } - } - return command -} - -function determine_os() { - var os = '' - var tmpVar = '' - if (process.env.OSTYPE) { - tmpVar = process.env.OSTYPE - } else if (process.env.OS) { - tmpVar = process.env.OS - } else { - //default is linux - tmpVar = 'linux' - } - - if (tmpVar.startsWith('linux')) { - os = 'linux' - } - if (tmpVar.startsWith('win')) { - os = 'win' - } - - return os -} - -function unlinkFile(file) { - fs.unlinkSync(file) -} - -module.exports = processExecSync diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/simple-proxy.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/simple-proxy.js deleted file mode 100644 index e55330c445bf6..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/simple-proxy.js +++ /dev/null @@ -1,24 +0,0 @@ -var http = require('http') - , https = require('https') - , server = http.createServer(handler) - , port = +process.argv[2] - , prefix = process.argv[3] - , upstream = process.argv[4] - , calls = 0 - -server.listen(port) - -function handler (req, res) { - if (req.url.indexOf(prefix) != 0) - throw new Error('request url [' + req.url + '] does not start with [' + prefix + ']') - - var upstreamUrl = upstream + req.url.substring(prefix.length) - console.log(req.url + ' -> ' + upstreamUrl) - https.get(upstreamUrl, function (ures) { - ures.on('end', function () { - if (++calls == 2) - server.close() - }) - ures.pipe(res) - }) -} diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-addon.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-addon.js deleted file mode 100644 index 89350effc46b4..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-addon.js +++ /dev/null @@ -1,113 +0,0 @@ -'use strict' - -var test = require('tape') -var path = require('path') -var fs = require('graceful-fs') -var child_process = require('child_process') -var addonPath = path.resolve(__dirname, 'node_modules', 'hello_world') -var nodeGyp = path.resolve(__dirname, '..', 'bin', 'node-gyp.js') -var execFileSync = child_process.execFileSync || require('./process-exec-sync') -var execFile = child_process.execFile - -function runHello() { - var testCode = "console.log(require('hello_world').hello())" - return execFileSync(process.execPath, ['-e', testCode], { cwd: __dirname }).toString() -} - -function getEncoding() { - var code = 'import locale;print locale.getdefaultlocale()[1]' - return execFileSync('python', ['-c', code]).toString().trim() -} - -function checkCharmapValid() { - var data - try { - data = execFileSync('python', ['fixtures/test-charmap.py'], - { cwd: __dirname }) - } catch (err) { - return false - } - var lines = data.toString().trim().split('\n') - return lines.pop() === 'True' -} - -test('build simple addon', function (t) { - t.plan(3) - - // Set the loglevel otherwise the output disappears when run via 'npm test' - var cmd = [nodeGyp, 'rebuild', '-C', addonPath, '--loglevel=verbose'] - var proc = execFile(process.execPath, cmd, function (err, stdout, stderr) { - var logLines = stderr.toString().trim().split(/\r?\n/) - var lastLine = logLines[logLines.length-1] - t.strictEqual(err, null) - t.strictEqual(lastLine, 'gyp info ok', 'should end in ok') - t.strictEqual(runHello().trim(), 'world') - }) - proc.stdout.setEncoding('utf-8') - proc.stderr.setEncoding('utf-8') -}) - -test('build simple addon in path with non-ascii characters', function (t) { - t.plan(1) - - if (!checkCharmapValid()) { - return t.skip('python console app can\'t encode non-ascii character.') - } - - var testDirNames = { - 'cp936': '文件夹', - 'cp1252': 'Latīna', - 'cp932': 'フォルダ' - } - // Select non-ascii characters by current encoding - var testDirName = testDirNames[getEncoding()] - // If encoding is UTF-8 or other then no need to test - if (!testDirName) { - return t.skip('no need to test') - } - - t.plan(3) - - var data, configPath = path.join(addonPath, 'build', 'config.gypi') - try { - data = fs.readFileSync(configPath, 'utf8') - } catch (err) { - t.error(err) - return - } - var config = JSON.parse(data.replace(/\#.+\n/, '')) - var nodeDir = config.variables.nodedir - var testNodeDir = path.join(addonPath, testDirName) - // Create symbol link to path with non-ascii characters - try { - fs.symlinkSync(nodeDir, testNodeDir, 'dir') - } catch (err) { - switch (err.code) { - case 'EEXIST': break - case 'EPERM': - t.error(err, 'Please try to running console as an administrator') - return - default: - t.error(err) - return - } - } - - var cmd = [nodeGyp, 'rebuild', '-C', addonPath, - '--loglevel=verbose', '-nodedir=' + testNodeDir] - var proc = execFile(process.execPath, cmd, function (err, stdout, stderr) { - try { - fs.unlink(testNodeDir) - } catch (err) { - t.error(err) - } - - var logLines = stderr.toString().trim().split(/\r?\n/) - var lastLine = logLines[logLines.length-1] - t.strictEqual(err, null) - t.strictEqual(lastLine, 'gyp info ok', 'should end in ok') - t.strictEqual(runHello().trim(), 'world') - }) - proc.stdout.setEncoding('utf-8') - proc.stderr.setEncoding('utf-8') -}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-configure-python.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-configure-python.js deleted file mode 100644 index f235bdbba1c9f..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-configure-python.js +++ /dev/null @@ -1,74 +0,0 @@ -'use strict' - -var test = require('tape') -var path = require('path') -var gyp = require('../lib/node-gyp') -var requireInject = require('require-inject') -var configure = requireInject('../lib/configure', { - 'graceful-fs': { - 'openSync': function (file, mode) { return 0; }, - 'closeSync': function (fd) { }, - 'writeFile': function (file, data, cb) { cb() }, - 'stat': function (file, cb) { cb(null, {}) } - } -}) - -var EXPECTED_PYPATH = path.join(__dirname, '..', 'gyp', 'pylib') -var SEPARATOR = process.platform == 'win32' ? ';' : ':' -var SPAWN_RESULT = { on: function () { } } - -test('configure PYTHONPATH with no existing env', function (t) { - t.plan(1) - - delete process.env.PYTHONPATH - - var prog = gyp() - prog.parseArgv([]) - prog.spawn = function () { - t.equal(process.env.PYTHONPATH, EXPECTED_PYPATH) - return SPAWN_RESULT - } - configure(prog, [], t.fail) -}) - -test('configure PYTHONPATH with existing env of one dir', function (t) { - t.plan(2) - - var existingPath = path.join('a', 'b') - process.env.PYTHONPATH = existingPath - - var prog = gyp() - prog.parseArgv([]) - prog.spawn = function () { - - t.equal(process.env.PYTHONPATH, [EXPECTED_PYPATH, existingPath].join(SEPARATOR)) - - var dirs = process.env.PYTHONPATH.split(SEPARATOR) - t.deepEqual(dirs, [EXPECTED_PYPATH, existingPath]) - - return SPAWN_RESULT - } - configure(prog, [], t.fail) -}) - -test('configure PYTHONPATH with existing env of multiple dirs', function (t) { - t.plan(2) - - var pythonDir1 = path.join('a', 'b') - var pythonDir2 = path.join('b', 'c') - var existingPath = [pythonDir1, pythonDir2].join(SEPARATOR) - process.env.PYTHONPATH = existingPath - - var prog = gyp() - prog.parseArgv([]) - prog.spawn = function () { - - t.equal(process.env.PYTHONPATH, [EXPECTED_PYPATH, existingPath].join(SEPARATOR)) - - var dirs = process.env.PYTHONPATH.split(SEPARATOR) - t.deepEqual(dirs, [EXPECTED_PYPATH, pythonDir1, pythonDir2]) - - return SPAWN_RESULT - } - configure(prog, [], t.fail) -}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-download.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-download.js deleted file mode 100644 index 6e6f64f058c2e..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-download.js +++ /dev/null @@ -1,102 +0,0 @@ -'use strict' - -var fs = require('fs') -var http = require('http') -var https = require('https') -var test = require('tape') -var install = require('../lib/install') - -test('download over http', function (t) { - t.plan(2) - - var server = http.createServer(function (req, res) { - t.strictEqual(req.headers['user-agent'], - 'node-gyp v42 (node ' + process.version + ')') - res.end('ok') - server.close() - }) - - var host = '127.0.0.1' - server.listen(0, host, function () { - var port = this.address().port - var gyp = { - opts: {}, - version: '42', - } - var url = 'http://' + host + ':' + port - var req = install.test.download(gyp, {}, url) - req.on('response', function (res) { - var body = '' - res.setEncoding('utf8') - res.on('data', function(data) { - body += data - }) - res.on('end', function() { - t.strictEqual(body, 'ok') - }) - }) - }) -}) - -test('download over https with custom ca', function (t) { - t.plan(3) - - var cert = fs.readFileSync(__dirname + '/fixtures/server.crt', 'utf8') - var key = fs.readFileSync(__dirname + '/fixtures/server.key', 'utf8') - - var cafile = __dirname + '/fixtures/ca.crt' - var ca = install.test.readCAFile(cafile) - t.strictEqual(ca.length, 1) - - var options = { ca: ca, cert: cert, key: key } - var server = https.createServer(options, function (req, res) { - t.strictEqual(req.headers['user-agent'], - 'node-gyp v42 (node ' + process.version + ')') - res.end('ok') - server.close() - }) - - server.on('clientError', function (err) { - throw err - }) - - var host = '127.0.0.1' - server.listen(8000, host, function () { - var port = this.address().port - var gyp = { - opts: { cafile: cafile }, - version: '42', - } - var url = 'https://' + host + ':' + port - var req = install.test.download(gyp, {}, url) - req.on('response', function (res) { - var body = '' - res.setEncoding('utf8') - res.on('data', function(data) { - body += data - }) - res.on('end', function() { - t.strictEqual(body, 'ok') - }) - }) - }) -}) - -test('download with missing cafile', function (t) { - t.plan(1) - var gyp = { - opts: { cafile: 'no.such.file' }, - } - try { - install.test.download(gyp, {}, 'http://bad/') - } catch (e) { - t.ok(/no.such.file/.test(e.message)) - } -}) - -test('check certificate splitting', function (t) { - var cas = install.test.readCAFile(__dirname + '/fixtures/ca-bundle.crt') - t.plan(2) - t.strictEqual(cas.length, 2) - t.notStrictEqual(cas[0], cas[1]) -}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-accessible-sync.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-accessible-sync.js deleted file mode 100644 index d336243dd0d7b..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-accessible-sync.js +++ /dev/null @@ -1,86 +0,0 @@ -'use strict' - -var test = require('tape') -var path = require('path') -var requireInject = require('require-inject') -var configure = requireInject('../lib/configure', { - 'graceful-fs': { - 'closeSync': function (fd) { return undefined }, - 'openSync': function (path) { - if (readableFiles.some(function (f) { return f === path} )) { - return 0 - } else { - var error = new Error('ENOENT - not found') - throw error - } - } - } -}) - -var dir = path.sep + 'testdir' -var readableFile = 'readable_file' -var anotherReadableFile = 'another_readable_file' -var readableFileInDir = 'somedir' + path.sep + readableFile -var readableFiles = [ - path.resolve(dir, readableFile), - path.resolve(dir, anotherReadableFile), - path.resolve(dir, readableFileInDir) -] - -test('find accessible - empty array', function (t) { - t.plan(1) - - var candidates = [] - var found = configure.test.findAccessibleSync('test', dir, candidates) - t.strictEqual(found, undefined) -}) - -test('find accessible - single item array, readable', function (t) { - t.plan(1) - - var candidates = [ readableFile ] - var found = configure.test.findAccessibleSync('test', dir, candidates) - t.strictEqual(found, path.resolve(dir, readableFile)) -}) - -test('find accessible - single item array, readable in subdir', function (t) { - t.plan(1) - - var candidates = [ readableFileInDir ] - var found = configure.test.findAccessibleSync('test', dir, candidates) - t.strictEqual(found, path.resolve(dir, readableFileInDir)) -}) - -test('find accessible - single item array, unreadable', function (t) { - t.plan(1) - - var candidates = [ 'unreadable_file' ] - var found = configure.test.findAccessibleSync('test', dir, candidates) - t.strictEqual(found, undefined) -}) - - -test('find accessible - multi item array, no matches', function (t) { - t.plan(1) - - var candidates = [ 'non_existent_file', 'unreadable_file' ] - var found = configure.test.findAccessibleSync('test', dir, candidates) - t.strictEqual(found, undefined) -}) - - -test('find accessible - multi item array, single match', function (t) { - t.plan(1) - - var candidates = [ 'non_existent_file', readableFile ] - var found = configure.test.findAccessibleSync('test', dir, candidates) - t.strictEqual(found, path.resolve(dir, readableFile)) -}) - -test('find accessible - multi item array, return first match', function (t) { - t.plan(1) - - var candidates = [ 'non_existent_file', anotherReadableFile, readableFile ] - var found = configure.test.findAccessibleSync('test', dir, candidates) - t.strictEqual(found, path.resolve(dir, anotherReadableFile)) -}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-node-directory.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-node-directory.js deleted file mode 100644 index 46659d0cfe8fa..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-node-directory.js +++ /dev/null @@ -1,115 +0,0 @@ -var test = require('tape') -var path = require('path') -var findNodeDirectory = require('../lib/find-node-directory') - -var platforms = ['darwin', 'freebsd', 'linux', 'sunos', 'win32', 'aix'] - -// we should find the directory based on the directory -// the script is running in and it should match the layout -// in a build tree where npm is installed in -// .... /deps/npm -test('test find-node-directory - node install', function (t) { - t.plan(platforms.length) - for (var next = 0; next < platforms.length; next++) { - var processObj = {execPath: '/x/y/bin/node', platform: platforms[next]} - t.equal( - findNodeDirectory('/x/deps/npm/node_modules/node-gyp/lib', processObj), - path.join('/x')) - } -}) - -// we should find the directory based on the directory -// the script is running in and it should match the layout -// in an installed tree where npm is installed in -// .... /lib/node_modules/npm or .../node_modules/npm -// depending on the patform -test('test find-node-directory - node build', function (t) { - t.plan(platforms.length) - for (var next = 0; next < platforms.length; next++) { - var processObj = {execPath: '/x/y/bin/node', platform: platforms[next]} - if (platforms[next] === 'win32') { - t.equal( - findNodeDirectory('/y/node_modules/npm/node_modules/node-gyp/lib', - processObj), path.join('/y')) - } else { - t.equal( - findNodeDirectory('/y/lib/node_modules/npm/node_modules/node-gyp/lib', - processObj), path.join('/y')) - } - } -}) - -// we should find the directory based on the execPath -// for node and match because it was in the bin directory -test('test find-node-directory - node in bin directory', function (t) { - t.plan(platforms.length) - for (var next = 0; next < platforms.length; next++) { - var processObj = {execPath: '/x/y/bin/node', platform: platforms[next]} - t.equal( - findNodeDirectory('/nothere/npm/node_modules/node-gyp/lib', processObj), - path.join('/x/y')) - } -}) - -// we should find the directory based on the execPath -// for node and match because it was in the Release directory -test('test find-node-directory - node in build release dir', function (t) { - t.plan(platforms.length) - for (var next = 0; next < platforms.length; next++) { - var processObj - if (platforms[next] === 'win32') { - processObj = {execPath: '/x/y/Release/node', platform: platforms[next]} - } else { - processObj = {execPath: '/x/y/out/Release/node', - platform: platforms[next]} - } - - t.equal( - findNodeDirectory('/nothere/npm/node_modules/node-gyp/lib', processObj), - path.join('/x/y')) - } -}) - -// we should find the directory based on the execPath -// for node and match because it was in the Debug directory -test('test find-node-directory - node in Debug release dir', function (t) { - t.plan(platforms.length) - for (var next = 0; next < platforms.length; next++) { - var processObj - if (platforms[next] === 'win32') { - processObj = {execPath: '/a/b/Debug/node', platform: platforms[next]} - } else { - processObj = {execPath: '/a/b/out/Debug/node', platform: platforms[next]} - } - - t.equal( - findNodeDirectory('/nothere/npm/node_modules/node-gyp/lib', processObj), - path.join('/a/b')) - } -}) - -// we should not find it as it will not match based on the execPath nor -// the directory from which the script is running -test('test find-node-directory - not found', function (t) { - t.plan(platforms.length) - for (var next = 0; next < platforms.length; next++) { - var processObj = {execPath: '/x/y/z/y', platform:next} - t.equal(findNodeDirectory('/a/b/c/d', processObj), '') - } -}) - -// we should find the directory based on the directory -// the script is running in and it should match the layout -// in a build tree where npm is installed in -// .... /deps/npm -// same test as above but make sure additional directory entries -// don't cause an issue -test('test find-node-directory - node install', function (t) { - t.plan(platforms.length) - for (var next = 0; next < platforms.length; next++) { - var processObj = {execPath: '/x/y/bin/node', platform: platforms[next]} - t.equal( - findNodeDirectory('/x/y/z/a/b/c/deps/npm/node_modules/node-gyp/lib', - processObj), path.join('/x/y/z/a/b/c')) - } -}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-python.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-python.js deleted file mode 100644 index 570eb180de7c7..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-find-python.js +++ /dev/null @@ -1,339 +0,0 @@ -'use strict' - -var test = require('tape') -var path = require('path') -var configure = require('../lib/configure') -var execFile = require('child_process').execFile -var PythonFinder = configure.test.PythonFinder - -test('find python', function (t) { - t.plan(4) - - configure.test.findPython('python', function (err, found) { - t.strictEqual(err, null) - var proc = execFile(found, ['-V'], function (err, stdout, stderr) { - t.strictEqual(err, null) - t.strictEqual(stdout, '') - t.ok(/Python 2/.test(stderr)) - }) - proc.stdout.setEncoding('utf-8') - proc.stderr.setEncoding('utf-8') - }) -}) - -function poison(object, property) { - function fail() { - throw new Error('Property ' + property + ' should not have been accessed.') - } - var descriptor = { - configurable: true, - enumerable: false, - writable: true, - getter: fail, - setter: fail, - } - Object.defineProperty(object, property, descriptor) -} - -// Work around a v0.10.x CI issue where path.resolve() on UNIX systems prefixes -// Windows paths with the current working directory. v0.12 and up are free of -// this issue because they use path.win32.resolve() which does the right thing. -var resolve = path.win32 && path.win32.resolve || function() { - function rstrip(s) { return s.replace(/\\+$/, '') } - return [].slice.call(arguments).map(rstrip).join('\\') -} - -function TestPythonFinder() { PythonFinder.apply(this, arguments) } -TestPythonFinder.prototype = Object.create(PythonFinder.prototype) -poison(TestPythonFinder.prototype, 'env') -poison(TestPythonFinder.prototype, 'execFile') -poison(TestPythonFinder.prototype, 'resolve') -poison(TestPythonFinder.prototype, 'stat') -poison(TestPythonFinder.prototype, 'which') -poison(TestPythonFinder.prototype, 'win') - -test('find python - python', function (t) { - t.plan(5) - - var f = new TestPythonFinder('python', done) - f.which = function(program, cb) { - t.strictEqual(program, 'python') - cb(null, program) - } - f.execFile = function(program, args, opts, cb) { - t.strictEqual(program, 'python') - t.ok(/import sys/.test(args[1])) - cb(null, '2.7.0') - } - f.checkPython() - - function done(err, python) { - t.strictEqual(err, null) - t.strictEqual(python, 'python') - } -}) - -test('find python - python too old', function (t) { - t.plan(4) - - var f = new TestPythonFinder('python', done) - f.which = function(program, cb) { - t.strictEqual(program, 'python') - cb(null, program) - } - f.execFile = function(program, args, opts, cb) { - t.strictEqual(program, 'python') - t.ok(/import sys/.test(args[1])) - cb(null, '2.3.4') - } - f.checkPython() - - function done(err, python) { - t.ok(/is not supported by gyp/.test(err)) - } -}) - -test('find python - python too new', function (t) { - t.plan(4) - - var f = new TestPythonFinder('python', done) - f.which = function(program, cb) { - t.strictEqual(program, 'python') - cb(null, program) - } - f.execFile = function(program, args, opts, cb) { - t.strictEqual(program, 'python') - t.ok(/import sys/.test(args[1])) - cb(null, '3.0.0') - } - f.checkPython() - - function done(err, python) { - t.ok(/is not supported by gyp/.test(err)) - } -}) - -test('find python - no python', function (t) { - t.plan(2) - - var f = new TestPythonFinder('python', done) - f.which = function(program, cb) { - t.strictEqual(program, 'python') - cb(new Error('not found')) - } - f.checkPython() - - function done(err, python) { - t.ok(/Can't find Python executable/.test(err)) - } -}) - -test('find python - no python2', function (t) { - t.plan(6) - - var f = new TestPythonFinder('python2', done) - f.which = function(program, cb) { - f.which = function(program, cb) { - t.strictEqual(program, 'python') - cb(null, program) - } - t.strictEqual(program, 'python2') - cb(new Error('not found')) - } - f.execFile = function(program, args, opts, cb) { - t.strictEqual(program, 'python') - t.ok(/import sys/.test(args[1])) - cb(null, '2.7.0') - } - f.checkPython() - - function done(err, python) { - t.strictEqual(err, null) - t.strictEqual(python, 'python') - } -}) - -test('find python - no python2, no python, unix', function (t) { - t.plan(3) - - var f = new TestPythonFinder('python2', done) - poison(f, 'checkPythonLauncher') - f.win = false - - f.which = function(program, cb) { - f.which = function(program, cb) { - t.strictEqual(program, 'python') - cb(new Error('not found')) - } - t.strictEqual(program, 'python2') - cb(new Error('not found')) - } - f.checkPython() - - function done(err, python) { - t.ok(/Can't find Python executable/.test(err)) - } -}) - -test('find python - no python, use python launcher', function (t) { - t.plan(8) - - var f = new TestPythonFinder('python', done) - f.env = {} - f.win = true - - f.which = function(program, cb) { - t.strictEqual(program, 'python') - cb(new Error('not found')) - } - f.execFile = function(program, args, opts, cb) { - f.execFile = function(program, args, opts, cb) { - t.strictEqual(program, 'Z:\\snake.exe') - t.ok(/import sys/.test(args[1])) - cb(null, '2.7.0') - } - t.strictEqual(program, 'py.exe') - t.notEqual(args.indexOf('-2'), -1) - t.notEqual(args.indexOf('-c'), -1) - cb(null, 'Z:\\snake.exe') - } - f.checkPython() - - function done(err, python) { - t.strictEqual(err, null) - t.strictEqual(python, 'Z:\\snake.exe') - } -}) - -test('find python - python 3, use python launcher', function (t) { - t.plan(10) - - var f = new TestPythonFinder('python', done) - f.env = {} - f.win = true - - f.which = function(program, cb) { - t.strictEqual(program, 'python') - cb(null, program) - } - f.execFile = function(program, args, opts, cb) { - f.execFile = function(program, args, opts, cb) { - f.execFile = function(program, args, opts, cb) { - t.strictEqual(program, 'Z:\\snake.exe') - t.ok(/import sys/.test(args[1])) - cb(null, '2.7.0') - } - t.strictEqual(program, 'py.exe') - t.notEqual(args.indexOf('-2'), -1) - t.notEqual(args.indexOf('-c'), -1) - cb(null, 'Z:\\snake.exe') - } - t.strictEqual(program, 'python') - t.ok(/import sys/.test(args[1])) - cb(null, '3.0.0') - } - f.checkPython() - - function done(err, python) { - t.strictEqual(err, null) - t.strictEqual(python, 'Z:\\snake.exe') - } -}) - -test('find python - python 3, use python launcher, python 2 too old', - function (t) { - t.plan(9) - - var f = new TestPythonFinder('python', done) - f.checkedPythonLauncher = false - f.env = {} - f.win = true - - f.which = function(program, cb) { - t.strictEqual(program, 'python') - cb(null, program) - } - f.execFile = function(program, args, opts, cb) { - f.execFile = function(program, args, opts, cb) { - f.execFile = function(program, args, opts, cb) { - t.strictEqual(program, 'Z:\\snake.exe') - t.ok(/import sys/.test(args[1])) - cb(null, '2.3.4') - } - t.strictEqual(program, 'py.exe') - t.notEqual(args.indexOf('-2'), -1) - t.notEqual(args.indexOf('-c'), -1) - cb(null, 'Z:\\snake.exe') - } - t.strictEqual(program, 'python') - t.ok(/import sys/.test(args[1])) - cb(null, '3.0.0') - } - f.checkPython() - - function done(err, python) { - t.ok(/is not supported by gyp/.test(err)) - } -}) - -test('find python - no python, no python launcher, good guess', function (t) { - t.plan(6) - - var re = /C:[\\\/]Python27[\\\/]python[.]exe/ - var f = new TestPythonFinder('python', done) - f.env = {} - f.win = true - - f.which = function(program, cb) { - t.strictEqual(program, 'python') - cb(new Error('not found')) - } - f.execFile = function(program, args, opts, cb) { - f.execFile = function(program, args, opts, cb) { - t.ok(re.test(program)) - t.ok(/import sys/.test(args[1])) - cb(null, '2.7.0') - } - t.strictEqual(program, 'py.exe') - cb(new Error('not found')) - } - f.resolve = resolve - f.stat = function(path, cb) { - t.ok(re.test(path)) - cb(null, {}) - } - f.checkPython() - - function done(err, python) { - t.ok(re.test(python)) - } -}) - -test('find python - no python, no python launcher, bad guess', function (t) { - t.plan(4) - - var f = new TestPythonFinder('python', done) - f.env = { SystemDrive: 'Z:\\' } - f.win = true - - f.which = function(program, cb) { - t.strictEqual(program, 'python') - cb(new Error('not found')) - } - f.execFile = function(program, args, opts, cb) { - t.strictEqual(program, 'py.exe') - cb(new Error('not found')) - } - f.resolve = resolve - f.stat = function(path, cb) { - t.ok(/Z:[\\\/]Python27[\\\/]python.exe/.test(path)) - var err = new Error('not found') - err.code = 'ENOENT' - cb(err) - } - f.checkPython() - - function done(err, python) { - t.ok(/Can't find Python executable/.test(err)) - } -}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-install.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-install.js deleted file mode 100644 index f647326a7fc66..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-install.js +++ /dev/null @@ -1,37 +0,0 @@ -'use strict' - -var test = require('tape') -var install = require('../lib/install').test.install - -test('EACCES retry once', function (t) { - t.plan(3) - - var fs = {} - fs.stat = function (path, cb) { - var err = new Error() - err.code = 'EACCES' - cb(err) - t.ok(true); - } - - - var gyp = {} - gyp.devDir = __dirname - gyp.opts = {} - gyp.opts.ensure = true - gyp.commands = {} - gyp.commands.install = function (argv, cb) { - install(fs, gyp, argv, cb) - } - gyp.commands.remove = function (argv, cb) { - cb() - } - - gyp.commands.install([], function (err) { - t.ok(true) - if (/"pre" versions of node cannot be installed/.test(err.message)) { - t.ok(true) - t.ok(true) - } - }) -}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-options.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-options.js deleted file mode 100644 index d097f81be62c8..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-options.js +++ /dev/null @@ -1,25 +0,0 @@ -'use strict'; - -var test = require('tape') -var gyp = require('../lib/node-gyp') - -test('options in environment', function (t) { - t.plan(1) - - // `npm test` dumps a ton of npm_config_* variables in the environment. - Object.keys(process.env) - .filter(function(key) { return /^npm_config_/.test(key) }) - .forEach(function(key) { delete process.env[key] }) - - // Zero-length keys should get filtered out. - process.env.npm_config_ = '42' - // Other keys should get added. - process.env.npm_config_x = '42' - // Except loglevel. - process.env.npm_config_loglevel = 'debug' - - var g = gyp(); - g.parseArgv(['rebuild']) // Also sets opts.argv. - - t.deepEqual(Object.keys(g.opts).sort(), ['argv', 'x']) -}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-process-release.js b/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-process-release.js deleted file mode 100644 index 48411ae0a7d5a..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/test/test-process-release.js +++ /dev/null @@ -1,637 +0,0 @@ -var test = require('tape') -var processRelease = require('../lib/process-release') - -test('test process release - process.version = 0.8.20', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v0.8.20', null) - - t.equal(release.semver.version, '0.8.20') - delete release.semver - - t.deepEqual(release, { - version: '0.8.20', - name: 'node', - baseUrl: 'https://nodejs.org/dist/v0.8.20/', - tarballUrl: 'https://nodejs.org/dist/v0.8.20/node-v0.8.20.tar.gz', - shasumsUrl: 'https://nodejs.org/dist/v0.8.20/SHASUMS256.txt', - versionDir: '0.8.20', - libUrl32: 'https://nodejs.org/dist/v0.8.20/node.lib', - libUrl64: 'https://nodejs.org/dist/v0.8.20/x64/node.lib', - libPath32: 'node.lib', - libPath64: 'x64/node.lib' - }) -}) - -test('test process release - process.version = 0.10.21', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v0.10.21', null) - - t.equal(release.semver.version, '0.10.21') - delete release.semver - - t.deepEqual(release, { - version: '0.10.21', - name: 'node', - baseUrl: 'https://nodejs.org/dist/v0.10.21/', - tarballUrl: 'https://nodejs.org/dist/v0.10.21/node-v0.10.21.tar.gz', - shasumsUrl: 'https://nodejs.org/dist/v0.10.21/SHASUMS256.txt', - versionDir: '0.10.21', - libUrl32: 'https://nodejs.org/dist/v0.10.21/node.lib', - libUrl64: 'https://nodejs.org/dist/v0.10.21/x64/node.lib', - libPath32: 'node.lib', - libPath64: 'x64/node.lib' - }) -}) - -// prior to -headers.tar.gz -test('test process release - process.version = 0.12.9', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v0.12.9', null) - - t.equal(release.semver.version, '0.12.9') - delete release.semver - - t.deepEqual(release, { - version: '0.12.9', - name: 'node', - baseUrl: 'https://nodejs.org/dist/v0.12.9/', - tarballUrl: 'https://nodejs.org/dist/v0.12.9/node-v0.12.9.tar.gz', - shasumsUrl: 'https://nodejs.org/dist/v0.12.9/SHASUMS256.txt', - versionDir: '0.12.9', - libUrl32: 'https://nodejs.org/dist/v0.12.9/node.lib', - libUrl64: 'https://nodejs.org/dist/v0.12.9/x64/node.lib', - libPath32: 'node.lib', - libPath64: 'x64/node.lib' - }) -}) - -// prior to -headers.tar.gz -test('test process release - process.version = 0.10.41', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v0.10.41', null) - - t.equal(release.semver.version, '0.10.41') - delete release.semver - - t.deepEqual(release, { - version: '0.10.41', - name: 'node', - baseUrl: 'https://nodejs.org/dist/v0.10.41/', - tarballUrl: 'https://nodejs.org/dist/v0.10.41/node-v0.10.41.tar.gz', - shasumsUrl: 'https://nodejs.org/dist/v0.10.41/SHASUMS256.txt', - versionDir: '0.10.41', - libUrl32: 'https://nodejs.org/dist/v0.10.41/node.lib', - libUrl64: 'https://nodejs.org/dist/v0.10.41/x64/node.lib', - libPath32: 'node.lib', - libPath64: 'x64/node.lib' - }) -}) - -// has -headers.tar.gz -test('test process release - process.release ~ node@0.10.42', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v0.10.42', null) - - t.equal(release.semver.version, '0.10.42') - delete release.semver - - t.deepEqual(release, { - version: '0.10.42', - name: 'node', - baseUrl: 'https://nodejs.org/dist/v0.10.42/', - tarballUrl: 'https://nodejs.org/dist/v0.10.42/node-v0.10.42-headers.tar.gz', - shasumsUrl: 'https://nodejs.org/dist/v0.10.42/SHASUMS256.txt', - versionDir: '0.10.42', - libUrl32: 'https://nodejs.org/dist/v0.10.42/node.lib', - libUrl64: 'https://nodejs.org/dist/v0.10.42/x64/node.lib', - libPath32: 'node.lib', - libPath64: 'x64/node.lib' - }) -}) - -// has -headers.tar.gz -test('test process release - process.release ~ node@0.12.10', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v0.12.10', null) - - t.equal(release.semver.version, '0.12.10') - delete release.semver - - t.deepEqual(release, { - version: '0.12.10', - name: 'node', - baseUrl: 'https://nodejs.org/dist/v0.12.10/', - tarballUrl: 'https://nodejs.org/dist/v0.12.10/node-v0.12.10-headers.tar.gz', - shasumsUrl: 'https://nodejs.org/dist/v0.12.10/SHASUMS256.txt', - versionDir: '0.12.10', - libUrl32: 'https://nodejs.org/dist/v0.12.10/node.lib', - libUrl64: 'https://nodejs.org/dist/v0.12.10/x64/node.lib', - libPath32: 'node.lib', - libPath64: 'x64/node.lib' - }) -}) - -test('test process release - process.release ~ node@4.1.23', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v4.1.23', { - name: 'node', - headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz' - }) - - t.equal(release.semver.version, '4.1.23') - delete release.semver - - t.deepEqual(release, { - version: '4.1.23', - name: 'node', - baseUrl: 'https://nodejs.org/dist/v4.1.23/', - tarballUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz', - shasumsUrl: 'https://nodejs.org/dist/v4.1.23/SHASUMS256.txt', - versionDir: '4.1.23', - libUrl32: 'https://nodejs.org/dist/v4.1.23/win-x86/node.lib', - libUrl64: 'https://nodejs.org/dist/v4.1.23/win-x64/node.lib', - libPath32: 'win-x86/node.lib', - libPath64: 'win-x64/node.lib' - }) -}) - -test('test process release - process.release ~ node@4.1.23 / corp build', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v4.1.23', { - name: 'node', - headersUrl: 'https://some.custom.location/node-v4.1.23-headers.tar.gz' - }) - - t.equal(release.semver.version, '4.1.23') - delete release.semver - - t.deepEqual(release, { - version: '4.1.23', - name: 'node', - baseUrl: 'https://some.custom.location/', - tarballUrl: 'https://some.custom.location/node-v4.1.23-headers.tar.gz', - shasumsUrl: 'https://some.custom.location/SHASUMS256.txt', - versionDir: '4.1.23', - libUrl32: 'https://some.custom.location/win-x86/node.lib', - libUrl64: 'https://some.custom.location/win-x64/node.lib', - libPath32: 'win-x86/node.lib', - libPath64: 'win-x64/node.lib' - }) -}) - -test('test process release - process.version = 1.8.4', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v1.8.4', null) - - t.equal(release.semver.version, '1.8.4') - delete release.semver - - t.deepEqual(release, { - version: '1.8.4', - name: 'iojs', - baseUrl: 'https://iojs.org/download/release/v1.8.4/', - tarballUrl: 'https://iojs.org/download/release/v1.8.4/iojs-v1.8.4.tar.gz', - shasumsUrl: 'https://iojs.org/download/release/v1.8.4/SHASUMS256.txt', - versionDir: 'iojs-1.8.4', - libUrl32: 'https://iojs.org/download/release/v1.8.4/win-x86/iojs.lib', - libUrl64: 'https://iojs.org/download/release/v1.8.4/win-x64/iojs.lib', - libPath32: 'win-x86/iojs.lib', - libPath64: 'win-x64/iojs.lib' - }) -}) - -test('test process release - process.release ~ iojs@3.2.24', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v3.2.24', { - name: 'io.js', - headersUrl: 'https://iojs.org/download/release/v3.2.24/iojs-v3.2.24-headers.tar.gz' - }) - - t.equal(release.semver.version, '3.2.24') - delete release.semver - - t.deepEqual(release, { - version: '3.2.24', - name: 'iojs', - baseUrl: 'https://iojs.org/download/release/v3.2.24/', - tarballUrl: 'https://iojs.org/download/release/v3.2.24/iojs-v3.2.24-headers.tar.gz', - shasumsUrl: 'https://iojs.org/download/release/v3.2.24/SHASUMS256.txt', - versionDir: 'iojs-3.2.24', - libUrl32: 'https://iojs.org/download/release/v3.2.24/win-x86/iojs.lib', - libUrl64: 'https://iojs.org/download/release/v3.2.24/win-x64/iojs.lib', - libPath32: 'win-x86/iojs.lib', - libPath64: 'win-x64/iojs.lib' - }) -}) - -test('test process release - process.release ~ iojs@3.2.11 +libUrl32', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v3.2.11', { - name: 'io.js', - headersUrl: 'https://iojs.org/download/release/v3.2.11/iojs-v3.2.11-headers.tar.gz', - libUrl: 'https://iojs.org/download/release/v3.2.11/win-x86/iojs.lib' // custom - }) - - t.equal(release.semver.version, '3.2.11') - delete release.semver - - t.deepEqual(release, { - version: '3.2.11', - name: 'iojs', - baseUrl: 'https://iojs.org/download/release/v3.2.11/', - tarballUrl: 'https://iojs.org/download/release/v3.2.11/iojs-v3.2.11-headers.tar.gz', - shasumsUrl: 'https://iojs.org/download/release/v3.2.11/SHASUMS256.txt', - versionDir: 'iojs-3.2.11', - libUrl32: 'https://iojs.org/download/release/v3.2.11/win-x86/iojs.lib', - libUrl64: 'https://iojs.org/download/release/v3.2.11/win-x64/iojs.lib', - libPath32: 'win-x86/iojs.lib', - libPath64: 'win-x64/iojs.lib' - }) -}) - -test('test process release - process.release ~ iojs@3.2.101 +libUrl64', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v3.2.101', { - name: 'io.js', - headersUrl: 'https://iojs.org/download/release/v3.2.101/iojs-v3.2.101-headers.tar.gz', - libUrl: 'https://iojs.org/download/release/v3.2.101/win-x64/iojs.lib' // custom - }) - - t.equal(release.semver.version, '3.2.101') - delete release.semver - - t.deepEqual(release, { - version: '3.2.101', - name: 'iojs', - baseUrl: 'https://iojs.org/download/release/v3.2.101/', - tarballUrl: 'https://iojs.org/download/release/v3.2.101/iojs-v3.2.101-headers.tar.gz', - shasumsUrl: 'https://iojs.org/download/release/v3.2.101/SHASUMS256.txt', - versionDir: 'iojs-3.2.101', - libUrl32: 'https://iojs.org/download/release/v3.2.101/win-x86/iojs.lib', - libUrl64: 'https://iojs.org/download/release/v3.2.101/win-x64/iojs.lib', - libPath32: 'win-x86/iojs.lib', - libPath64: 'win-x64/iojs.lib' - }) -}) - -test('test process release - process.release ~ iojs@3.3.0 - borked win-ia32', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v3.2.101', { - name: 'io.js', - headersUrl: 'https://iojs.org/download/release/v3.2.101/iojs-v3.2.101-headers.tar.gz', - libUrl: 'https://iojs.org/download/release/v3.2.101/win-ia32/iojs.lib' // custom - }) - - t.equal(release.semver.version, '3.2.101') - delete release.semver - - t.deepEqual(release, { - version: '3.2.101', - name: 'iojs', - baseUrl: 'https://iojs.org/download/release/v3.2.101/', - tarballUrl: 'https://iojs.org/download/release/v3.2.101/iojs-v3.2.101-headers.tar.gz', - shasumsUrl: 'https://iojs.org/download/release/v3.2.101/SHASUMS256.txt', - versionDir: 'iojs-3.2.101', - libUrl32: 'https://iojs.org/download/release/v3.2.101/win-x86/iojs.lib', - libUrl64: 'https://iojs.org/download/release/v3.2.101/win-x64/iojs.lib', - libPath32: 'win-x86/iojs.lib', - libPath64: 'win-x64/iojs.lib' - }) -}) - -test('test process release - process.release ~ node@4.1.23 --target=0.10.40', function (t) { - t.plan(2) - - var release = processRelease([], { opts: { target: '0.10.40' } }, 'v4.1.23', { - name: 'node', - headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz' - }) - - t.equal(release.semver.version, '0.10.40') - delete release.semver - - t.deepEqual(release, { - version: '0.10.40', - name: 'node', - baseUrl: 'https://nodejs.org/dist/v0.10.40/', - tarballUrl: 'https://nodejs.org/dist/v0.10.40/node-v0.10.40.tar.gz', - shasumsUrl: 'https://nodejs.org/dist/v0.10.40/SHASUMS256.txt', - versionDir: '0.10.40', - libUrl32: 'https://nodejs.org/dist/v0.10.40/node.lib', - libUrl64: 'https://nodejs.org/dist/v0.10.40/x64/node.lib', - libPath32: 'node.lib', - libPath64: 'x64/node.lib' - }) -}) - -test('test process release - process.release ~ node@4.1.23 --target=1.8.4', function (t) { - t.plan(2) - - var release = processRelease([], { opts: { target: '1.8.4' } }, 'v4.1.23', { - name: 'node', - headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz' - }) - - t.equal(release.semver.version, '1.8.4') - delete release.semver - - t.deepEqual(release, { - version: '1.8.4', - name: 'iojs', - baseUrl: 'https://iojs.org/download/release/v1.8.4/', - tarballUrl: 'https://iojs.org/download/release/v1.8.4/iojs-v1.8.4.tar.gz', - shasumsUrl: 'https://iojs.org/download/release/v1.8.4/SHASUMS256.txt', - versionDir: 'iojs-1.8.4', - libUrl32: 'https://iojs.org/download/release/v1.8.4/win-x86/iojs.lib', - libUrl64: 'https://iojs.org/download/release/v1.8.4/win-x64/iojs.lib', - libPath32: 'win-x86/iojs.lib', - libPath64: 'win-x64/iojs.lib' - }) -}) - -test('test process release - process.release ~ node@4.1.23 --dist-url=https://foo.bar/baz', function (t) { - t.plan(2) - - var release = processRelease([], { opts: { 'dist-url': 'https://foo.bar/baz' } }, 'v4.1.23', { - name: 'node', - headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz' - }) - - t.equal(release.semver.version, '4.1.23') - delete release.semver - - t.deepEqual(release, { - version: '4.1.23', - name: 'node', - baseUrl: 'https://foo.bar/baz/v4.1.23/', - tarballUrl: 'https://foo.bar/baz/v4.1.23/node-v4.1.23-headers.tar.gz', - shasumsUrl: 'https://foo.bar/baz/v4.1.23/SHASUMS256.txt', - versionDir: '4.1.23', - libUrl32: 'https://foo.bar/baz/v4.1.23/win-x86/node.lib', - libUrl64: 'https://foo.bar/baz/v4.1.23/win-x64/node.lib', - libPath32: 'win-x86/node.lib', - libPath64: 'win-x64/node.lib' - }) -}) - -test('test process release - process.release ~ frankenstein@4.1.23', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v4.1.23', { - name: 'frankenstein', - headersUrl: 'https://frankensteinjs.org/dist/v4.1.23/frankenstein-v4.1.23-headers.tar.gz' - }) - - t.equal(release.semver.version, '4.1.23') - delete release.semver - - t.deepEqual(release, { - version: '4.1.23', - name: 'frankenstein', - baseUrl: 'https://frankensteinjs.org/dist/v4.1.23/', - tarballUrl: 'https://frankensteinjs.org/dist/v4.1.23/frankenstein-v4.1.23-headers.tar.gz', - shasumsUrl: 'https://frankensteinjs.org/dist/v4.1.23/SHASUMS256.txt', - versionDir: 'frankenstein-4.1.23', - libUrl32: 'https://frankensteinjs.org/dist/v4.1.23/win-x86/frankenstein.lib', - libUrl64: 'https://frankensteinjs.org/dist/v4.1.23/win-x64/frankenstein.lib', - libPath32: 'win-x86/frankenstein.lib', - libPath64: 'win-x64/frankenstein.lib' - }) -}) - - -test('test process release - process.release ~ frankenstein@4.1.23 --dist-url=http://foo.bar/baz/', function (t) { - t.plan(2) - - var release = processRelease([], { opts: { 'dist-url': 'http://foo.bar/baz/' } }, 'v4.1.23', { - name: 'frankenstein', - headersUrl: 'https://frankensteinjs.org/dist/v4.1.23/frankenstein-v4.1.23.tar.gz' - }) - - t.equal(release.semver.version, '4.1.23') - delete release.semver - - t.deepEqual(release, { - version: '4.1.23', - name: 'frankenstein', - baseUrl: 'http://foo.bar/baz/v4.1.23/', - tarballUrl: 'http://foo.bar/baz/v4.1.23/frankenstein-v4.1.23-headers.tar.gz', - shasumsUrl: 'http://foo.bar/baz/v4.1.23/SHASUMS256.txt', - versionDir: 'frankenstein-4.1.23', - libUrl32: 'http://foo.bar/baz/v4.1.23/win-x86/frankenstein.lib', - libUrl64: 'http://foo.bar/baz/v4.1.23/win-x64/frankenstein.lib', - libPath32: 'win-x86/frankenstein.lib', - libPath64: 'win-x64/frankenstein.lib' - }) -}) - -test('test process release - process.release ~ node@4.0.0-rc.4', function (t) { - t.plan(2) - - var release = processRelease([], { opts: {} }, 'v4.0.0-rc.4', { - name: 'node', - headersUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz' - }) - - t.equal(release.semver.version, '4.0.0-rc.4') - delete release.semver - - t.deepEqual(release, { - version: '4.0.0-rc.4', - name: 'node', - baseUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/', - tarballUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz', - shasumsUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/SHASUMS256.txt', - versionDir: '4.0.0-rc.4', - libUrl32: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x86/node.lib', - libUrl64: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x64/node.lib', - libPath32: 'win-x86/node.lib', - libPath64: 'win-x64/node.lib' - }) -}) - - -test('test process release - process.release ~ node@4.0.0-rc.4 passed as argv[0]', function (t) { - t.plan(2) - - // note the missing 'v' on the arg, it should normalise when checking - // whether we're on the default or not - var release = processRelease([ '4.0.0-rc.4' ], { opts: {} }, 'v4.0.0-rc.4', { - name: 'node', - headersUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz' - }) - - t.equal(release.semver.version, '4.0.0-rc.4') - delete release.semver - - t.deepEqual(release, { - version: '4.0.0-rc.4', - name: 'node', - baseUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/', - tarballUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz', - shasumsUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/SHASUMS256.txt', - versionDir: '4.0.0-rc.4', - libUrl32: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x86/node.lib', - libUrl64: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x64/node.lib', - libPath32: 'win-x86/node.lib', - libPath64: 'win-x64/node.lib' - }) -}) - - -test('test process release - process.release ~ node@4.0.0-rc.4 - bogus string passed as argv[0]', function (t) { - t.plan(2) - - // additional arguments can be passed in on the commandline that should be ignored if they - // are not specifying a valid version @ position 0 - var release = processRelease([ 'this is no version!' ], { opts: {} }, 'v4.0.0-rc.4', { - name: 'node', - headersUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz' - }) - - t.equal(release.semver.version, '4.0.0-rc.4') - delete release.semver - - t.deepEqual(release, { - version: '4.0.0-rc.4', - name: 'node', - baseUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/', - tarballUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/node-v4.0.0-rc.4-headers.tar.gz', - shasumsUrl: 'https://nodejs.org/download/rc/v4.0.0-rc.4/SHASUMS256.txt', - versionDir: '4.0.0-rc.4', - libUrl32: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x86/node.lib', - libUrl64: 'https://nodejs.org/download/rc/v4.0.0-rc.4/win-x64/node.lib', - libPath32: 'win-x86/node.lib', - libPath64: 'win-x64/node.lib' - }) -}) - -test('test process release - NODEJS_ORG_MIRROR', function (t) { - t.plan(2) - - process.env.NODEJS_ORG_MIRROR = 'http://foo.bar' - - var release = processRelease([], { opts: {} }, 'v4.1.23', { - name: 'node', - headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz' - }) - - t.equal(release.semver.version, '4.1.23') - delete release.semver - - t.deepEqual(release, { - version: '4.1.23', - name: 'node', - baseUrl: 'http://foo.bar/v4.1.23/', - tarballUrl: 'http://foo.bar/v4.1.23/node-v4.1.23-headers.tar.gz', - shasumsUrl: 'http://foo.bar/v4.1.23/SHASUMS256.txt', - versionDir: '4.1.23', - libUrl32: 'http://foo.bar/v4.1.23/win-x86/node.lib', - libUrl64: 'http://foo.bar/v4.1.23/win-x64/node.lib', - libPath32: 'win-x86/node.lib', - libPath64: 'win-x64/node.lib' - }) - - delete process.env.NODEJS_ORG_MIRROR -}) - -test('test process release - NVM_NODEJS_ORG_MIRROR', function (t) { - t.plan(2) - - process.env.NVM_NODEJS_ORG_MIRROR = 'http://foo.bar' - - var release = processRelease([], { opts: {} }, 'v4.1.23', { - name: 'node', - headersUrl: 'https://nodejs.org/dist/v4.1.23/node-v4.1.23-headers.tar.gz' - }) - - t.equal(release.semver.version, '4.1.23') - delete release.semver - - t.deepEqual(release, { - version: '4.1.23', - name: 'node', - baseUrl: 'http://foo.bar/v4.1.23/', - tarballUrl: 'http://foo.bar/v4.1.23/node-v4.1.23-headers.tar.gz', - shasumsUrl: 'http://foo.bar/v4.1.23/SHASUMS256.txt', - versionDir: '4.1.23', - libUrl32: 'http://foo.bar/v4.1.23/win-x86/node.lib', - libUrl64: 'http://foo.bar/v4.1.23/win-x64/node.lib', - libPath32: 'win-x86/node.lib', - libPath64: 'win-x64/node.lib' - }) - - delete process.env.NVM_NODEJS_ORG_MIRROR -}) - -test('test process release - IOJS_ORG_MIRROR', function (t) { - t.plan(2) - - process.env.IOJS_ORG_MIRROR = 'http://foo.bar' - - var release = processRelease([], { opts: {} }, 'v3.2.24', { - name: 'io.js', - headersUrl: 'https://iojs.org/download/release/v3.2.24/iojs-v3.2.24-headers.tar.gz' - }) - - t.equal(release.semver.version, '3.2.24') - delete release.semver - - t.deepEqual(release, { - version: '3.2.24', - name: 'iojs', - baseUrl: 'http://foo.bar/v3.2.24/', - tarballUrl: 'http://foo.bar/v3.2.24/iojs-v3.2.24-headers.tar.gz', - shasumsUrl: 'http://foo.bar/v3.2.24/SHASUMS256.txt', - versionDir: 'iojs-3.2.24', - libUrl32: 'http://foo.bar/v3.2.24/win-x86/iojs.lib', - libUrl64: 'http://foo.bar/v3.2.24/win-x64/iojs.lib', - libPath32: 'win-x86/iojs.lib', - libPath64: 'win-x64/iojs.lib' - }) - - delete process.env.IOJS_ORG_MIRROR -}) - - -test('test process release - NVM_IOJS_ORG_MIRROR', function (t) { - t.plan(2) - - process.env.NVM_IOJS_ORG_MIRROR = 'http://foo.bar' - - var release = processRelease([], { opts: {} }, 'v3.2.24', { - name: 'io.js', - headersUrl: 'https://iojs.org/download/release/v3.2.24/iojs-v3.2.24-headers.tar.gz' - }) - - t.equal(release.semver.version, '3.2.24') - delete release.semver - - t.deepEqual(release, { - version: '3.2.24', - name: 'iojs', - baseUrl: 'http://foo.bar/v3.2.24/', - tarballUrl: 'http://foo.bar/v3.2.24/iojs-v3.2.24-headers.tar.gz', - shasumsUrl: 'http://foo.bar/v3.2.24/SHASUMS256.txt', - versionDir: 'iojs-3.2.24', - libUrl32: 'http://foo.bar/v3.2.24/win-x86/iojs.lib', - libUrl64: 'http://foo.bar/v3.2.24/win-x64/iojs.lib', - libPath32: 'win-x86/iojs.lib', - libPath64: 'win-x64/iojs.lib' - }) - - delete process.env.NVM_IOJS_ORG_MIRROR -}) diff --git a/node_modules/npm-lifecycle/node_modules/node-gyp/tools/gyp/pylib/gyp/generator/compile_commands_json.py b/node_modules/npm-lifecycle/node_modules/node-gyp/tools/gyp/pylib/gyp/generator/compile_commands_json.py deleted file mode 100644 index 575db63c4e194..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/node-gyp/tools/gyp/pylib/gyp/generator/compile_commands_json.py +++ /dev/null @@ -1,115 +0,0 @@ -# Copyright (c) 2016 Ben Noordhuis . All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import gyp.common -import gyp.xcode_emulation -import json -import os - -generator_additional_non_configuration_keys = [] -generator_additional_path_sections = [] -generator_extra_sources_for_rules = [] -generator_filelist_paths = None -generator_supports_multiple_toolsets = True -generator_wants_sorted_dependencies = False - -# Lifted from make.py. The actual values don't matter much. -generator_default_variables = { - 'CONFIGURATION_NAME': '$(BUILDTYPE)', - 'EXECUTABLE_PREFIX': '', - 'EXECUTABLE_SUFFIX': '', - 'INTERMEDIATE_DIR': '$(obj).$(TOOLSET)/$(TARGET)/geni', - 'PRODUCT_DIR': '$(builddir)', - 'RULE_INPUT_DIRNAME': '%(INPUT_DIRNAME)s', - 'RULE_INPUT_EXT': '$(suffix $<)', - 'RULE_INPUT_NAME': '$(notdir $<)', - 'RULE_INPUT_PATH': '$(abspath $<)', - 'RULE_INPUT_ROOT': '%(INPUT_ROOT)s', - 'SHARED_INTERMEDIATE_DIR': '$(obj)/gen', - 'SHARED_LIB_PREFIX': 'lib', - 'STATIC_LIB_PREFIX': 'lib', - 'STATIC_LIB_SUFFIX': '.a', -} - - -def IsMac(params): - return 'mac' == gyp.common.GetFlavor(params) - - -def CalculateVariables(default_variables, params): - default_variables.setdefault('OS', gyp.common.GetFlavor(params)) - - -def AddCommandsForTarget(cwd, target, params, per_config_commands): - output_dir = params['generator_flags']['output_dir'] - for configuration_name, configuration in target['configurations'].iteritems(): - builddir_name = os.path.join(output_dir, configuration_name) - - if IsMac(params): - xcode_settings = gyp.xcode_emulation.XcodeSettings(target) - cflags = xcode_settings.GetCflags(configuration_name) - cflags_c = xcode_settings.GetCflagsC(configuration_name) - cflags_cc = xcode_settings.GetCflagsCC(configuration_name) - else: - cflags = configuration.get('cflags', []) - cflags_c = configuration.get('cflags_c', []) - cflags_cc = configuration.get('cflags_cc', []) - - cflags_c = cflags + cflags_c - cflags_cc = cflags + cflags_cc - - defines = configuration.get('defines', []) - defines = ['-D' + s for s in defines] - - # TODO(bnoordhuis) Handle generated source files. - sources = target.get('sources', []) - sources = [s for s in sources if s.endswith('.c') or s.endswith('.cc')] - - def resolve(filename): - return os.path.abspath(os.path.join(cwd, filename)) - - # TODO(bnoordhuis) Handle generated header files. - include_dirs = configuration.get('include_dirs', []) - include_dirs = [s for s in include_dirs if not s.startswith('$(obj)')] - includes = ['-I' + resolve(s) for s in include_dirs] - - defines = gyp.common.EncodePOSIXShellList(defines) - includes = gyp.common.EncodePOSIXShellList(includes) - cflags_c = gyp.common.EncodePOSIXShellList(cflags_c) - cflags_cc = gyp.common.EncodePOSIXShellList(cflags_cc) - - commands = per_config_commands.setdefault(configuration_name, []) - for source in sources: - file = resolve(source) - isc = source.endswith('.c') - cc = 'cc' if isc else 'c++' - cflags = cflags_c if isc else cflags_cc - command = ' '.join((cc, defines, includes, cflags, - '-c', gyp.common.EncodePOSIXShellArgument(file))) - commands.append(dict(command=command, directory=output_dir, file=file)) - - -def GenerateOutput(target_list, target_dicts, data, params): - per_config_commands = {} - for qualified_target, target in target_dicts.iteritems(): - build_file, target_name, toolset = ( - gyp.common.ParseQualifiedTarget(qualified_target)) - if IsMac(params): - settings = data[build_file] - gyp.xcode_emulation.MergeGlobalXcodeSettingsToSpec(settings, target) - cwd = os.path.dirname(build_file) - AddCommandsForTarget(cwd, target, params, per_config_commands) - - output_dir = params['generator_flags']['output_dir'] - for configuration_name, commands in per_config_commands.iteritems(): - filename = os.path.join(output_dir, - configuration_name, - 'compile_commands.json') - gyp.common.EnsureDirExists(filename) - fp = open(filename, 'w') - json.dump(commands, fp=fp, indent=0, check_circular=False) - - -def PerformBuild(data, configurations, params): - pass diff --git a/node_modules/npm-lifecycle/node_modules/nopt/.npmignore b/node_modules/npm-lifecycle/node_modules/nopt/.npmignore deleted file mode 100644 index 3c3629e647f5d..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/nopt/.npmignore +++ /dev/null @@ -1 +0,0 @@ -node_modules diff --git a/node_modules/npm-lifecycle/node_modules/nopt/.travis.yml b/node_modules/npm-lifecycle/node_modules/nopt/.travis.yml deleted file mode 100644 index 99f2bbf5068a8..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/nopt/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: node_js -language: node_js -node_js: - - '0.8' - - '0.10' - - '0.12' - - 'iojs' -before_install: - - npm install -g npm@latest diff --git a/node_modules/npm-lifecycle/node_modules/nopt/LICENSE b/node_modules/npm-lifecycle/node_modules/nopt/LICENSE deleted file mode 100644 index 19129e315fe59..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/nopt/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -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/node_modules/npm-lifecycle/node_modules/nopt/README.md b/node_modules/npm-lifecycle/node_modules/nopt/README.md deleted file mode 100644 index f21a4b31c5d48..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/nopt/README.md +++ /dev/null @@ -1,211 +0,0 @@ -If you want to write an option parser, and have it be good, there are -two ways to do it. The Right Way, and the Wrong Way. - -The Wrong Way is to sit down and write an option parser. We've all done -that. - -The Right Way is to write some complex configurable program with so many -options that you hit the limit of your frustration just trying to -manage them all, and defer it with duct-tape solutions until you see -exactly to the core of the problem, and finally snap and write an -awesome option parser. - -If you want to write an option parser, don't write an option parser. -Write a package manager, or a source control system, or a service -restarter, or an operating system. You probably won't end up with a -good one of those, but if you don't give up, and you are relentless and -diligent enough in your procrastination, you may just end up with a very -nice option parser. - -## USAGE - - // my-program.js - var nopt = require("nopt") - , Stream = require("stream").Stream - , path = require("path") - , knownOpts = { "foo" : [String, null] - , "bar" : [Stream, Number] - , "baz" : path - , "bloo" : [ "big", "medium", "small" ] - , "flag" : Boolean - , "pick" : Boolean - , "many1" : [String, Array] - , "many2" : [path] - } - , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] - , "b7" : ["--bar", "7"] - , "m" : ["--bloo", "medium"] - , "p" : ["--pick"] - , "f" : ["--flag"] - } - // everything is optional. - // knownOpts and shorthands default to {} - // arg list defaults to process.argv - // slice defaults to 2 - , parsed = nopt(knownOpts, shortHands, process.argv, 2) - console.log(parsed) - -This would give you support for any of the following: - -```bash -$ node my-program.js --foo "blerp" --no-flag -{ "foo" : "blerp", "flag" : false } - -$ node my-program.js ---bar 7 --foo "Mr. Hand" --flag -{ bar: 7, foo: "Mr. Hand", flag: true } - -$ node my-program.js --foo "blerp" -f -----p -{ foo: "blerp", flag: true, pick: true } - -$ node my-program.js -fp --foofoo -{ foo: "Mr. Foo", flag: true, pick: true } - -$ node my-program.js --foofoo -- -fp # -- stops the flag parsing. -{ foo: "Mr. Foo", argv: { remain: ["-fp"] } } - -$ node my-program.js --blatzk -fp # unknown opts are ok. -{ blatzk: true, flag: true, pick: true } - -$ node my-program.js --blatzk=1000 -fp # but you need to use = if they have a value -{ blatzk: 1000, flag: true, pick: true } - -$ node my-program.js --no-blatzk -fp # unless they start with "no-" -{ blatzk: false, flag: true, pick: true } - -$ node my-program.js --baz b/a/z # known paths are resolved. -{ baz: "/Users/isaacs/b/a/z" } - -# if Array is one of the types, then it can take many -# values, and will always be an array. The other types provided -# specify what types are allowed in the list. - -$ node my-program.js --many1 5 --many1 null --many1 foo -{ many1: ["5", "null", "foo"] } - -$ node my-program.js --many2 foo --many2 bar -{ many2: ["/path/to/foo", "path/to/bar"] } -``` - -Read the tests at the bottom of `lib/nopt.js` for more examples of -what this puppy can do. - -## Types - -The following types are supported, and defined on `nopt.typeDefs` - -* String: A normal string. No parsing is done. -* path: A file system path. Gets resolved against cwd if not absolute. -* url: A url. If it doesn't parse, it isn't accepted. -* Number: Must be numeric. -* Date: Must parse as a date. If it does, and `Date` is one of the options, - then it will return a Date object, not a string. -* Boolean: Must be either `true` or `false`. If an option is a boolean, - then it does not need a value, and its presence will imply `true` as - the value. To negate boolean flags, do `--no-whatever` or `--whatever - false` -* NaN: Means that the option is strictly not allowed. Any value will - fail. -* Stream: An object matching the "Stream" class in node. Valuable - for use when validating programmatically. (npm uses this to let you - supply any WriteStream on the `outfd` and `logfd` config options.) -* Array: If `Array` is specified as one of the types, then the value - will be parsed as a list of options. This means that multiple values - can be specified, and that the value will always be an array. - -If a type is an array of values not on this list, then those are -considered valid values. For instance, in the example above, the -`--bloo` option can only be one of `"big"`, `"medium"`, or `"small"`, -and any other value will be rejected. - -When parsing unknown fields, `"true"`, `"false"`, and `"null"` will be -interpreted as their JavaScript equivalents. - -You can also mix types and values, or multiple types, in a list. For -instance `{ blah: [Number, null] }` would allow a value to be set to -either a Number or null. When types are ordered, this implies a -preference, and the first type that can be used to properly interpret -the value will be used. - -To define a new type, add it to `nopt.typeDefs`. Each item in that -hash is an object with a `type` member and a `validate` method. The -`type` member is an object that matches what goes in the type list. The -`validate` method is a function that gets called with `validate(data, -key, val)`. Validate methods should assign `data[key]` to the valid -value of `val` if it can be handled properly, or return boolean -`false` if it cannot. - -You can also call `nopt.clean(data, types, typeDefs)` to clean up a -config object and remove its invalid properties. - -## Error Handling - -By default, nopt outputs a warning to standard error when invalid values for -known options are found. You can change this behavior by assigning a method -to `nopt.invalidHandler`. This method will be called with -the offending `nopt.invalidHandler(key, val, types)`. - -If no `nopt.invalidHandler` is assigned, then it will console.error -its whining. If it is assigned to boolean `false` then the warning is -suppressed. - -## Abbreviations - -Yes, they are supported. If you define options like this: - -```javascript -{ "foolhardyelephants" : Boolean -, "pileofmonkeys" : Boolean } -``` - -Then this will work: - -```bash -node program.js --foolhar --pil -node program.js --no-f --pileofmon -# etc. -``` - -## Shorthands - -Shorthands are a hash of shorter option names to a snippet of args that -they expand to. - -If multiple one-character shorthands are all combined, and the -combination does not unambiguously match any other option or shorthand, -then they will be broken up into their constituent parts. For example: - -```json -{ "s" : ["--loglevel", "silent"] -, "g" : "--global" -, "f" : "--force" -, "p" : "--parseable" -, "l" : "--long" -} -``` - -```bash -npm ls -sgflp -# just like doing this: -npm ls --loglevel silent --global --force --long --parseable -``` - -## The Rest of the args - -The config object returned by nopt is given a special member called -`argv`, which is an object with the following fields: - -* `remain`: The remaining args after all the parsing has occurred. -* `original`: The args as they originally appeared. -* `cooked`: The args after flags and shorthands are expanded. - -## Slicing - -Node programs are called with more or less the exact argv as it appears -in C land, after the v8 and node-specific options have been plucked off. -As such, `argv[0]` is always `node` and `argv[1]` is always the -JavaScript program being run. - -That's usually not very useful to you. So they're sliced off by -default. If you want them, then you can pass in `0` as the last -argument, or any other number that you'd like to slice off the start of -the list. diff --git a/node_modules/npm-lifecycle/node_modules/nopt/bin/nopt.js b/node_modules/npm-lifecycle/node_modules/nopt/bin/nopt.js deleted file mode 100755 index 3232d4c570fdc..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/nopt/bin/nopt.js +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env node -var nopt = require("../lib/nopt") - , path = require("path") - , types = { num: Number - , bool: Boolean - , help: Boolean - , list: Array - , "num-list": [Number, Array] - , "str-list": [String, Array] - , "bool-list": [Boolean, Array] - , str: String - , clear: Boolean - , config: Boolean - , length: Number - , file: path - } - , shorthands = { s: [ "--str", "astring" ] - , b: [ "--bool" ] - , nb: [ "--no-bool" ] - , tft: [ "--bool-list", "--no-bool-list", "--bool-list", "true" ] - , "?": ["--help"] - , h: ["--help"] - , H: ["--help"] - , n: [ "--num", "125" ] - , c: ["--config"] - , l: ["--length"] - , f: ["--file"] - } - , parsed = nopt( types - , shorthands - , process.argv - , 2 ) - -console.log("parsed", parsed) - -if (parsed.help) { - console.log("") - console.log("nopt cli tester") - console.log("") - console.log("types") - console.log(Object.keys(types).map(function M (t) { - var type = types[t] - if (Array.isArray(type)) { - return [t, type.map(function (type) { return type.name })] - } - return [t, type && type.name] - }).reduce(function (s, i) { - s[i[0]] = i[1] - return s - }, {})) - console.log("") - console.log("shorthands") - console.log(shorthands) -} diff --git a/node_modules/npm-lifecycle/node_modules/nopt/examples/my-program.js b/node_modules/npm-lifecycle/node_modules/nopt/examples/my-program.js deleted file mode 100755 index 142447e18e756..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/nopt/examples/my-program.js +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env node - -//process.env.DEBUG_NOPT = 1 - -// my-program.js -var nopt = require("../lib/nopt") - , Stream = require("stream").Stream - , path = require("path") - , knownOpts = { "foo" : [String, null] - , "bar" : [Stream, Number] - , "baz" : path - , "bloo" : [ "big", "medium", "small" ] - , "flag" : Boolean - , "pick" : Boolean - } - , shortHands = { "foofoo" : ["--foo", "Mr. Foo"] - , "b7" : ["--bar", "7"] - , "m" : ["--bloo", "medium"] - , "p" : ["--pick"] - , "f" : ["--flag", "true"] - , "g" : ["--flag"] - , "s" : "--flag" - } - // everything is optional. - // knownOpts and shorthands default to {} - // arg list defaults to process.argv - // slice defaults to 2 - , parsed = nopt(knownOpts, shortHands, process.argv, 2) - -console.log("parsed =\n"+ require("util").inspect(parsed)) diff --git a/node_modules/npm-lifecycle/node_modules/nopt/lib/nopt.js b/node_modules/npm-lifecycle/node_modules/nopt/lib/nopt.js deleted file mode 100644 index 97707e784243b..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/nopt/lib/nopt.js +++ /dev/null @@ -1,415 +0,0 @@ -// info about each config option. - -var debug = process.env.DEBUG_NOPT || process.env.NOPT_DEBUG - ? function () { console.error.apply(console, arguments) } - : function () {} - -var url = require("url") - , path = require("path") - , Stream = require("stream").Stream - , abbrev = require("abbrev") - -module.exports = exports = nopt -exports.clean = clean - -exports.typeDefs = - { String : { type: String, validate: validateString } - , Boolean : { type: Boolean, validate: validateBoolean } - , url : { type: url, validate: validateUrl } - , Number : { type: Number, validate: validateNumber } - , path : { type: path, validate: validatePath } - , Stream : { type: Stream, validate: validateStream } - , Date : { type: Date, validate: validateDate } - } - -function nopt (types, shorthands, args, slice) { - args = args || process.argv - types = types || {} - shorthands = shorthands || {} - if (typeof slice !== "number") slice = 2 - - debug(types, shorthands, args, slice) - - args = args.slice(slice) - var data = {} - , key - , remain = [] - , cooked = args - , original = args.slice(0) - - parse(args, data, remain, types, shorthands) - // now data is full - clean(data, types, exports.typeDefs) - data.argv = {remain:remain,cooked:cooked,original:original} - Object.defineProperty(data.argv, 'toString', { value: function () { - return this.original.map(JSON.stringify).join(" ") - }, enumerable: false }) - return data -} - -function clean (data, types, typeDefs) { - typeDefs = typeDefs || exports.typeDefs - var remove = {} - , typeDefault = [false, true, null, String, Array] - - Object.keys(data).forEach(function (k) { - if (k === "argv") return - var val = data[k] - , isArray = Array.isArray(val) - , type = types[k] - if (!isArray) val = [val] - if (!type) type = typeDefault - if (type === Array) type = typeDefault.concat(Array) - if (!Array.isArray(type)) type = [type] - - debug("val=%j", val) - debug("types=", type) - val = val.map(function (val) { - // if it's an unknown value, then parse false/true/null/numbers/dates - if (typeof val === "string") { - debug("string %j", val) - val = val.trim() - if ((val === "null" && ~type.indexOf(null)) - || (val === "true" && - (~type.indexOf(true) || ~type.indexOf(Boolean))) - || (val === "false" && - (~type.indexOf(false) || ~type.indexOf(Boolean)))) { - val = JSON.parse(val) - debug("jsonable %j", val) - } else if (~type.indexOf(Number) && !isNaN(val)) { - debug("convert to number", val) - val = +val - } else if (~type.indexOf(Date) && !isNaN(Date.parse(val))) { - debug("convert to date", val) - val = new Date(val) - } - } - - if (!types.hasOwnProperty(k)) { - return val - } - - // allow `--no-blah` to set 'blah' to null if null is allowed - if (val === false && ~type.indexOf(null) && - !(~type.indexOf(false) || ~type.indexOf(Boolean))) { - val = null - } - - var d = {} - d[k] = val - debug("prevalidated val", d, val, types[k]) - if (!validate(d, k, val, types[k], typeDefs)) { - if (exports.invalidHandler) { - exports.invalidHandler(k, val, types[k], data) - } else if (exports.invalidHandler !== false) { - debug("invalid: "+k+"="+val, types[k]) - } - return remove - } - debug("validated val", d, val, types[k]) - return d[k] - }).filter(function (val) { return val !== remove }) - - if (!val.length) delete data[k] - else if (isArray) { - debug(isArray, data[k], val) - data[k] = val - } else data[k] = val[0] - - debug("k=%s val=%j", k, val, data[k]) - }) -} - -function validateString (data, k, val) { - data[k] = String(val) -} - -function validatePath (data, k, val) { - if (val === true) return false - if (val === null) return true - - val = String(val) - var homePattern = process.platform === 'win32' ? /^~(\/|\\)/ : /^~\// - if (val.match(homePattern) && process.env.HOME) { - val = path.resolve(process.env.HOME, val.substr(2)) - } - data[k] = path.resolve(String(val)) - return true -} - -function validateNumber (data, k, val) { - debug("validate Number %j %j %j", k, val, isNaN(val)) - if (isNaN(val)) return false - data[k] = +val -} - -function validateDate (data, k, val) { - debug("validate Date %j %j %j", k, val, Date.parse(val)) - var s = Date.parse(val) - if (isNaN(s)) return false - data[k] = new Date(val) -} - -function validateBoolean (data, k, val) { - if (val instanceof Boolean) val = val.valueOf() - else if (typeof val === "string") { - if (!isNaN(val)) val = !!(+val) - else if (val === "null" || val === "false") val = false - else val = true - } else val = !!val - data[k] = val -} - -function validateUrl (data, k, val) { - val = url.parse(String(val)) - if (!val.host) return false - data[k] = val.href -} - -function validateStream (data, k, val) { - if (!(val instanceof Stream)) return false - data[k] = val -} - -function validate (data, k, val, type, typeDefs) { - // arrays are lists of types. - if (Array.isArray(type)) { - for (var i = 0, l = type.length; i < l; i ++) { - if (type[i] === Array) continue - if (validate(data, k, val, type[i], typeDefs)) return true - } - delete data[k] - return false - } - - // an array of anything? - if (type === Array) return true - - // NaN is poisonous. Means that something is not allowed. - if (type !== type) { - debug("Poison NaN", k, val, type) - delete data[k] - return false - } - - // explicit list of values - if (val === type) { - debug("Explicitly allowed %j", val) - // if (isArray) (data[k] = data[k] || []).push(val) - // else data[k] = val - data[k] = val - return true - } - - // now go through the list of typeDefs, validate against each one. - var ok = false - , types = Object.keys(typeDefs) - for (var i = 0, l = types.length; i < l; i ++) { - debug("test type %j %j %j", k, val, types[i]) - var t = typeDefs[types[i]] - if (t && - ((type && type.name && t.type && t.type.name) ? (type.name === t.type.name) : (type === t.type))) { - var d = {} - ok = false !== t.validate(d, k, val) - val = d[k] - if (ok) { - // if (isArray) (data[k] = data[k] || []).push(val) - // else data[k] = val - data[k] = val - break - } - } - } - debug("OK? %j (%j %j %j)", ok, k, val, types[i]) - - if (!ok) delete data[k] - return ok -} - -function parse (args, data, remain, types, shorthands) { - debug("parse", args, data, remain) - - var key = null - , abbrevs = abbrev(Object.keys(types)) - , shortAbbr = abbrev(Object.keys(shorthands)) - - for (var i = 0; i < args.length; i ++) { - var arg = args[i] - debug("arg", arg) - - if (arg.match(/^-{2,}$/)) { - // done with keys. - // the rest are args. - remain.push.apply(remain, args.slice(i + 1)) - args[i] = "--" - break - } - var hadEq = false - if (arg.charAt(0) === "-" && arg.length > 1) { - if (arg.indexOf("=") !== -1) { - hadEq = true - var v = arg.split("=") - arg = v.shift() - v = v.join("=") - args.splice.apply(args, [i, 1].concat([arg, v])) - } - - // see if it's a shorthand - // if so, splice and back up to re-parse it. - var shRes = resolveShort(arg, shorthands, shortAbbr, abbrevs) - debug("arg=%j shRes=%j", arg, shRes) - if (shRes) { - debug(arg, shRes) - args.splice.apply(args, [i, 1].concat(shRes)) - if (arg !== shRes[0]) { - i -- - continue - } - } - arg = arg.replace(/^-+/, "") - var no = null - while (arg.toLowerCase().indexOf("no-") === 0) { - no = !no - arg = arg.substr(3) - } - - if (abbrevs[arg]) arg = abbrevs[arg] - - var isArray = types[arg] === Array || - Array.isArray(types[arg]) && types[arg].indexOf(Array) !== -1 - - // allow unknown things to be arrays if specified multiple times. - if (!types.hasOwnProperty(arg) && data.hasOwnProperty(arg)) { - if (!Array.isArray(data[arg])) - data[arg] = [data[arg]] - isArray = true - } - - var val - , la = args[i + 1] - - var isBool = typeof no === 'boolean' || - types[arg] === Boolean || - Array.isArray(types[arg]) && types[arg].indexOf(Boolean) !== -1 || - (typeof types[arg] === 'undefined' && !hadEq) || - (la === "false" && - (types[arg] === null || - Array.isArray(types[arg]) && ~types[arg].indexOf(null))) - - if (isBool) { - // just set and move along - val = !no - // however, also support --bool true or --bool false - if (la === "true" || la === "false") { - val = JSON.parse(la) - la = null - if (no) val = !val - i ++ - } - - // also support "foo":[Boolean, "bar"] and "--foo bar" - if (Array.isArray(types[arg]) && la) { - if (~types[arg].indexOf(la)) { - // an explicit type - val = la - i ++ - } else if ( la === "null" && ~types[arg].indexOf(null) ) { - // null allowed - val = null - i ++ - } else if ( !la.match(/^-{2,}[^-]/) && - !isNaN(la) && - ~types[arg].indexOf(Number) ) { - // number - val = +la - i ++ - } else if ( !la.match(/^-[^-]/) && ~types[arg].indexOf(String) ) { - // string - val = la - i ++ - } - } - - if (isArray) (data[arg] = data[arg] || []).push(val) - else data[arg] = val - - continue - } - - if (types[arg] === String && la === undefined) - la = "" - - if (la && la.match(/^-{2,}$/)) { - la = undefined - i -- - } - - val = la === undefined ? true : la - if (isArray) (data[arg] = data[arg] || []).push(val) - else data[arg] = val - - i ++ - continue - } - remain.push(arg) - } -} - -function resolveShort (arg, shorthands, shortAbbr, abbrevs) { - // handle single-char shorthands glommed together, like - // npm ls -glp, but only if there is one dash, and only if - // all of the chars are single-char shorthands, and it's - // not a match to some other abbrev. - arg = arg.replace(/^-+/, '') - - // if it's an exact known option, then don't go any further - if (abbrevs[arg] === arg) - return null - - // if it's an exact known shortopt, same deal - if (shorthands[arg]) { - // make it an array, if it's a list of words - if (shorthands[arg] && !Array.isArray(shorthands[arg])) - shorthands[arg] = shorthands[arg].split(/\s+/) - - return shorthands[arg] - } - - // first check to see if this arg is a set of single-char shorthands - var singles = shorthands.___singles - if (!singles) { - singles = Object.keys(shorthands).filter(function (s) { - return s.length === 1 - }).reduce(function (l,r) { - l[r] = true - return l - }, {}) - shorthands.___singles = singles - debug('shorthand singles', singles) - } - - var chrs = arg.split("").filter(function (c) { - return singles[c] - }) - - if (chrs.join("") === arg) return chrs.map(function (c) { - return shorthands[c] - }).reduce(function (l, r) { - return l.concat(r) - }, []) - - - // if it's an arg abbrev, and not a literal shorthand, then prefer the arg - if (abbrevs[arg] && !shorthands[arg]) - return null - - // if it's an abbr for a shorthand, then use that - if (shortAbbr[arg]) - arg = shortAbbr[arg] - - // make it an array, if it's a list of words - if (shorthands[arg] && !Array.isArray(shorthands[arg])) - shorthands[arg] = shorthands[arg].split(/\s+/) - - return shorthands[arg] -} diff --git a/node_modules/npm-lifecycle/node_modules/nopt/package.json b/node_modules/npm-lifecycle/node_modules/nopt/package.json deleted file mode 100644 index 76ed91f436451..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/nopt/package.json +++ /dev/null @@ -1,57 +0,0 @@ -{ - "_from": "nopt@2 || 3", - "_id": "nopt@3.0.6", - "_inBundle": false, - "_integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "_location": "/npm-lifecycle/nopt", - "_phantomChildren": {}, - "_requested": { - "type": "range", - "registry": true, - "raw": "nopt@2 || 3", - "name": "nopt", - "escapedName": "nopt", - "rawSpec": "2 || 3", - "saveSpec": null, - "fetchSpec": "2 || 3" - }, - "_requiredBy": [ - "/npm-lifecycle/node-gyp" - ], - "_resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "_shasum": "c6465dbf08abcd4db359317f79ac68a646b28ff9", - "_spec": "nopt@2 || 3", - "_where": "/home/hugh/Development/github.com/npm/cli/node_modules/npm-lifecycle/node_modules/node-gyp", - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me", - "url": "http://blog.izs.me/" - }, - "bin": { - "nopt": "./bin/nopt.js" - }, - "bugs": { - "url": "https://github.com/npm/nopt/issues" - }, - "bundleDependencies": false, - "dependencies": { - "abbrev": "1" - }, - "deprecated": false, - "description": "Option parsing for Node, supporting types, shorthands, etc. Used by npm.", - "devDependencies": { - "tap": "^1.2.0" - }, - "homepage": "https://github.com/npm/nopt#readme", - "license": "ISC", - "main": "lib/nopt.js", - "name": "nopt", - "repository": { - "type": "git", - "url": "git+https://github.com/npm/nopt.git" - }, - "scripts": { - "test": "tap test/*.js" - }, - "version": "3.0.6" -} diff --git a/node_modules/npm-lifecycle/node_modules/nopt/test/basic.js b/node_modules/npm-lifecycle/node_modules/nopt/test/basic.js deleted file mode 100644 index d399de9209932..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/nopt/test/basic.js +++ /dev/null @@ -1,273 +0,0 @@ -var nopt = require("../") - , test = require('tap').test - - -test("passing a string results in a string", function (t) { - var parsed = nopt({ key: String }, {}, ["--key", "myvalue"], 0) - t.same(parsed.key, "myvalue") - t.end() -}) - -// https://github.com/npm/nopt/issues/31 -test("Empty String results in empty string, not true", function (t) { - var parsed = nopt({ empty: String }, {}, ["--empty"], 0) - t.same(parsed.empty, "") - t.end() -}) - -test("~ path is resolved to $HOME", function (t) { - var path = require("path") - if (!process.env.HOME) process.env.HOME = "/tmp" - var parsed = nopt({key: path}, {}, ["--key=~/val"], 0) - t.same(parsed.key, path.resolve(process.env.HOME, "val")) - t.end() -}) - -// https://github.com/npm/nopt/issues/24 -test("Unknown options are not parsed as numbers", function (t) { - var parsed = nopt({"parse-me": Number}, null, ['--leave-as-is=1.20', '--parse-me=1.20'], 0) - t.equal(parsed['leave-as-is'], '1.20') - t.equal(parsed['parse-me'], 1.2) - t.end() -}); - -// https://github.com/npm/nopt/issues/48 -test("Check types based on name of type", function (t) { - var parsed = nopt({"parse-me": {name: "Number"}}, null, ['--parse-me=1.20'], 0) - t.equal(parsed['parse-me'], 1.2) - t.end() -}) - - -test("Missing types are not parsed", function (t) { - var parsed = nopt({"parse-me": {}}, null, ['--parse-me=1.20'], 0) - //should only contain argv - t.equal(Object.keys(parsed).length, 1) - t.end() -}) - -test("Types passed without a name are not parsed", function (t) { - var parsed = nopt({"parse-me": {}}, {}, ['--parse-me=1.20'], 0) - //should only contain argv - t.equal(Object.keys(parsed).length, 1) - t.end() -}) - -test("other tests", function (t) { - - var util = require("util") - , Stream = require("stream") - , path = require("path") - , url = require("url") - - , shorthands = - { s : ["--loglevel", "silent"] - , d : ["--loglevel", "info"] - , dd : ["--loglevel", "verbose"] - , ddd : ["--loglevel", "silly"] - , noreg : ["--no-registry"] - , reg : ["--registry"] - , "no-reg" : ["--no-registry"] - , silent : ["--loglevel", "silent"] - , verbose : ["--loglevel", "verbose"] - , h : ["--usage"] - , H : ["--usage"] - , "?" : ["--usage"] - , help : ["--usage"] - , v : ["--version"] - , f : ["--force"] - , desc : ["--description"] - , "no-desc" : ["--no-description"] - , "local" : ["--no-global"] - , l : ["--long"] - , p : ["--parseable"] - , porcelain : ["--parseable"] - , g : ["--global"] - } - - , types = - { aoa: Array - , nullstream: [null, Stream] - , date: Date - , str: String - , browser : String - , cache : path - , color : ["always", Boolean] - , depth : Number - , description : Boolean - , dev : Boolean - , editor : path - , force : Boolean - , global : Boolean - , globalconfig : path - , group : [String, Number] - , gzipbin : String - , logfd : [Number, Stream] - , loglevel : ["silent","win","error","warn","info","verbose","silly"] - , long : Boolean - , "node-version" : [false, String] - , npaturl : url - , npat : Boolean - , "onload-script" : [false, String] - , outfd : [Number, Stream] - , parseable : Boolean - , pre: Boolean - , prefix: path - , proxy : url - , "rebuild-bundle" : Boolean - , registry : url - , searchopts : String - , searchexclude: [null, String] - , shell : path - , t: [Array, String] - , tag : String - , tar : String - , tmp : path - , "unsafe-perm" : Boolean - , usage : Boolean - , user : String - , username : String - , userconfig : path - , version : Boolean - , viewer: path - , _exit : Boolean - , path: path - } - - ; [["-v", {version:true}, []] - ,["---v", {version:true}, []] - ,["ls -s --no-reg connect -d", - {loglevel:"info",registry:null},["ls","connect"]] - ,["ls ---s foo",{loglevel:"silent"},["ls","foo"]] - ,["ls --registry blargle", {}, ["ls"]] - ,["--no-registry", {registry:null}, []] - ,["--no-color true", {color:false}, []] - ,["--no-color false", {color:true}, []] - ,["--no-color", {color:false}, []] - ,["--color false", {color:false}, []] - ,["--color --logfd 7", {logfd:7,color:true}, []] - ,["--color=true", {color:true}, []] - ,["--logfd=10", {logfd:10}, []] - ,["--tmp=/tmp -tar=gtar",{tmp:"/tmp",tar:"gtar"},[]] - ,["--tmp=tmp -tar=gtar", - {tmp:path.resolve(process.cwd(), "tmp"),tar:"gtar"},[]] - ,["--logfd x", {}, []] - ,["a -true -- -no-false", {true:true},["a","-no-false"]] - ,["a -no-false", {false:false},["a"]] - ,["a -no-no-true", {true:true}, ["a"]] - ,["a -no-no-no-false", {false:false}, ["a"]] - ,["---NO-no-No-no-no-no-nO-no-no"+ - "-No-no-no-no-no-no-no-no-no"+ - "-no-no-no-no-NO-NO-no-no-no-no-no-no"+ - "-no-body-can-do-the-boogaloo-like-I-do" - ,{"body-can-do-the-boogaloo-like-I-do":false}, []] - ,["we are -no-strangers-to-love "+ - "--you-know=the-rules --and=so-do-i "+ - "---im-thinking-of=a-full-commitment "+ - "--no-you-would-get-this-from-any-other-guy "+ - "--no-gonna-give-you-up "+ - "-no-gonna-let-you-down=true "+ - "--no-no-gonna-run-around false "+ - "--desert-you=false "+ - "--make-you-cry false "+ - "--no-tell-a-lie "+ - "--no-no-and-hurt-you false" - ,{"strangers-to-love":false - ,"you-know":"the-rules" - ,"and":"so-do-i" - ,"you-would-get-this-from-any-other-guy":false - ,"gonna-give-you-up":false - ,"gonna-let-you-down":false - ,"gonna-run-around":false - ,"desert-you":false - ,"make-you-cry":false - ,"tell-a-lie":false - ,"and-hurt-you":false - },["we", "are"]] - ,["-t one -t two -t three" - ,{t: ["one", "two", "three"]} - ,[]] - ,["-t one -t null -t three four five null" - ,{t: ["one", "null", "three"]} - ,["four", "five", "null"]] - ,["-t foo" - ,{t:["foo"]} - ,[]] - ,["--no-t" - ,{t:["false"]} - ,[]] - ,["-no-no-t" - ,{t:["true"]} - ,[]] - ,["-aoa one -aoa null -aoa 100" - ,{aoa:["one", null, '100']} - ,[]] - ,["-str 100" - ,{str:"100"} - ,[]] - ,["--color always" - ,{color:"always"} - ,[]] - ,["--no-nullstream" - ,{nullstream:null} - ,[]] - ,["--nullstream false" - ,{nullstream:null} - ,[]] - ,["--notadate=2011-01-25" - ,{notadate: "2011-01-25"} - ,[]] - ,["--date 2011-01-25" - ,{date: new Date("2011-01-25")} - ,[]] - ,["-cl 1" - ,{config: true, length: 1} - ,[] - ,{config: Boolean, length: Number, clear: Boolean} - ,{c: "--config", l: "--length"}] - ,["--acount bla" - ,{"acount":true} - ,["bla"] - ,{account: Boolean, credentials: Boolean, options: String} - ,{a:"--account", c:"--credentials",o:"--options"}] - ,["--clear" - ,{clear:true} - ,[] - ,{clear:Boolean,con:Boolean,len:Boolean,exp:Boolean,add:Boolean,rep:Boolean} - ,{c:"--con",l:"--len",e:"--exp",a:"--add",r:"--rep"}] - ,["--file -" - ,{"file":"-"} - ,[] - ,{file:String} - ,{}] - ,["--file -" - ,{"file":true} - ,["-"] - ,{file:Boolean} - ,{}] - ,["--path" - ,{"path":null} - ,[]] - ,["--path ." - ,{"path":process.cwd()} - ,[]] - ].forEach(function (test) { - var argv = test[0].split(/\s+/) - , opts = test[1] - , rem = test[2] - , actual = nopt(test[3] || types, test[4] || shorthands, argv, 0) - , parsed = actual.argv - delete actual.argv - for (var i in opts) { - var e = JSON.stringify(opts[i]) - , a = JSON.stringify(actual[i] === undefined ? null : actual[i]) - if (e && typeof e === "object") { - t.deepEqual(e, a) - } else { - t.equal(e, a) - } - } - t.deepEqual(rem, parsed.remain) - }) - t.end() -}) diff --git a/node_modules/npm-lifecycle/node_modules/semver/LICENSE b/node_modules/npm-lifecycle/node_modules/semver/LICENSE deleted file mode 100644 index 19129e315fe59..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/semver/LICENSE +++ /dev/null @@ -1,15 +0,0 @@ -The ISC License - -Copyright (c) Isaac Z. Schlueter and Contributors - -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/node_modules/npm-lifecycle/node_modules/semver/README.md b/node_modules/npm-lifecycle/node_modules/semver/README.md deleted file mode 100644 index cbd956549dbb0..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/semver/README.md +++ /dev/null @@ -1,350 +0,0 @@ -semver(1) -- The semantic versioner for npm -=========================================== - -## Usage - - $ npm install semver - $ node - var semver = require('semver') - - semver.valid('1.2.3') // '1.2.3' - semver.valid('a.b.c') // null - semver.clean(' =v1.2.3 ') // '1.2.3' - semver.satisfies('1.2.3', '1.x || >=2.5.0 || 5.0.0 - 7.2.3') // true - semver.gt('1.2.3', '9.8.7') // false - semver.lt('1.2.3', '9.8.7') // true - -As a command-line utility: - - $ semver -h - - SemVer 5.1.0 - - A JavaScript implementation of the http://semver.org/ specification - Copyright Isaac Z. Schlueter - - Usage: semver [options] [ [...]] - Prints valid versions sorted by SemVer precedence - - Options: - -r --range - Print versions that match the specified range. - - -i --increment [] - Increment a version by the specified level. Level can - be one of: major, minor, patch, premajor, preminor, - prepatch, or prerelease. Default level is 'patch'. - Only one version may be specified. - - --preid - Identifier to be used to prefix premajor, preminor, - prepatch or prerelease version increments. - - -l --loose - Interpret versions and ranges loosely - - Program exits successfully if any valid version satisfies - all supplied ranges, and prints all satisfying versions. - - If no satisfying versions are found, then exits failure. - - Versions are printed in ascending order, so supplying - multiple versions to the utility will just sort them. - -## Versions - -A "version" is described by the `v2.0.0` specification found at -. - -A leading `"="` or `"v"` character is stripped off and ignored. - -## Ranges - -A `version range` is a set of `comparators` which specify versions -that satisfy the range. - -A `comparator` is composed of an `operator` and a `version`. The set -of primitive `operators` is: - -* `<` Less than -* `<=` Less than or equal to -* `>` Greater than -* `>=` Greater than or equal to -* `=` Equal. If no operator is specified, then equality is assumed, - so this operator is optional, but MAY be included. - -For example, the comparator `>=1.2.7` would match the versions -`1.2.7`, `1.2.8`, `2.5.3`, and `1.3.9`, but not the versions `1.2.6` -or `1.1.0`. - -Comparators can be joined by whitespace to form a `comparator set`, -which is satisfied by the **intersection** of all of the comparators -it includes. - -A range is composed of one or more comparator sets, joined by `||`. A -version matches a range if and only if every comparator in at least -one of the `||`-separated comparator sets is satisfied by the version. - -For example, the range `>=1.2.7 <1.3.0` would match the versions -`1.2.7`, `1.2.8`, and `1.2.99`, but not the versions `1.2.6`, `1.3.0`, -or `1.1.0`. - -The range `1.2.7 || >=1.2.9 <2.0.0` would match the versions `1.2.7`, -`1.2.9`, and `1.4.6`, but not the versions `1.2.8` or `2.0.0`. - -### Prerelease Tags - -If a version has a prerelease tag (for example, `1.2.3-alpha.3`) then -it will only be allowed to satisfy comparator sets if at least one -comparator with the same `[major, minor, patch]` tuple also has a -prerelease tag. - -For example, the range `>1.2.3-alpha.3` would be allowed to match the -version `1.2.3-alpha.7`, but it would *not* be satisfied by -`3.4.5-alpha.9`, even though `3.4.5-alpha.9` is technically "greater -than" `1.2.3-alpha.3` according to the SemVer sort rules. The version -range only accepts prerelease tags on the `1.2.3` version. The -version `3.4.5` *would* satisfy the range, because it does not have a -prerelease flag, and `3.4.5` is greater than `1.2.3-alpha.7`. - -The purpose for this behavior is twofold. First, prerelease versions -frequently are updated very quickly, and contain many breaking changes -that are (by the author's design) not yet fit for public consumption. -Therefore, by default, they are excluded from range matching -semantics. - -Second, a user who has opted into using a prerelease version has -clearly indicated the intent to use *that specific* set of -alpha/beta/rc versions. By including a prerelease tag in the range, -the user is indicating that they are aware of the risk. However, it -is still not appropriate to assume that they have opted into taking a -similar risk on the *next* set of prerelease versions. - -#### Prerelease Identifiers - -The method `.inc` takes an additional `identifier` string argument that -will append the value of the string as a prerelease identifier: - -```javascript -> semver.inc('1.2.3', 'prerelease', 'beta') -'1.2.4-beta.0' -``` - -command-line example: - -```shell -$ semver 1.2.3 -i prerelease --preid beta -1.2.4-beta.0 -``` - -Which then can be used to increment further: - -```shell -$ semver 1.2.4-beta.0 -i prerelease -1.2.4-beta.1 -``` - -### Advanced Range Syntax - -Advanced range syntax desugars to primitive comparators in -deterministic ways. - -Advanced ranges may be combined in the same way as primitive -comparators using white space or `||`. - -#### Hyphen Ranges `X.Y.Z - A.B.C` - -Specifies an inclusive set. - -* `1.2.3 - 2.3.4` := `>=1.2.3 <=2.3.4` - -If a partial version is provided as the first version in the inclusive -range, then the missing pieces are replaced with zeroes. - -* `1.2 - 2.3.4` := `>=1.2.0 <=2.3.4` - -If a partial version is provided as the second version in the -inclusive range, then all versions that start with the supplied parts -of the tuple are accepted, but nothing that would be greater than the -provided tuple parts. - -* `1.2.3 - 2.3` := `>=1.2.3 <2.4.0` -* `1.2.3 - 2` := `>=1.2.3 <3.0.0` - -#### X-Ranges `1.2.x` `1.X` `1.2.*` `*` - -Any of `X`, `x`, or `*` may be used to "stand in" for one of the -numeric values in the `[major, minor, patch]` tuple. - -* `*` := `>=0.0.0` (Any version satisfies) -* `1.x` := `>=1.0.0 <2.0.0` (Matching major version) -* `1.2.x` := `>=1.2.0 <1.3.0` (Matching major and minor versions) - -A partial version range is treated as an X-Range, so the special -character is in fact optional. - -* `""` (empty string) := `*` := `>=0.0.0` -* `1` := `1.x.x` := `>=1.0.0 <2.0.0` -* `1.2` := `1.2.x` := `>=1.2.0 <1.3.0` - -#### Tilde Ranges `~1.2.3` `~1.2` `~1` - -Allows patch-level changes if a minor version is specified on the -comparator. Allows minor-level changes if not. - -* `~1.2.3` := `>=1.2.3 <1.(2+1).0` := `>=1.2.3 <1.3.0` -* `~1.2` := `>=1.2.0 <1.(2+1).0` := `>=1.2.0 <1.3.0` (Same as `1.2.x`) -* `~1` := `>=1.0.0 <(1+1).0.0` := `>=1.0.0 <2.0.0` (Same as `1.x`) -* `~0.2.3` := `>=0.2.3 <0.(2+1).0` := `>=0.2.3 <0.3.0` -* `~0.2` := `>=0.2.0 <0.(2+1).0` := `>=0.2.0 <0.3.0` (Same as `0.2.x`) -* `~0` := `>=0.0.0 <(0+1).0.0` := `>=0.0.0 <1.0.0` (Same as `0.x`) -* `~1.2.3-beta.2` := `>=1.2.3-beta.2 <1.3.0` Note that prereleases in - the `1.2.3` version will be allowed, if they are greater than or - equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but - `1.2.4-beta.2` would not, because it is a prerelease of a - different `[major, minor, patch]` tuple. - -#### Caret Ranges `^1.2.3` `^0.2.5` `^0.0.4` - -Allows changes that do not modify the left-most non-zero digit in the -`[major, minor, patch]` tuple. In other words, this allows patch and -minor updates for versions `1.0.0` and above, patch updates for -versions `0.X >=0.1.0`, and *no* updates for versions `0.0.X`. - -Many authors treat a `0.x` version as if the `x` were the major -"breaking-change" indicator. - -Caret ranges are ideal when an author may make breaking changes -between `0.2.4` and `0.3.0` releases, which is a common practice. -However, it presumes that there will *not* be breaking changes between -`0.2.4` and `0.2.5`. It allows for changes that are presumed to be -additive (but non-breaking), according to commonly observed practices. - -* `^1.2.3` := `>=1.2.3 <2.0.0` -* `^0.2.3` := `>=0.2.3 <0.3.0` -* `^0.0.3` := `>=0.0.3 <0.0.4` -* `^1.2.3-beta.2` := `>=1.2.3-beta.2 <2.0.0` Note that prereleases in - the `1.2.3` version will be allowed, if they are greater than or - equal to `beta.2`. So, `1.2.3-beta.4` would be allowed, but - `1.2.4-beta.2` would not, because it is a prerelease of a - different `[major, minor, patch]` tuple. -* `^0.0.3-beta` := `>=0.0.3-beta <0.0.4` Note that prereleases in the - `0.0.3` version *only* will be allowed, if they are greater than or - equal to `beta`. So, `0.0.3-pr.2` would be allowed. - -When parsing caret ranges, a missing `patch` value desugars to the -number `0`, but will allow flexibility within that value, even if the -major and minor versions are both `0`. - -* `^1.2.x` := `>=1.2.0 <2.0.0` -* `^0.0.x` := `>=0.0.0 <0.1.0` -* `^0.0` := `>=0.0.0 <0.1.0` - -A missing `minor` and `patch` values will desugar to zero, but also -allow flexibility within those values, even if the major version is -zero. - -* `^1.x` := `>=1.0.0 <2.0.0` -* `^0.x` := `>=0.0.0 <1.0.0` - -### Range Grammar - -Putting all this together, here is a Backus-Naur grammar for ranges, -for the benefit of parser authors: - -```bnf -range-set ::= range ( logical-or range ) * -logical-or ::= ( ' ' ) * '||' ( ' ' ) * -range ::= hyphen | simple ( ' ' simple ) * | '' -hyphen ::= partial ' - ' partial -simple ::= primitive | partial | tilde | caret -primitive ::= ( '<' | '>' | '>=' | '<=' | '=' | ) partial -partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? -xr ::= 'x' | 'X' | '*' | nr -nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) * -tilde ::= '~' partial -caret ::= '^' partial -qualifier ::= ( '-' pre )? ( '+' build )? -pre ::= parts -build ::= parts -parts ::= part ( '.' part ) * -part ::= nr | [-0-9A-Za-z]+ -``` - -## Functions - -All methods and classes take a final `loose` boolean argument that, if -true, will be more forgiving about not-quite-valid semver strings. -The resulting output will always be 100% strict, of course. - -Strict-mode Comparators and Ranges will be strict about the SemVer -strings that they parse. - -* `valid(v)`: Return the parsed version, or null if it's not valid. -* `inc(v, release)`: Return the version incremented by the release - type (`major`, `premajor`, `minor`, `preminor`, `patch`, - `prepatch`, or `prerelease`), or null if it's not valid - * `premajor` in one call will bump the version up to the next major - version and down to a prerelease of that major version. - `preminor`, and `prepatch` work the same way. - * If called from a non-prerelease version, the `prerelease` will work the - same as `prepatch`. It increments the patch version, then makes a - prerelease. If the input version is already a prerelease it simply - increments it. -* `prerelease(v)`: Returns an array of prerelease components, or null - if none exist. Example: `prerelease('1.2.3-alpha.1') -> ['alpha', 1]` -* `major(v)`: Return the major version number. -* `minor(v)`: Return the minor version number. -* `patch(v)`: Return the patch version number. - -### Comparison - -* `gt(v1, v2)`: `v1 > v2` -* `gte(v1, v2)`: `v1 >= v2` -* `lt(v1, v2)`: `v1 < v2` -* `lte(v1, v2)`: `v1 <= v2` -* `eq(v1, v2)`: `v1 == v2` This is true if they're logically equivalent, - even if they're not the exact same string. You already know how to - compare strings. -* `neq(v1, v2)`: `v1 != v2` The opposite of `eq`. -* `cmp(v1, comparator, v2)`: Pass in a comparison string, and it'll call - the corresponding function above. `"==="` and `"!=="` do simple - string comparison, but are included for completeness. Throws if an - invalid comparison string is provided. -* `compare(v1, v2)`: Return `0` if `v1 == v2`, or `1` if `v1` is greater, or `-1` if - `v2` is greater. Sorts in ascending order if passed to `Array.sort()`. -* `rcompare(v1, v2)`: The reverse of compare. Sorts an array of versions - in descending order when passed to `Array.sort()`. -* `diff(v1, v2)`: Returns difference between two versions by the release type - (`major`, `premajor`, `minor`, `preminor`, `patch`, `prepatch`, or `prerelease`), - or null if the versions are the same. - - -### Ranges - -* `validRange(range)`: Return the valid range or null if it's not valid -* `satisfies(version, range)`: Return true if the version satisfies the - range. -* `maxSatisfying(versions, range)`: Return the highest version in the list - that satisfies the range, or `null` if none of them do. -* `minSatisfying(versions, range)`: Return the lowest version in the list - that satisfies the range, or `null` if none of them do. -* `gtr(version, range)`: Return `true` if version is greater than all the - versions possible in the range. -* `ltr(version, range)`: Return `true` if version is less than all the - versions possible in the range. -* `outside(version, range, hilo)`: Return true if the version is outside - the bounds of the range in either the high or low direction. The - `hilo` argument must be either the string `'>'` or `'<'`. (This is - the function called by `gtr` and `ltr`.) - -Note that, since ranges may be non-contiguous, a version might not be -greater than a range, less than a range, *or* satisfy a range! For -example, the range `1.2 <1.2.9 || >2.0.0` would have a hole from `1.2.9` -until `2.0.0`, so the version `1.2.10` would not be greater than the -range (because `2.0.1` satisfies, which is higher), nor less than the -range (since `1.2.8` satisfies, which is lower), and it also does not -satisfy the range. - -If you want to know if a version satisfies or does not satisfy a -range, use the `satisfies(version, range)` function. diff --git a/node_modules/npm-lifecycle/node_modules/semver/bin/semver b/node_modules/npm-lifecycle/node_modules/semver/bin/semver deleted file mode 100755 index c5f2e857e8279..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/semver/bin/semver +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env node -// Standalone semver comparison program. -// Exits successfully and prints matching version(s) if -// any supplied version is valid and passes all tests. - -var argv = process.argv.slice(2) - , versions = [] - , range = [] - , gt = [] - , lt = [] - , eq = [] - , inc = null - , version = require("../package.json").version - , loose = false - , identifier = undefined - , semver = require("../semver") - , reverse = false - -main() - -function main () { - if (!argv.length) return help() - while (argv.length) { - var a = argv.shift() - var i = a.indexOf('=') - if (i !== -1) { - a = a.slice(0, i) - argv.unshift(a.slice(i + 1)) - } - switch (a) { - case "-rv": case "-rev": case "--rev": case "--reverse": - reverse = true - break - case "-l": case "--loose": - loose = true - break - case "-v": case "--version": - versions.push(argv.shift()) - break - case "-i": case "--inc": case "--increment": - switch (argv[0]) { - case "major": case "minor": case "patch": case "prerelease": - case "premajor": case "preminor": case "prepatch": - inc = argv.shift() - break - default: - inc = "patch" - break - } - break - case "--preid": - identifier = argv.shift() - break - case "-r": case "--range": - range.push(argv.shift()) - break - case "-h": case "--help": case "-?": - return help() - default: - versions.push(a) - break - } - } - - versions = versions.filter(function (v) { - return semver.valid(v, loose) - }) - if (!versions.length) return fail() - if (inc && (versions.length !== 1 || range.length)) - return failInc() - - for (var i = 0, l = range.length; i < l ; i ++) { - versions = versions.filter(function (v) { - return semver.satisfies(v, range[i], loose) - }) - if (!versions.length) return fail() - } - return success(versions) -} - -function failInc () { - console.error("--inc can only be used on a single version with no range") - fail() -} - -function fail () { process.exit(1) } - -function success () { - var compare = reverse ? "rcompare" : "compare" - versions.sort(function (a, b) { - return semver[compare](a, b, loose) - }).map(function (v) { - return semver.clean(v, loose) - }).map(function (v) { - return inc ? semver.inc(v, inc, loose, identifier) : v - }).forEach(function (v,i,_) { console.log(v) }) -} - -function help () { - console.log(["SemVer " + version - ,"" - ,"A JavaScript implementation of the http://semver.org/ specification" - ,"Copyright Isaac Z. Schlueter" - ,"" - ,"Usage: semver [options] [ [...]]" - ,"Prints valid versions sorted by SemVer precedence" - ,"" - ,"Options:" - ,"-r --range " - ," Print versions that match the specified range." - ,"" - ,"-i --increment []" - ," Increment a version by the specified level. Level can" - ," be one of: major, minor, patch, premajor, preminor," - ," prepatch, or prerelease. Default level is 'patch'." - ," Only one version may be specified." - ,"" - ,"--preid " - ," Identifier to be used to prefix premajor, preminor," - ," prepatch or prerelease version increments." - ,"" - ,"-l --loose" - ," Interpret versions and ranges loosely" - ,"" - ,"Program exits successfully if any valid version satisfies" - ,"all supplied ranges, and prints all satisfying versions." - ,"" - ,"If no satisfying versions are found, then exits failure." - ,"" - ,"Versions are printed in ascending order, so supplying" - ,"multiple versions to the utility will just sort them." - ].join("\n")) -} diff --git a/node_modules/npm-lifecycle/node_modules/semver/package.json b/node_modules/npm-lifecycle/node_modules/semver/package.json deleted file mode 100644 index 15592dc76bd93..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/semver/package.json +++ /dev/null @@ -1,54 +0,0 @@ -{ - "_from": "semver@~5.3.0", - "_id": "semver@5.3.0", - "_inBundle": false, - "_integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=", - "_location": "/npm-lifecycle/semver", - "_phantomChildren": {}, - "_requested": { - "type": "range", - "registry": true, - "raw": "semver@~5.3.0", - "name": "semver", - "escapedName": "semver", - "rawSpec": "~5.3.0", - "saveSpec": null, - "fetchSpec": "~5.3.0" - }, - "_requiredBy": [ - "/npm-lifecycle/node-gyp" - ], - "_resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "_shasum": "9b2ce5d3de02d17c6012ad326aa6b4d0cf54f94f", - "_spec": "semver@~5.3.0", - "_where": "/home/hugh/Development/github.com/npm/cli/node_modules/npm-lifecycle/node_modules/node-gyp", - "bin": { - "semver": "./bin/semver" - }, - "bugs": { - "url": "https://github.com/npm/node-semver/issues" - }, - "bundleDependencies": false, - "deprecated": false, - "description": "The semantic version parser used by npm.", - "devDependencies": { - "tap": "^2.0.0" - }, - "files": [ - "bin", - "range.bnf", - "semver.js" - ], - "homepage": "https://github.com/npm/node-semver#readme", - "license": "ISC", - "main": "semver.js", - "name": "semver", - "repository": { - "type": "git", - "url": "git+https://github.com/npm/node-semver.git" - }, - "scripts": { - "test": "tap test/*.js" - }, - "version": "5.3.0" -} diff --git a/node_modules/npm-lifecycle/node_modules/semver/range.bnf b/node_modules/npm-lifecycle/node_modules/semver/range.bnf deleted file mode 100644 index 25ebd5c832548..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/semver/range.bnf +++ /dev/null @@ -1,16 +0,0 @@ -range-set ::= range ( logical-or range ) * -logical-or ::= ( ' ' ) * '||' ( ' ' ) * -range ::= hyphen | simple ( ' ' simple ) * | '' -hyphen ::= partial ' - ' partial -simple ::= primitive | partial | tilde | caret -primitive ::= ( '<' | '>' | '>=' | '<=' | '=' | ) partial -partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? -xr ::= 'x' | 'X' | '*' | nr -nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) * -tilde ::= '~' partial -caret ::= '^' partial -qualifier ::= ( '-' pre )? ( '+' build )? -pre ::= parts -build ::= parts -parts ::= part ( '.' part ) * -part ::= nr | [-0-9A-Za-z]+ diff --git a/node_modules/npm-lifecycle/node_modules/semver/semver.js b/node_modules/npm-lifecycle/node_modules/semver/semver.js deleted file mode 100644 index 5f1a3c5c9e5dc..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/semver/semver.js +++ /dev/null @@ -1,1203 +0,0 @@ -exports = module.exports = SemVer; - -// The debug function is excluded entirely from the minified version. -/* nomin */ var debug; -/* nomin */ if (typeof process === 'object' && - /* nomin */ process.env && - /* nomin */ process.env.NODE_DEBUG && - /* nomin */ /\bsemver\b/i.test(process.env.NODE_DEBUG)) - /* nomin */ debug = function() { - /* nomin */ var args = Array.prototype.slice.call(arguments, 0); - /* nomin */ args.unshift('SEMVER'); - /* nomin */ console.log.apply(console, args); - /* nomin */ }; -/* nomin */ else - /* nomin */ debug = function() {}; - -// Note: this is the semver.org version of the spec that it implements -// Not necessarily the package version of this code. -exports.SEMVER_SPEC_VERSION = '2.0.0'; - -var MAX_LENGTH = 256; -var MAX_SAFE_INTEGER = Number.MAX_SAFE_INTEGER || 9007199254740991; - -// The actual regexps go on exports.re -var re = exports.re = []; -var src = exports.src = []; -var R = 0; - -// The following Regular Expressions can be used for tokenizing, -// validating, and parsing SemVer version strings. - -// ## Numeric Identifier -// A single `0`, or a non-zero digit followed by zero or more digits. - -var NUMERICIDENTIFIER = R++; -src[NUMERICIDENTIFIER] = '0|[1-9]\\d*'; -var NUMERICIDENTIFIERLOOSE = R++; -src[NUMERICIDENTIFIERLOOSE] = '[0-9]+'; - - -// ## Non-numeric Identifier -// Zero or more digits, followed by a letter or hyphen, and then zero or -// more letters, digits, or hyphens. - -var NONNUMERICIDENTIFIER = R++; -src[NONNUMERICIDENTIFIER] = '\\d*[a-zA-Z-][a-zA-Z0-9-]*'; - - -// ## Main Version -// Three dot-separated numeric identifiers. - -var MAINVERSION = R++; -src[MAINVERSION] = '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')\\.' + - '(' + src[NUMERICIDENTIFIER] + ')'; - -var MAINVERSIONLOOSE = R++; -src[MAINVERSIONLOOSE] = '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')\\.' + - '(' + src[NUMERICIDENTIFIERLOOSE] + ')'; - -// ## Pre-release Version Identifier -// A numeric identifier, or a non-numeric identifier. - -var PRERELEASEIDENTIFIER = R++; -src[PRERELEASEIDENTIFIER] = '(?:' + src[NUMERICIDENTIFIER] + - '|' + src[NONNUMERICIDENTIFIER] + ')'; - -var PRERELEASEIDENTIFIERLOOSE = R++; -src[PRERELEASEIDENTIFIERLOOSE] = '(?:' + src[NUMERICIDENTIFIERLOOSE] + - '|' + src[NONNUMERICIDENTIFIER] + ')'; - - -// ## Pre-release Version -// Hyphen, followed by one or more dot-separated pre-release version -// identifiers. - -var PRERELEASE = R++; -src[PRERELEASE] = '(?:-(' + src[PRERELEASEIDENTIFIER] + - '(?:\\.' + src[PRERELEASEIDENTIFIER] + ')*))'; - -var PRERELEASELOOSE = R++; -src[PRERELEASELOOSE] = '(?:-?(' + src[PRERELEASEIDENTIFIERLOOSE] + - '(?:\\.' + src[PRERELEASEIDENTIFIERLOOSE] + ')*))'; - -// ## Build Metadata Identifier -// Any combination of digits, letters, or hyphens. - -var BUILDIDENTIFIER = R++; -src[BUILDIDENTIFIER] = '[0-9A-Za-z-]+'; - -// ## Build Metadata -// Plus sign, followed by one or more period-separated build metadata -// identifiers. - -var BUILD = R++; -src[BUILD] = '(?:\\+(' + src[BUILDIDENTIFIER] + - '(?:\\.' + src[BUILDIDENTIFIER] + ')*))'; - - -// ## Full Version String -// A main version, followed optionally by a pre-release version and -// build metadata. - -// Note that the only major, minor, patch, and pre-release sections of -// the version string are capturing groups. The build metadata is not a -// capturing group, because it should not ever be used in version -// comparison. - -var FULL = R++; -var FULLPLAIN = 'v?' + src[MAINVERSION] + - src[PRERELEASE] + '?' + - src[BUILD] + '?'; - -src[FULL] = '^' + FULLPLAIN + '$'; - -// like full, but allows v1.2.3 and =1.2.3, which people do sometimes. -// also, 1.0.0alpha1 (prerelease without the hyphen) which is pretty -// common in the npm registry. -var LOOSEPLAIN = '[v=\\s]*' + src[MAINVERSIONLOOSE] + - src[PRERELEASELOOSE] + '?' + - src[BUILD] + '?'; - -var LOOSE = R++; -src[LOOSE] = '^' + LOOSEPLAIN + '$'; - -var GTLT = R++; -src[GTLT] = '((?:<|>)?=?)'; - -// Something like "2.*" or "1.2.x". -// Note that "x.x" is a valid xRange identifer, meaning "any version" -// Only the first item is strictly required. -var XRANGEIDENTIFIERLOOSE = R++; -src[XRANGEIDENTIFIERLOOSE] = src[NUMERICIDENTIFIERLOOSE] + '|x|X|\\*'; -var XRANGEIDENTIFIER = R++; -src[XRANGEIDENTIFIER] = src[NUMERICIDENTIFIER] + '|x|X|\\*'; - -var XRANGEPLAIN = R++; -src[XRANGEPLAIN] = '[v=\\s]*(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIER] + ')' + - '(?:' + src[PRERELEASE] + ')?' + - src[BUILD] + '?' + - ')?)?'; - -var XRANGEPLAINLOOSE = R++; -src[XRANGEPLAINLOOSE] = '[v=\\s]*(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:\\.(' + src[XRANGEIDENTIFIERLOOSE] + ')' + - '(?:' + src[PRERELEASELOOSE] + ')?' + - src[BUILD] + '?' + - ')?)?'; - -var XRANGE = R++; -src[XRANGE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAIN] + '$'; -var XRANGELOOSE = R++; -src[XRANGELOOSE] = '^' + src[GTLT] + '\\s*' + src[XRANGEPLAINLOOSE] + '$'; - -// Tilde ranges. -// Meaning is "reasonably at or greater than" -var LONETILDE = R++; -src[LONETILDE] = '(?:~>?)'; - -var TILDETRIM = R++; -src[TILDETRIM] = '(\\s*)' + src[LONETILDE] + '\\s+'; -re[TILDETRIM] = new RegExp(src[TILDETRIM], 'g'); -var tildeTrimReplace = '$1~'; - -var TILDE = R++; -src[TILDE] = '^' + src[LONETILDE] + src[XRANGEPLAIN] + '$'; -var TILDELOOSE = R++; -src[TILDELOOSE] = '^' + src[LONETILDE] + src[XRANGEPLAINLOOSE] + '$'; - -// Caret ranges. -// Meaning is "at least and backwards compatible with" -var LONECARET = R++; -src[LONECARET] = '(?:\\^)'; - -var CARETTRIM = R++; -src[CARETTRIM] = '(\\s*)' + src[LONECARET] + '\\s+'; -re[CARETTRIM] = new RegExp(src[CARETTRIM], 'g'); -var caretTrimReplace = '$1^'; - -var CARET = R++; -src[CARET] = '^' + src[LONECARET] + src[XRANGEPLAIN] + '$'; -var CARETLOOSE = R++; -src[CARETLOOSE] = '^' + src[LONECARET] + src[XRANGEPLAINLOOSE] + '$'; - -// A simple gt/lt/eq thing, or just "" to indicate "any version" -var COMPARATORLOOSE = R++; -src[COMPARATORLOOSE] = '^' + src[GTLT] + '\\s*(' + LOOSEPLAIN + ')$|^$'; -var COMPARATOR = R++; -src[COMPARATOR] = '^' + src[GTLT] + '\\s*(' + FULLPLAIN + ')$|^$'; - - -// An expression to strip any whitespace between the gtlt and the thing -// it modifies, so that `> 1.2.3` ==> `>1.2.3` -var COMPARATORTRIM = R++; -src[COMPARATORTRIM] = '(\\s*)' + src[GTLT] + - '\\s*(' + LOOSEPLAIN + '|' + src[XRANGEPLAIN] + ')'; - -// this one has to use the /g flag -re[COMPARATORTRIM] = new RegExp(src[COMPARATORTRIM], 'g'); -var comparatorTrimReplace = '$1$2$3'; - - -// Something like `1.2.3 - 1.2.4` -// Note that these all use the loose form, because they'll be -// checked against either the strict or loose comparator form -// later. -var HYPHENRANGE = R++; -src[HYPHENRANGE] = '^\\s*(' + src[XRANGEPLAIN] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAIN] + ')' + - '\\s*$'; - -var HYPHENRANGELOOSE = R++; -src[HYPHENRANGELOOSE] = '^\\s*(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s+-\\s+' + - '(' + src[XRANGEPLAINLOOSE] + ')' + - '\\s*$'; - -// Star ranges basically just allow anything at all. -var STAR = R++; -src[STAR] = '(<|>)?=?\\s*\\*'; - -// Compile to actual regexp objects. -// All are flag-free, unless they were created above with a flag. -for (var i = 0; i < R; i++) { - debug(i, src[i]); - if (!re[i]) - re[i] = new RegExp(src[i]); -} - -exports.parse = parse; -function parse(version, loose) { - if (version instanceof SemVer) - return version; - - if (typeof version !== 'string') - return null; - - if (version.length > MAX_LENGTH) - return null; - - var r = loose ? re[LOOSE] : re[FULL]; - if (!r.test(version)) - return null; - - try { - return new SemVer(version, loose); - } catch (er) { - return null; - } -} - -exports.valid = valid; -function valid(version, loose) { - var v = parse(version, loose); - return v ? v.version : null; -} - - -exports.clean = clean; -function clean(version, loose) { - var s = parse(version.trim().replace(/^[=v]+/, ''), loose); - return s ? s.version : null; -} - -exports.SemVer = SemVer; - -function SemVer(version, loose) { - if (version instanceof SemVer) { - if (version.loose === loose) - return version; - else - version = version.version; - } else if (typeof version !== 'string') { - throw new TypeError('Invalid Version: ' + version); - } - - if (version.length > MAX_LENGTH) - throw new TypeError('version is longer than ' + MAX_LENGTH + ' characters') - - if (!(this instanceof SemVer)) - return new SemVer(version, loose); - - debug('SemVer', version, loose); - this.loose = loose; - var m = version.trim().match(loose ? re[LOOSE] : re[FULL]); - - if (!m) - throw new TypeError('Invalid Version: ' + version); - - this.raw = version; - - // these are actually numbers - this.major = +m[1]; - this.minor = +m[2]; - this.patch = +m[3]; - - if (this.major > MAX_SAFE_INTEGER || this.major < 0) - throw new TypeError('Invalid major version') - - if (this.minor > MAX_SAFE_INTEGER || this.minor < 0) - throw new TypeError('Invalid minor version') - - if (this.patch > MAX_SAFE_INTEGER || this.patch < 0) - throw new TypeError('Invalid patch version') - - // numberify any prerelease numeric ids - if (!m[4]) - this.prerelease = []; - else - this.prerelease = m[4].split('.').map(function(id) { - if (/^[0-9]+$/.test(id)) { - var num = +id; - if (num >= 0 && num < MAX_SAFE_INTEGER) - return num; - } - return id; - }); - - this.build = m[5] ? m[5].split('.') : []; - this.format(); -} - -SemVer.prototype.format = function() { - this.version = this.major + '.' + this.minor + '.' + this.patch; - if (this.prerelease.length) - this.version += '-' + this.prerelease.join('.'); - return this.version; -}; - -SemVer.prototype.toString = function() { - return this.version; -}; - -SemVer.prototype.compare = function(other) { - debug('SemVer.compare', this.version, this.loose, other); - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); - - return this.compareMain(other) || this.comparePre(other); -}; - -SemVer.prototype.compareMain = function(other) { - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); - - return compareIdentifiers(this.major, other.major) || - compareIdentifiers(this.minor, other.minor) || - compareIdentifiers(this.patch, other.patch); -}; - -SemVer.prototype.comparePre = function(other) { - if (!(other instanceof SemVer)) - other = new SemVer(other, this.loose); - - // NOT having a prerelease is > having one - if (this.prerelease.length && !other.prerelease.length) - return -1; - else if (!this.prerelease.length && other.prerelease.length) - return 1; - else if (!this.prerelease.length && !other.prerelease.length) - return 0; - - var i = 0; - do { - var a = this.prerelease[i]; - var b = other.prerelease[i]; - debug('prerelease compare', i, a, b); - if (a === undefined && b === undefined) - return 0; - else if (b === undefined) - return 1; - else if (a === undefined) - return -1; - else if (a === b) - continue; - else - return compareIdentifiers(a, b); - } while (++i); -}; - -// preminor will bump the version up to the next minor release, and immediately -// down to pre-release. premajor and prepatch work the same way. -SemVer.prototype.inc = function(release, identifier) { - switch (release) { - case 'premajor': - this.prerelease.length = 0; - this.patch = 0; - this.minor = 0; - this.major++; - this.inc('pre', identifier); - break; - case 'preminor': - this.prerelease.length = 0; - this.patch = 0; - this.minor++; - this.inc('pre', identifier); - break; - case 'prepatch': - // If this is already a prerelease, it will bump to the next version - // drop any prereleases that might already exist, since they are not - // relevant at this point. - this.prerelease.length = 0; - this.inc('patch', identifier); - this.inc('pre', identifier); - break; - // If the input is a non-prerelease version, this acts the same as - // prepatch. - case 'prerelease': - if (this.prerelease.length === 0) - this.inc('patch', identifier); - this.inc('pre', identifier); - break; - - case 'major': - // If this is a pre-major version, bump up to the same major version. - // Otherwise increment major. - // 1.0.0-5 bumps to 1.0.0 - // 1.1.0 bumps to 2.0.0 - if (this.minor !== 0 || this.patch !== 0 || this.prerelease.length === 0) - this.major++; - this.minor = 0; - this.patch = 0; - this.prerelease = []; - break; - case 'minor': - // If this is a pre-minor version, bump up to the same minor version. - // Otherwise increment minor. - // 1.2.0-5 bumps to 1.2.0 - // 1.2.1 bumps to 1.3.0 - if (this.patch !== 0 || this.prerelease.length === 0) - this.minor++; - this.patch = 0; - this.prerelease = []; - break; - case 'patch': - // If this is not a pre-release version, it will increment the patch. - // If it is a pre-release it will bump up to the same patch version. - // 1.2.0-5 patches to 1.2.0 - // 1.2.0 patches to 1.2.1 - if (this.prerelease.length === 0) - this.patch++; - this.prerelease = []; - break; - // This probably shouldn't be used publicly. - // 1.0.0 "pre" would become 1.0.0-0 which is the wrong direction. - case 'pre': - if (this.prerelease.length === 0) - this.prerelease = [0]; - else { - var i = this.prerelease.length; - while (--i >= 0) { - if (typeof this.prerelease[i] === 'number') { - this.prerelease[i]++; - i = -2; - } - } - if (i === -1) // didn't increment anything - this.prerelease.push(0); - } - if (identifier) { - // 1.2.0-beta.1 bumps to 1.2.0-beta.2, - // 1.2.0-beta.fooblz or 1.2.0-beta bumps to 1.2.0-beta.0 - if (this.prerelease[0] === identifier) { - if (isNaN(this.prerelease[1])) - this.prerelease = [identifier, 0]; - } else - this.prerelease = [identifier, 0]; - } - break; - - default: - throw new Error('invalid increment argument: ' + release); - } - this.format(); - this.raw = this.version; - return this; -}; - -exports.inc = inc; -function inc(version, release, loose, identifier) { - if (typeof(loose) === 'string') { - identifier = loose; - loose = undefined; - } - - try { - return new SemVer(version, loose).inc(release, identifier).version; - } catch (er) { - return null; - } -} - -exports.diff = diff; -function diff(version1, version2) { - if (eq(version1, version2)) { - return null; - } else { - var v1 = parse(version1); - var v2 = parse(version2); - if (v1.prerelease.length || v2.prerelease.length) { - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return 'pre'+key; - } - } - } - return 'prerelease'; - } - for (var key in v1) { - if (key === 'major' || key === 'minor' || key === 'patch') { - if (v1[key] !== v2[key]) { - return key; - } - } - } - } -} - -exports.compareIdentifiers = compareIdentifiers; - -var numeric = /^[0-9]+$/; -function compareIdentifiers(a, b) { - var anum = numeric.test(a); - var bnum = numeric.test(b); - - if (anum && bnum) { - a = +a; - b = +b; - } - - return (anum && !bnum) ? -1 : - (bnum && !anum) ? 1 : - a < b ? -1 : - a > b ? 1 : - 0; -} - -exports.rcompareIdentifiers = rcompareIdentifiers; -function rcompareIdentifiers(a, b) { - return compareIdentifiers(b, a); -} - -exports.major = major; -function major(a, loose) { - return new SemVer(a, loose).major; -} - -exports.minor = minor; -function minor(a, loose) { - return new SemVer(a, loose).minor; -} - -exports.patch = patch; -function patch(a, loose) { - return new SemVer(a, loose).patch; -} - -exports.compare = compare; -function compare(a, b, loose) { - return new SemVer(a, loose).compare(b); -} - -exports.compareLoose = compareLoose; -function compareLoose(a, b) { - return compare(a, b, true); -} - -exports.rcompare = rcompare; -function rcompare(a, b, loose) { - return compare(b, a, loose); -} - -exports.sort = sort; -function sort(list, loose) { - return list.sort(function(a, b) { - return exports.compare(a, b, loose); - }); -} - -exports.rsort = rsort; -function rsort(list, loose) { - return list.sort(function(a, b) { - return exports.rcompare(a, b, loose); - }); -} - -exports.gt = gt; -function gt(a, b, loose) { - return compare(a, b, loose) > 0; -} - -exports.lt = lt; -function lt(a, b, loose) { - return compare(a, b, loose) < 0; -} - -exports.eq = eq; -function eq(a, b, loose) { - return compare(a, b, loose) === 0; -} - -exports.neq = neq; -function neq(a, b, loose) { - return compare(a, b, loose) !== 0; -} - -exports.gte = gte; -function gte(a, b, loose) { - return compare(a, b, loose) >= 0; -} - -exports.lte = lte; -function lte(a, b, loose) { - return compare(a, b, loose) <= 0; -} - -exports.cmp = cmp; -function cmp(a, op, b, loose) { - var ret; - switch (op) { - case '===': - if (typeof a === 'object') a = a.version; - if (typeof b === 'object') b = b.version; - ret = a === b; - break; - case '!==': - if (typeof a === 'object') a = a.version; - if (typeof b === 'object') b = b.version; - ret = a !== b; - break; - case '': case '=': case '==': ret = eq(a, b, loose); break; - case '!=': ret = neq(a, b, loose); break; - case '>': ret = gt(a, b, loose); break; - case '>=': ret = gte(a, b, loose); break; - case '<': ret = lt(a, b, loose); break; - case '<=': ret = lte(a, b, loose); break; - default: throw new TypeError('Invalid operator: ' + op); - } - return ret; -} - -exports.Comparator = Comparator; -function Comparator(comp, loose) { - if (comp instanceof Comparator) { - if (comp.loose === loose) - return comp; - else - comp = comp.value; - } - - if (!(this instanceof Comparator)) - return new Comparator(comp, loose); - - debug('comparator', comp, loose); - this.loose = loose; - this.parse(comp); - - if (this.semver === ANY) - this.value = ''; - else - this.value = this.operator + this.semver.version; - - debug('comp', this); -} - -var ANY = {}; -Comparator.prototype.parse = function(comp) { - var r = this.loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; - var m = comp.match(r); - - if (!m) - throw new TypeError('Invalid comparator: ' + comp); - - this.operator = m[1]; - if (this.operator === '=') - this.operator = ''; - - // if it literally is just '>' or '' then allow anything. - if (!m[2]) - this.semver = ANY; - else - this.semver = new SemVer(m[2], this.loose); -}; - -Comparator.prototype.toString = function() { - return this.value; -}; - -Comparator.prototype.test = function(version) { - debug('Comparator.test', version, this.loose); - - if (this.semver === ANY) - return true; - - if (typeof version === 'string') - version = new SemVer(version, this.loose); - - return cmp(version, this.operator, this.semver, this.loose); -}; - - -exports.Range = Range; -function Range(range, loose) { - if ((range instanceof Range) && range.loose === loose) - return range; - - if (!(this instanceof Range)) - return new Range(range, loose); - - this.loose = loose; - - // First, split based on boolean or || - this.raw = range; - this.set = range.split(/\s*\|\|\s*/).map(function(range) { - return this.parseRange(range.trim()); - }, this).filter(function(c) { - // throw out any that are not relevant for whatever reason - return c.length; - }); - - if (!this.set.length) { - throw new TypeError('Invalid SemVer Range: ' + range); - } - - this.format(); -} - -Range.prototype.format = function() { - this.range = this.set.map(function(comps) { - return comps.join(' ').trim(); - }).join('||').trim(); - return this.range; -}; - -Range.prototype.toString = function() { - return this.range; -}; - -Range.prototype.parseRange = function(range) { - var loose = this.loose; - range = range.trim(); - debug('range', range, loose); - // `1.2.3 - 1.2.4` => `>=1.2.3 <=1.2.4` - var hr = loose ? re[HYPHENRANGELOOSE] : re[HYPHENRANGE]; - range = range.replace(hr, hyphenReplace); - debug('hyphen replace', range); - // `> 1.2.3 < 1.2.5` => `>1.2.3 <1.2.5` - range = range.replace(re[COMPARATORTRIM], comparatorTrimReplace); - debug('comparator trim', range, re[COMPARATORTRIM]); - - // `~ 1.2.3` => `~1.2.3` - range = range.replace(re[TILDETRIM], tildeTrimReplace); - - // `^ 1.2.3` => `^1.2.3` - range = range.replace(re[CARETTRIM], caretTrimReplace); - - // normalize spaces - range = range.split(/\s+/).join(' '); - - // At this point, the range is completely trimmed and - // ready to be split into comparators. - - var compRe = loose ? re[COMPARATORLOOSE] : re[COMPARATOR]; - var set = range.split(' ').map(function(comp) { - return parseComparator(comp, loose); - }).join(' ').split(/\s+/); - if (this.loose) { - // in loose mode, throw out any that are not valid comparators - set = set.filter(function(comp) { - return !!comp.match(compRe); - }); - } - set = set.map(function(comp) { - return new Comparator(comp, loose); - }); - - return set; -}; - -// Mostly just for testing and legacy API reasons -exports.toComparators = toComparators; -function toComparators(range, loose) { - return new Range(range, loose).set.map(function(comp) { - return comp.map(function(c) { - return c.value; - }).join(' ').trim().split(' '); - }); -} - -// comprised of xranges, tildes, stars, and gtlt's at this point. -// already replaced the hyphen ranges -// turn into a set of JUST comparators. -function parseComparator(comp, loose) { - debug('comp', comp); - comp = replaceCarets(comp, loose); - debug('caret', comp); - comp = replaceTildes(comp, loose); - debug('tildes', comp); - comp = replaceXRanges(comp, loose); - debug('xrange', comp); - comp = replaceStars(comp, loose); - debug('stars', comp); - return comp; -} - -function isX(id) { - return !id || id.toLowerCase() === 'x' || id === '*'; -} - -// ~, ~> --> * (any, kinda silly) -// ~2, ~2.x, ~2.x.x, ~>2, ~>2.x ~>2.x.x --> >=2.0.0 <3.0.0 -// ~2.0, ~2.0.x, ~>2.0, ~>2.0.x --> >=2.0.0 <2.1.0 -// ~1.2, ~1.2.x, ~>1.2, ~>1.2.x --> >=1.2.0 <1.3.0 -// ~1.2.3, ~>1.2.3 --> >=1.2.3 <1.3.0 -// ~1.2.0, ~>1.2.0 --> >=1.2.0 <1.3.0 -function replaceTildes(comp, loose) { - return comp.trim().split(/\s+/).map(function(comp) { - return replaceTilde(comp, loose); - }).join(' '); -} - -function replaceTilde(comp, loose) { - var r = loose ? re[TILDELOOSE] : re[TILDE]; - return comp.replace(r, function(_, M, m, p, pr) { - debug('tilde', comp, _, M, m, p, pr); - var ret; - - if (isX(M)) - ret = ''; - else if (isX(m)) - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - else if (isX(p)) - // ~1.2 == >=1.2.0 <1.3.0 - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - else if (pr) { - debug('replaceTilde pr', pr); - if (pr.charAt(0) !== '-') - pr = '-' + pr; - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - // ~1.2.3 == >=1.2.3 <1.3.0 - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0'; - - debug('tilde return', ret); - return ret; - }); -} - -// ^ --> * (any, kinda silly) -// ^2, ^2.x, ^2.x.x --> >=2.0.0 <3.0.0 -// ^2.0, ^2.0.x --> >=2.0.0 <3.0.0 -// ^1.2, ^1.2.x --> >=1.2.0 <2.0.0 -// ^1.2.3 --> >=1.2.3 <2.0.0 -// ^1.2.0 --> >=1.2.0 <2.0.0 -function replaceCarets(comp, loose) { - return comp.trim().split(/\s+/).map(function(comp) { - return replaceCaret(comp, loose); - }).join(' '); -} - -function replaceCaret(comp, loose) { - debug('caret', comp, loose); - var r = loose ? re[CARETLOOSE] : re[CARET]; - return comp.replace(r, function(_, M, m, p, pr) { - debug('caret', comp, _, M, m, p, pr); - var ret; - - if (isX(M)) - ret = ''; - else if (isX(m)) - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - else if (isX(p)) { - if (M === '0') - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - else - ret = '>=' + M + '.' + m + '.0 <' + (+M + 1) + '.0.0'; - } else if (pr) { - debug('replaceCaret pr', pr); - if (pr.charAt(0) !== '-') - pr = '-' + pr; - if (M === '0') { - if (m === '0') - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + m + '.' + (+p + 1); - else - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - ret = '>=' + M + '.' + m + '.' + p + pr + - ' <' + (+M + 1) + '.0.0'; - } else { - debug('no pr'); - if (M === '0') { - if (m === '0') - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + m + '.' + (+p + 1); - else - ret = '>=' + M + '.' + m + '.' + p + - ' <' + M + '.' + (+m + 1) + '.0'; - } else - ret = '>=' + M + '.' + m + '.' + p + - ' <' + (+M + 1) + '.0.0'; - } - - debug('caret return', ret); - return ret; - }); -} - -function replaceXRanges(comp, loose) { - debug('replaceXRanges', comp, loose); - return comp.split(/\s+/).map(function(comp) { - return replaceXRange(comp, loose); - }).join(' '); -} - -function replaceXRange(comp, loose) { - comp = comp.trim(); - var r = loose ? re[XRANGELOOSE] : re[XRANGE]; - return comp.replace(r, function(ret, gtlt, M, m, p, pr) { - debug('xRange', comp, ret, gtlt, M, m, p, pr); - var xM = isX(M); - var xm = xM || isX(m); - var xp = xm || isX(p); - var anyX = xp; - - if (gtlt === '=' && anyX) - gtlt = ''; - - if (xM) { - if (gtlt === '>' || gtlt === '<') { - // nothing is allowed - ret = '<0.0.0'; - } else { - // nothing is forbidden - ret = '*'; - } - } else if (gtlt && anyX) { - // replace X with 0 - if (xm) - m = 0; - if (xp) - p = 0; - - if (gtlt === '>') { - // >1 => >=2.0.0 - // >1.2 => >=1.3.0 - // >1.2.3 => >= 1.2.4 - gtlt = '>='; - if (xm) { - M = +M + 1; - m = 0; - p = 0; - } else if (xp) { - m = +m + 1; - p = 0; - } - } else if (gtlt === '<=') { - // <=0.7.x is actually <0.8.0, since any 0.7.x should - // pass. Similarly, <=7.x is actually <8.0.0, etc. - gtlt = '<'; - if (xm) - M = +M + 1; - else - m = +m + 1; - } - - ret = gtlt + M + '.' + m + '.' + p; - } else if (xm) { - ret = '>=' + M + '.0.0 <' + (+M + 1) + '.0.0'; - } else if (xp) { - ret = '>=' + M + '.' + m + '.0 <' + M + '.' + (+m + 1) + '.0'; - } - - debug('xRange return', ret); - - return ret; - }); -} - -// Because * is AND-ed with everything else in the comparator, -// and '' means "any version", just remove the *s entirely. -function replaceStars(comp, loose) { - debug('replaceStars', comp, loose); - // Looseness is ignored here. star is always as loose as it gets! - return comp.trim().replace(re[STAR], ''); -} - -// This function is passed to string.replace(re[HYPHENRANGE]) -// M, m, patch, prerelease, build -// 1.2 - 3.4.5 => >=1.2.0 <=3.4.5 -// 1.2.3 - 3.4 => >=1.2.0 <3.5.0 Any 3.4.x will do -// 1.2 - 3.4 => >=1.2.0 <3.5.0 -function hyphenReplace($0, - from, fM, fm, fp, fpr, fb, - to, tM, tm, tp, tpr, tb) { - - if (isX(fM)) - from = ''; - else if (isX(fm)) - from = '>=' + fM + '.0.0'; - else if (isX(fp)) - from = '>=' + fM + '.' + fm + '.0'; - else - from = '>=' + from; - - if (isX(tM)) - to = ''; - else if (isX(tm)) - to = '<' + (+tM + 1) + '.0.0'; - else if (isX(tp)) - to = '<' + tM + '.' + (+tm + 1) + '.0'; - else if (tpr) - to = '<=' + tM + '.' + tm + '.' + tp + '-' + tpr; - else - to = '<=' + to; - - return (from + ' ' + to).trim(); -} - - -// if ANY of the sets match ALL of its comparators, then pass -Range.prototype.test = function(version) { - if (!version) - return false; - - if (typeof version === 'string') - version = new SemVer(version, this.loose); - - for (var i = 0; i < this.set.length; i++) { - if (testSet(this.set[i], version)) - return true; - } - return false; -}; - -function testSet(set, version) { - for (var i = 0; i < set.length; i++) { - if (!set[i].test(version)) - return false; - } - - if (version.prerelease.length) { - // Find the set of versions that are allowed to have prereleases - // For example, ^1.2.3-pr.1 desugars to >=1.2.3-pr.1 <2.0.0 - // That should allow `1.2.3-pr.2` to pass. - // However, `1.2.4-alpha.notready` should NOT be allowed, - // even though it's within the range set by the comparators. - for (var i = 0; i < set.length; i++) { - debug(set[i].semver); - if (set[i].semver === ANY) - continue; - - if (set[i].semver.prerelease.length > 0) { - var allowed = set[i].semver; - if (allowed.major === version.major && - allowed.minor === version.minor && - allowed.patch === version.patch) - return true; - } - } - - // Version has a -pre, but it's not one of the ones we like. - return false; - } - - return true; -} - -exports.satisfies = satisfies; -function satisfies(version, range, loose) { - try { - range = new Range(range, loose); - } catch (er) { - return false; - } - return range.test(version); -} - -exports.maxSatisfying = maxSatisfying; -function maxSatisfying(versions, range, loose) { - return versions.filter(function(version) { - return satisfies(version, range, loose); - }).sort(function(a, b) { - return rcompare(a, b, loose); - })[0] || null; -} - -exports.minSatisfying = minSatisfying; -function minSatisfying(versions, range, loose) { - return versions.filter(function(version) { - return satisfies(version, range, loose); - }).sort(function(a, b) { - return compare(a, b, loose); - })[0] || null; -} - -exports.validRange = validRange; -function validRange(range, loose) { - try { - // Return '*' instead of '' so that truthiness works. - // This will throw if it's invalid anyway - return new Range(range, loose).range || '*'; - } catch (er) { - return null; - } -} - -// Determine if version is less than all the versions possible in the range -exports.ltr = ltr; -function ltr(version, range, loose) { - return outside(version, range, '<', loose); -} - -// Determine if version is greater than all the versions possible in the range. -exports.gtr = gtr; -function gtr(version, range, loose) { - return outside(version, range, '>', loose); -} - -exports.outside = outside; -function outside(version, range, hilo, loose) { - version = new SemVer(version, loose); - range = new Range(range, loose); - - var gtfn, ltefn, ltfn, comp, ecomp; - switch (hilo) { - case '>': - gtfn = gt; - ltefn = lte; - ltfn = lt; - comp = '>'; - ecomp = '>='; - break; - case '<': - gtfn = lt; - ltefn = gte; - ltfn = gt; - comp = '<'; - ecomp = '<='; - break; - default: - throw new TypeError('Must provide a hilo val of "<" or ">"'); - } - - // If it satisifes the range it is not outside - if (satisfies(version, range, loose)) { - return false; - } - - // From now on, variable terms are as if we're in "gtr" mode. - // but note that everything is flipped for the "ltr" function. - - for (var i = 0; i < range.set.length; ++i) { - var comparators = range.set[i]; - - var high = null; - var low = null; - - comparators.forEach(function(comparator) { - if (comparator.semver === ANY) { - comparator = new Comparator('>=0.0.0') - } - high = high || comparator; - low = low || comparator; - if (gtfn(comparator.semver, high.semver, loose)) { - high = comparator; - } else if (ltfn(comparator.semver, low.semver, loose)) { - low = comparator; - } - }); - - // If the edge version comparator has a operator then our version - // isn't outside it - if (high.operator === comp || high.operator === ecomp) { - return false; - } - - // If the lowest version comparator has an operator and our version - // is less than it then it isn't higher than the range - if ((!low.operator || low.operator === comp) && - ltefn(version, low.semver)) { - return false; - } else if (low.operator === ecomp && ltfn(version, low.semver)) { - return false; - } - } - return true; -} - -exports.prerelease = prerelease; -function prerelease(version, loose) { - var parsed = parse(version, loose); - return (parsed && parsed.prerelease.length) ? parsed.prerelease : null; -} diff --git a/node_modules/npm-lifecycle/node_modules/tar/.travis.yml b/node_modules/npm-lifecycle/node_modules/tar/.travis.yml deleted file mode 100644 index fca8ef019405d..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/.travis.yml +++ /dev/null @@ -1,4 +0,0 @@ -language: node_js -node_js: - - 0.10 - - 0.11 diff --git a/node_modules/npm-lifecycle/node_modules/tar/LICENSE b/node_modules/npm-lifecycle/node_modules/tar/LICENSE deleted file mode 100644 index 019b7e40ea056..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/LICENSE +++ /dev/null @@ -1,12 +0,0 @@ -The ISC License -Copyright (c) Isaac Z. Schlueter and Contributors -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/node_modules/npm-lifecycle/node_modules/tar/README.md b/node_modules/npm-lifecycle/node_modules/tar/README.md deleted file mode 100644 index cfda2ac180611..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# node-tar - -Tar for Node.js. - -[![NPM](https://nodei.co/npm/tar.png)](https://nodei.co/npm/tar/) - -## API - -See `examples/` for usage examples. - -### var tar = require('tar') - -Returns an object with `.Pack`, `.Extract` and `.Parse` methods. - -### tar.Pack([properties]) - -Returns a through stream. Use -[fstream](https://npmjs.org/package/fstream) to write files into the -pack stream and you will receive tar archive data from the pack -stream. - -This only works with directories, it does not work with individual files. - -The optional `properties` object are used to set properties in the tar -'Global Extended Header'. If the `fromBase` property is set to true, -the tar will contain files relative to the path passed, and not with -the path included. - -### tar.Extract([options]) - -Returns a through stream. Write tar data to the stream and the files -in the tarball will be extracted onto the filesystem. - -`options` can be: - -```js -{ - path: '/path/to/extract/tar/into', - strip: 0, // how many path segments to strip from the root when extracting -} -``` - -`options` also get passed to the `fstream.Writer` instance that `tar` -uses internally. - -### tar.Parse() - -Returns a writable stream. Write tar data to it and it will emit -`entry` events for each entry parsed from the tarball. This is used by -`tar.Extract`. diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/base.css b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/base.css deleted file mode 100644 index 417c7adc95f1d..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/base.css +++ /dev/null @@ -1,212 +0,0 @@ -body, html { - margin:0; padding: 0; - height: 100%; -} -body { - font-family: Helvetica Neue, Helvetica, Arial; - font-size: 14px; - color:#333; -} -.small { font-size: 12px; } -*, *:after, *:before { - -webkit-box-sizing:border-box; - -moz-box-sizing:border-box; - box-sizing:border-box; - } -h1 { font-size: 20px; margin: 0;} -h2 { font-size: 14px; } -pre { - font: 12px/1.4 Consolas, "Liberation Mono", Menlo, Courier, monospace; - margin: 0; - padding: 0; - -moz-tab-size: 2; - -o-tab-size: 2; - tab-size: 2; -} -a { color:#0074D9; text-decoration:none; } -a:hover { text-decoration:underline; } -.strong { font-weight: bold; } -.space-top1 { padding: 10px 0 0 0; } -.pad2y { padding: 20px 0; } -.pad1y { padding: 10px 0; } -.pad2x { padding: 0 20px; } -.pad2 { padding: 20px; } -.pad1 { padding: 10px; } -.space-left2 { padding-left:55px; } -.space-right2 { padding-right:20px; } -.center { text-align:center; } -.clearfix { display:block; } -.clearfix:after { - content:''; - display:block; - height:0; - clear:both; - visibility:hidden; - } -.fl { float: left; } -@media only screen and (max-width:640px) { - .col3 { width:100%; max-width:100%; } - .hide-mobile { display:none!important; } -} - -.quiet { - color: #7f7f7f; - color: rgba(0,0,0,0.5); -} -.quiet a { opacity: 0.7; } - -.fraction { - font-family: Consolas, 'Liberation Mono', Menlo, Courier, monospace; - font-size: 10px; - color: #555; - background: #E8E8E8; - padding: 4px 5px; - border-radius: 3px; - vertical-align: middle; -} - -div.path a:link, div.path a:visited { color: #333; } -table.coverage { - border-collapse: collapse; - margin: 10px 0 0 0; - padding: 0; -} - -table.coverage td { - margin: 0; - padding: 0; - vertical-align: top; -} -table.coverage td.line-count { - text-align: right; - padding: 0 5px 0 20px; -} -table.coverage td.line-coverage { - text-align: right; - padding-right: 10px; - min-width:20px; -} - -table.coverage td span.cline-any { - display: inline-block; - padding: 0 5px; - width: 100%; -} -.missing-if-branch { - display: inline-block; - margin-right: 5px; - border-radius: 3px; - position: relative; - padding: 0 4px; - background: #333; - color: yellow; -} - -.skip-if-branch { - display: none; - margin-right: 10px; - position: relative; - padding: 0 4px; - background: #ccc; - color: white; -} -.missing-if-branch .typ, .skip-if-branch .typ { - color: inherit !important; -} -.coverage-summary { - border-collapse: collapse; - width: 100%; -} -.coverage-summary tr { border-bottom: 1px solid #bbb; } -.keyline-all { border: 1px solid #ddd; } -.coverage-summary td, .coverage-summary th { padding: 10px; } -.coverage-summary tbody { border: 1px solid #bbb; } -.coverage-summary td { border-right: 1px solid #bbb; } -.coverage-summary td:last-child { border-right: none; } -.coverage-summary th { - text-align: left; - font-weight: normal; - white-space: nowrap; -} -.coverage-summary th.file { border-right: none !important; } -.coverage-summary th.pct { } -.coverage-summary th.pic, -.coverage-summary th.abs, -.coverage-summary td.pct, -.coverage-summary td.abs { text-align: right; } -.coverage-summary td.file { white-space: nowrap; } -.coverage-summary td.pic { min-width: 120px !important; } -.coverage-summary tfoot td { } - -.coverage-summary .sorter { - height: 10px; - width: 7px; - display: inline-block; - margin-left: 0.5em; - background: url(sort-arrow-sprite.png) no-repeat scroll 0 0 transparent; -} -.coverage-summary .sorted .sorter { - background-position: 0 -20px; -} -.coverage-summary .sorted-desc .sorter { - background-position: 0 -10px; -} -.status-line { height: 10px; } -/* dark red */ -.red.solid, .status-line.low, .low .cover-fill { background:#C21F39 } -.low .chart { border:1px solid #C21F39 } -/* medium red */ -.cstat-no, .fstat-no, .cbranch-no, .cbranch-no { background:#F6C6CE } -/* light red */ -.low, .cline-no { background:#FCE1E5 } -/* light green */ -.high, .cline-yes { background:rgb(230,245,208) } -/* medium green */ -.cstat-yes { background:rgb(161,215,106) } -/* dark green */ -.status-line.high, .high .cover-fill { background:rgb(77,146,33) } -.high .chart { border:1px solid rgb(77,146,33) } - - -.medium .chart { border:1px solid #666; } -.medium .cover-fill { background: #666; } - -.cbranch-no { background: yellow !important; color: #111; } - -.cstat-skip { background: #ddd; color: #111; } -.fstat-skip { background: #ddd; color: #111 !important; } -.cbranch-skip { background: #ddd !important; color: #111; } - -span.cline-neutral { background: #eaeaea; } -.medium { background: #eaeaea; } - -.cover-fill, .cover-empty { - display:inline-block; - height: 12px; -} -.chart { - line-height: 0; -} -.cover-empty { - background: white; -} -.cover-full { - border-right: none !important; -} -pre.prettyprint { - border: none !important; - padding: 0 !important; - margin: 0 !important; -} -.com { color: #999 !important; } -.ignore-none { color: #999; font-weight: normal; } - -.wrapper { - min-height: 100%; - height: auto !important; - height: 100%; - margin: 0 auto -48px; -} -.footer, .push { - height: 48px; -} diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/index.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/index.html deleted file mode 100644 index 27224804e1082..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/index.html +++ /dev/null @@ -1,106 +0,0 @@ - - - - Code coverage report for All files - - - - - - - -
    -
    -

    - All files -

    -
    -
    - 99.94% - Statements - 1795/1796 -
    -
    - 99.67% - Branches - 1224/1228 -
    -
    - 100% - Functions - 271/271 -
    -
    - 99.94% - Lines - 1748/1749 -
    -
    -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FileStatementsBranchesFunctionsLines
    tar
    100%13/13100%0/0100%0/0100%13/13
    tar/lib
    99.94%1782/178399.67%1224/1228100%271/27199.94%1735/1736
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.css b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.css deleted file mode 100644 index b317a7cda31a4..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.css +++ /dev/null @@ -1 +0,0 @@ -.pln{color:#000}@media screen{.str{color:#080}.kwd{color:#008}.com{color:#800}.typ{color:#606}.lit{color:#066}.pun,.opn,.clo{color:#660}.tag{color:#008}.atn{color:#606}.atv{color:#080}.dec,.var{color:#606}.fun{color:red}}@media print,projection{.str{color:#060}.kwd{color:#006;font-weight:bold}.com{color:#600;font-style:italic}.typ{color:#404;font-weight:bold}.lit{color:#044}.pun,.opn,.clo{color:#440}.tag{color:#006;font-weight:bold}.atn{color:#404}.atv{color:#060}}pre.prettyprint{padding:2px;border:1px solid #888}ol.linenums{margin-top:0;margin-bottom:0}li.L0,li.L1,li.L2,li.L3,li.L5,li.L6,li.L7,li.L8{list-style-type:none}li.L1,li.L3,li.L5,li.L7,li.L9{background:#eee} diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.js b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.js deleted file mode 100644 index ef51e03866898..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/prettify.js +++ /dev/null @@ -1 +0,0 @@ -window.PR_SHOULD_USE_CONTINUATION=true;(function(){var h=["break,continue,do,else,for,if,return,while"];var u=[h,"auto,case,char,const,default,double,enum,extern,float,goto,int,long,register,short,signed,sizeof,static,struct,switch,typedef,union,unsigned,void,volatile"];var p=[u,"catch,class,delete,false,import,new,operator,private,protected,public,this,throw,true,try,typeof"];var l=[p,"alignof,align_union,asm,axiom,bool,concept,concept_map,const_cast,constexpr,decltype,dynamic_cast,explicit,export,friend,inline,late_check,mutable,namespace,nullptr,reinterpret_cast,static_assert,static_cast,template,typeid,typename,using,virtual,where"];var x=[p,"abstract,boolean,byte,extends,final,finally,implements,import,instanceof,null,native,package,strictfp,super,synchronized,throws,transient"];var R=[x,"as,base,by,checked,decimal,delegate,descending,dynamic,event,fixed,foreach,from,group,implicit,in,interface,internal,into,is,lock,object,out,override,orderby,params,partial,readonly,ref,sbyte,sealed,stackalloc,string,select,uint,ulong,unchecked,unsafe,ushort,var"];var r="all,and,by,catch,class,else,extends,false,finally,for,if,in,is,isnt,loop,new,no,not,null,of,off,on,or,return,super,then,true,try,unless,until,when,while,yes";var w=[p,"debugger,eval,export,function,get,null,set,undefined,var,with,Infinity,NaN"];var s="caller,delete,die,do,dump,elsif,eval,exit,foreach,for,goto,if,import,last,local,my,next,no,our,print,package,redo,require,sub,undef,unless,until,use,wantarray,while,BEGIN,END";var I=[h,"and,as,assert,class,def,del,elif,except,exec,finally,from,global,import,in,is,lambda,nonlocal,not,or,pass,print,raise,try,with,yield,False,True,None"];var f=[h,"alias,and,begin,case,class,def,defined,elsif,end,ensure,false,in,module,next,nil,not,or,redo,rescue,retry,self,super,then,true,undef,unless,until,when,yield,BEGIN,END"];var H=[h,"case,done,elif,esac,eval,fi,function,in,local,set,then,until"];var A=[l,R,w,s+I,f,H];var e=/^(DIR|FILE|vector|(de|priority_)?queue|list|stack|(const_)?iterator|(multi)?(set|map)|bitset|u?(int|float)\d*)/;var C="str";var z="kwd";var j="com";var O="typ";var G="lit";var L="pun";var F="pln";var m="tag";var E="dec";var J="src";var P="atn";var n="atv";var N="nocode";var M="(?:^^\\.?|[+-]|\\!|\\!=|\\!==|\\#|\\%|\\%=|&|&&|&&=|&=|\\(|\\*|\\*=|\\+=|\\,|\\-=|\\->|\\/|\\/=|:|::|\\;|<|<<|<<=|<=|=|==|===|>|>=|>>|>>=|>>>|>>>=|\\?|\\@|\\[|\\^|\\^=|\\^\\^|\\^\\^=|\\{|\\||\\|=|\\|\\||\\|\\|=|\\~|break|case|continue|delete|do|else|finally|instanceof|return|throw|try|typeof)\\s*";function k(Z){var ad=0;var S=false;var ac=false;for(var V=0,U=Z.length;V122)){if(!(al<65||ag>90)){af.push([Math.max(65,ag)|32,Math.min(al,90)|32])}if(!(al<97||ag>122)){af.push([Math.max(97,ag)&~32,Math.min(al,122)&~32])}}}}af.sort(function(av,au){return(av[0]-au[0])||(au[1]-av[1])});var ai=[];var ap=[NaN,NaN];for(var ar=0;arat[0]){if(at[1]+1>at[0]){an.push("-")}an.push(T(at[1]))}}an.push("]");return an.join("")}function W(al){var aj=al.source.match(new RegExp("(?:\\[(?:[^\\x5C\\x5D]|\\\\[\\s\\S])*\\]|\\\\u[A-Fa-f0-9]{4}|\\\\x[A-Fa-f0-9]{2}|\\\\[0-9]+|\\\\[^ux0-9]|\\(\\?[:!=]|[\\(\\)\\^]|[^\\x5B\\x5C\\(\\)\\^]+)","g"));var ah=aj.length;var an=[];for(var ak=0,am=0;ak=2&&ai==="["){aj[ak]=X(ag)}else{if(ai!=="\\"){aj[ak]=ag.replace(/[a-zA-Z]/g,function(ao){var ap=ao.charCodeAt(0);return"["+String.fromCharCode(ap&~32,ap|32)+"]"})}}}}return aj.join("")}var aa=[];for(var V=0,U=Z.length;V=0;){S[ac.charAt(ae)]=Y}}var af=Y[1];var aa=""+af;if(!ag.hasOwnProperty(aa)){ah.push(af);ag[aa]=null}}ah.push(/[\0-\uffff]/);V=k(ah)})();var X=T.length;var W=function(ah){var Z=ah.sourceCode,Y=ah.basePos;var ad=[Y,F];var af=0;var an=Z.match(V)||[];var aj={};for(var ae=0,aq=an.length;ae=5&&"lang-"===ap.substring(0,5);if(am&&!(ai&&typeof ai[1]==="string")){am=false;ap=J}if(!am){aj[ag]=ap}}var ab=af;af+=ag.length;if(!am){ad.push(Y+ab,ap)}else{var al=ai[1];var ak=ag.indexOf(al);var ac=ak+al.length;if(ai[2]){ac=ag.length-ai[2].length;ak=ac-al.length}var ar=ap.substring(5);B(Y+ab,ag.substring(0,ak),W,ad);B(Y+ab+ak,al,q(ar,al),ad);B(Y+ab+ac,ag.substring(ac),W,ad)}}ah.decorations=ad};return W}function i(T){var W=[],S=[];if(T.tripleQuotedStrings){W.push([C,/^(?:\'\'\'(?:[^\'\\]|\\[\s\S]|\'{1,2}(?=[^\']))*(?:\'\'\'|$)|\"\"\"(?:[^\"\\]|\\[\s\S]|\"{1,2}(?=[^\"]))*(?:\"\"\"|$)|\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$))/,null,"'\""])}else{if(T.multiLineStrings){W.push([C,/^(?:\'(?:[^\\\']|\\[\s\S])*(?:\'|$)|\"(?:[^\\\"]|\\[\s\S])*(?:\"|$)|\`(?:[^\\\`]|\\[\s\S])*(?:\`|$))/,null,"'\"`"])}else{W.push([C,/^(?:\'(?:[^\\\'\r\n]|\\.)*(?:\'|$)|\"(?:[^\\\"\r\n]|\\.)*(?:\"|$))/,null,"\"'"])}}if(T.verbatimStrings){S.push([C,/^@\"(?:[^\"]|\"\")*(?:\"|$)/,null])}var Y=T.hashComments;if(Y){if(T.cStyleComments){if(Y>1){W.push([j,/^#(?:##(?:[^#]|#(?!##))*(?:###|$)|.*)/,null,"#"])}else{W.push([j,/^#(?:(?:define|elif|else|endif|error|ifdef|include|ifndef|line|pragma|undef|warning)\b|[^\r\n]*)/,null,"#"])}S.push([C,/^<(?:(?:(?:\.\.\/)*|\/?)(?:[\w-]+(?:\/[\w-]+)+)?[\w-]+\.h|[a-z]\w*)>/,null])}else{W.push([j,/^#[^\r\n]*/,null,"#"])}}if(T.cStyleComments){S.push([j,/^\/\/[^\r\n]*/,null]);S.push([j,/^\/\*[\s\S]*?(?:\*\/|$)/,null])}if(T.regexLiterals){var X=("/(?=[^/*])(?:[^/\\x5B\\x5C]|\\x5C[\\s\\S]|\\x5B(?:[^\\x5C\\x5D]|\\x5C[\\s\\S])*(?:\\x5D|$))+/");S.push(["lang-regex",new RegExp("^"+M+"("+X+")")])}var V=T.types;if(V){S.push([O,V])}var U=(""+T.keywords).replace(/^ | $/g,"");if(U.length){S.push([z,new RegExp("^(?:"+U.replace(/[\s,]+/g,"|")+")\\b"),null])}W.push([F,/^\s+/,null," \r\n\t\xA0"]);S.push([G,/^@[a-z_$][a-z_$@0-9]*/i,null],[O,/^(?:[@_]?[A-Z]+[a-z][A-Za-z_$@0-9]*|\w+_t\b)/,null],[F,/^[a-z_$][a-z_$@0-9]*/i,null],[G,new RegExp("^(?:0x[a-f0-9]+|(?:\\d(?:_\\d+)*\\d*(?:\\.\\d*)?|\\.\\d\\+)(?:e[+\\-]?\\d+)?)[a-z]*","i"),null,"0123456789"],[F,/^\\[\s\S]?/,null],[L,/^.[^\s\w\.$@\'\"\`\/\#\\]*/,null]);return g(W,S)}var K=i({keywords:A,hashComments:true,cStyleComments:true,multiLineStrings:true,regexLiterals:true});function Q(V,ag){var U=/(?:^|\s)nocode(?:\s|$)/;var ab=/\r\n?|\n/;var ac=V.ownerDocument;var S;if(V.currentStyle){S=V.currentStyle.whiteSpace}else{if(window.getComputedStyle){S=ac.defaultView.getComputedStyle(V,null).getPropertyValue("white-space")}}var Z=S&&"pre"===S.substring(0,3);var af=ac.createElement("LI");while(V.firstChild){af.appendChild(V.firstChild)}var W=[af];function ae(al){switch(al.nodeType){case 1:if(U.test(al.className)){break}if("BR"===al.nodeName){ad(al);if(al.parentNode){al.parentNode.removeChild(al)}}else{for(var an=al.firstChild;an;an=an.nextSibling){ae(an)}}break;case 3:case 4:if(Z){var am=al.nodeValue;var aj=am.match(ab);if(aj){var ai=am.substring(0,aj.index);al.nodeValue=ai;var ah=am.substring(aj.index+aj[0].length);if(ah){var ak=al.parentNode;ak.insertBefore(ac.createTextNode(ah),al.nextSibling)}ad(al);if(!ai){al.parentNode.removeChild(al)}}}break}}function ad(ak){while(!ak.nextSibling){ak=ak.parentNode;if(!ak){return}}function ai(al,ar){var aq=ar?al.cloneNode(false):al;var ao=al.parentNode;if(ao){var ap=ai(ao,1);var an=al.nextSibling;ap.appendChild(aq);for(var am=an;am;am=an){an=am.nextSibling;ap.appendChild(am)}}return aq}var ah=ai(ak.nextSibling,0);for(var aj;(aj=ah.parentNode)&&aj.nodeType===1;){ah=aj}W.push(ah)}for(var Y=0;Y=S){ah+=2}if(V>=ap){Z+=2}}}var t={};function c(U,V){for(var S=V.length;--S>=0;){var T=V[S];if(!t.hasOwnProperty(T)){t[T]=U}else{if(window.console){console.warn("cannot override language handler %s",T)}}}}function q(T,S){if(!(T&&t.hasOwnProperty(T))){T=/^\s*]*(?:>|$)/],[j,/^<\!--[\s\S]*?(?:-\->|$)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],[L,/^(?:<[%?]|[%?]>)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i]]),["default-markup","htm","html","mxml","xhtml","xml","xsl"]);c(g([[F,/^[\s]+/,null," \t\r\n"],[n,/^(?:\"[^\"]*\"?|\'[^\']*\'?)/,null,"\"'"]],[[m,/^^<\/?[a-z](?:[\w.:-]*\w)?|\/?>$/i],[P,/^(?!style[\s=]|on)[a-z](?:[\w:-]*\w)?/i],["lang-uq.val",/^=\s*([^>\'\"\s]*(?:[^>\'\"\s\/]|\/(?=\s)))/],[L,/^[=<>\/]+/],["lang-js",/^on\w+\s*=\s*\"([^\"]+)\"/i],["lang-js",/^on\w+\s*=\s*\'([^\']+)\'/i],["lang-js",/^on\w+\s*=\s*([^\"\'>\s]+)/i],["lang-css",/^style\s*=\s*\"([^\"]+)\"/i],["lang-css",/^style\s*=\s*\'([^\']+)\'/i],["lang-css",/^style\s*=\s*([^\"\'>\s]+)/i]]),["in.tag"]);c(g([],[[n,/^[\s\S]+/]]),["uq.val"]);c(i({keywords:l,hashComments:true,cStyleComments:true,types:e}),["c","cc","cpp","cxx","cyc","m"]);c(i({keywords:"null,true,false"}),["json"]);c(i({keywords:R,hashComments:true,cStyleComments:true,verbatimStrings:true,types:e}),["cs"]);c(i({keywords:x,cStyleComments:true}),["java"]);c(i({keywords:H,hashComments:true,multiLineStrings:true}),["bsh","csh","sh"]);c(i({keywords:I,hashComments:true,multiLineStrings:true,tripleQuotedStrings:true}),["cv","py"]);c(i({keywords:s,hashComments:true,multiLineStrings:true,regexLiterals:true}),["perl","pl","pm"]);c(i({keywords:f,hashComments:true,multiLineStrings:true,regexLiterals:true}),["rb"]);c(i({keywords:w,cStyleComments:true,regexLiterals:true}),["js"]);c(i({keywords:r,hashComments:3,cStyleComments:true,multilineStrings:true,tripleQuotedStrings:true,regexLiterals:true}),["coffee"]);c(g([],[[C,/^[\s\S]+/]]),["regex"]);function d(V){var U=V.langExtension;try{var S=a(V.sourceNode);var T=S.sourceCode;V.sourceCode=T;V.spans=S.spans;V.basePos=0;q(U,T)(V);D(V)}catch(W){if("console" in window){console.log(W&&W.stack?W.stack:W)}}}function y(W,V,U){var S=document.createElement("PRE");S.innerHTML=W;if(U){Q(S,U)}var T={langExtension:V,numberLines:U,sourceNode:S};d(T);return S.innerHTML}function b(ad){function Y(af){return document.getElementsByTagName(af)}var ac=[Y("pre"),Y("code"),Y("xmp")];var T=[];for(var aa=0;aa=0){var ah=ai.match(ab);var am;if(!ah&&(am=o(aj))&&"CODE"===am.tagName){ah=am.className.match(ab)}if(ah){ah=ah[1]}var al=false;for(var ak=aj.parentNode;ak;ak=ak.parentNode){if((ak.tagName==="pre"||ak.tagName==="code"||ak.tagName==="xmp")&&ak.className&&ak.className.indexOf("prettyprint")>=0){al=true;break}}if(!al){var af=aj.className.match(/\blinenums\b(?::(\d+))?/);af=af?af[1]&&af[1].length?+af[1]:true:false;if(af){Q(aj,af)}S={langExtension:ah,sourceNode:aj,numberLines:af};d(S)}}}if(X]*(?:>|$)/],[PR.PR_COMMENT,/^<\!--[\s\S]*?(?:-\->|$)/],[PR.PR_PUNCTUATION,/^(?:<[%?]|[%?]>)/],["lang-",/^<\?([\s\S]+?)(?:\?>|$)/],["lang-",/^<%([\s\S]+?)(?:%>|$)/],["lang-",/^]*>([\s\S]+?)<\/xmp\b[^>]*>/i],["lang-handlebars",/^]*type\s*=\s*['"]?text\/x-handlebars-template['"]?\b[^>]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-js",/^]*>([\s\S]*?)(<\/script\b[^>]*>)/i],["lang-css",/^]*>([\s\S]*?)(<\/style\b[^>]*>)/i],["lang-in.tag",/^(<\/?[a-z][^<>]*>)/i],[PR.PR_DECLARATION,/^{{[#^>/]?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{&?\s*[\w.][^}]*}}/],[PR.PR_DECLARATION,/^{{{>?\s*[\w.][^}]*}}}/],[PR.PR_COMMENT,/^{{![^}]*}}/]]),["handlebars","hbs"]);PR.registerLangHandler(PR.createSimpleLexer([[PR.PR_PLAIN,/^[ \t\r\n\f]+/,null," \t\r\n\f"]],[[PR.PR_STRING,/^\"(?:[^\n\r\f\\\"]|\\(?:\r\n?|\n|\f)|\\[\s\S])*\"/,null],[PR.PR_STRING,/^\'(?:[^\n\r\f\\\']|\\(?:\r\n?|\n|\f)|\\[\s\S])*\'/,null],["lang-css-str",/^url\(([^\)\"\']*)\)/i],[PR.PR_KEYWORD,/^(?:url|rgb|\!important|@import|@page|@media|@charset|inherit)(?=[^\-\w]|$)/i,null],["lang-css-kw",/^(-?(?:[_a-z]|(?:\\[0-9a-f]+ ?))(?:[_a-z0-9\-]|\\(?:\\[0-9a-f]+ ?))*)\s*:/i],[PR.PR_COMMENT,/^\/\*[^*]*\*+(?:[^\/*][^*]*\*+)*\//],[PR.PR_COMMENT,/^(?:)/],[PR.PR_LITERAL,/^(?:\d+|\d*\.\d+)(?:%|[a-z]+)?/i],[PR.PR_LITERAL,/^#(?:[0-9a-f]{3}){1,2}/i],[PR.PR_PLAIN,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i],[PR.PR_PUNCTUATION,/^[^\s\w\'\"]+/]]),["css"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_KEYWORD,/^-?(?:[_a-z]|(?:\\[\da-f]+ ?))(?:[_a-z\d\-]|\\(?:\\[\da-f]+ ?))*/i]]),["css-kw"]);PR.registerLangHandler(PR.createSimpleLexer([],[[PR.PR_STRING,/^[^\)\"\']+/]]),["css-str"]); diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/sort-arrow-sprite.png b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/sort-arrow-sprite.png deleted file mode 100644 index 03f704a609c6fd0dbfdac63466a7d7c958b5cbf3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 209 zcmeAS@N?(olHy`uVBq!ia0vp^>_9Bd!3HEZxJ@+%Qj#UE5hcO-X(i=}MX3yqDfvmM z3ZA)%>8U}fi7AzZCsS>Jii$m5978H@?Fn+^JD|Y9yzj{W`447Gxa{7*dM7nnnD-Lb z6^}Hx2)'; - } - } - return cols; - } - // attaches a data attribute to every tr element with an object - // of data values keyed by column name - function loadRowData(tableRow) { - var tableCols = tableRow.querySelectorAll('td'), - colNode, - col, - data = {}, - i, - val; - for (i = 0; i < tableCols.length; i += 1) { - colNode = tableCols[i]; - col = cols[i]; - val = colNode.getAttribute('data-value'); - if (col.type === 'number') { - val = Number(val); - } - data[col.key] = val; - } - return data; - } - // loads all row data - function loadData() { - var rows = getTableBody().querySelectorAll('tr'), - i; - - for (i = 0; i < rows.length; i += 1) { - rows[i].data = loadRowData(rows[i]); - } - } - // sorts the table using the data for the ith column - function sortByIndex(index, desc) { - var key = cols[index].key, - sorter = function (a, b) { - a = a.data[key]; - b = b.data[key]; - return a < b ? -1 : a > b ? 1 : 0; - }, - finalSorter = sorter, - tableBody = document.querySelector('.coverage-summary tbody'), - rowNodes = tableBody.querySelectorAll('tr'), - rows = [], - i; - - if (desc) { - finalSorter = function (a, b) { - return -1 * sorter(a, b); - }; - } - - for (i = 0; i < rowNodes.length; i += 1) { - rows.push(rowNodes[i]); - tableBody.removeChild(rowNodes[i]); - } - - rows.sort(finalSorter); - - for (i = 0; i < rows.length; i += 1) { - tableBody.appendChild(rows[i]); - } - } - // removes sort indicators for current column being sorted - function removeSortIndicators() { - var col = getNthColumn(currentSort.index), - cls = col.className; - - cls = cls.replace(/ sorted$/, '').replace(/ sorted-desc$/, ''); - col.className = cls; - } - // adds sort indicators for current column being sorted - function addSortIndicators() { - getNthColumn(currentSort.index).className += currentSort.desc ? ' sorted-desc' : ' sorted'; - } - // adds event listeners for all sorter widgets - function enableUI() { - var i, - el, - ithSorter = function ithSorter(i) { - var col = cols[i]; - - return function () { - var desc = col.defaultDescSort; - - if (currentSort.index === i) { - desc = !currentSort.desc; - } - sortByIndex(i, desc); - removeSortIndicators(); - currentSort.index = i; - currentSort.desc = desc; - addSortIndicators(); - }; - }; - for (i =0 ; i < cols.length; i += 1) { - if (cols[i].sortable) { - // add the click event handler on the th so users - // dont have to click on those tiny arrows - el = getNthColumn(i).querySelector('.sorter').parentElement; - if (el.addEventListener) { - el.addEventListener('click', ithSorter(i)); - } else { - el.attachEvent('onclick', ithSorter(i)); - } - } - } - } - // adds sorting functionality to the UI - return function () { - if (!getTable()) { - return; - } - cols = loadColumns(); - loadData(cols); - addSortIndicators(); - enableUI(); - }; -})(); - -window.addEventListener('load', addSorting); diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.html deleted file mode 100644 index 9c917bdeb14ba..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.html +++ /dev/null @@ -1,93 +0,0 @@ - - - - Code coverage report for tar - - - - - - - -
    -
    -

    - All files tar -

    -
    -
    - 100% - Statements - 13/13 -
    -
    - 100% - Branches - 0/0 -
    -
    - 100% - Functions - 0/0 -
    -
    - 100% - Lines - 13/13 -
    -
    -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FileStatementsBranchesFunctionsLines
    index.js
    100%13/13100%0/0100%0/0100%13/13
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.js.html deleted file mode 100644 index f04c992346340..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/index.js.html +++ /dev/null @@ -1,119 +0,0 @@ - - - - Code coverage report for tar/index.js - - - - - - - -
    -
    -

    - All files / tar index.js -

    -
    -
    - 100% - Statements - 13/13 -
    -
    - 100% - Branches - 0/0 -
    -
    - 100% - Functions - 0/0 -
    -
    - 100% - Lines - 13/13 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19  -  -  -1x -1x -1x -1x -1x -  -  -1x -1x -1x -1x -1x -1x -1x -1x - 
    'use strict'
    - 
    -// high-level commands
    -exports.c = exports.create = require('./lib/create.js')
    -exports.r = exports.replace = require('./lib/replace.js')
    -exports.t = exports.list = require('./lib/list.js')
    -exports.u = exports.update = require('./lib/update.js')
    -exports.x = exports.extract = require('./lib/extract.js')
    - 
    -// classes
    -exports.Pack = require('./lib/pack.js')
    -exports.Unpack = require('./lib/unpack.js')
    -exports.Parse = require('./lib/parse.js')
    -exports.ReadEntry = require('./lib/read-entry.js')
    -exports.WriteEntry = require('./lib/write-entry.js')
    -exports.Header = require('./lib/header.js')
    -exports.Pax = require('./lib/pax.js')
    -exports.types = require('./lib/types.js')
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/create.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/create.js.html deleted file mode 100644 index 2f01c7e302a1e..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/create.js.html +++ /dev/null @@ -1,380 +0,0 @@ - - - - Code coverage report for tar/lib/create.js - - - - - - - -
    -
    -

    - All files / tar/lib create.js -

    -
    -
    - 100% - Statements - 59/59 -
    -
    - 100% - Branches - 35/35 -
    -
    - 100% - Functions - 12/12 -
    -
    - 100% - Lines - 59/59 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106  -  -  -2x -  -2x -2x -2x -2x -2x -  -2x -15x -1x -  -15x -1x -  -15x -2x -  -13x -  -13x -  -13x -1x -  -12x -1x -  -11x -  -  -  -  -  -2x -4x -4x -  -  -4x -4x -  -  -2x -4x -4x -  -  -4x -  -4x -4x -4x -4x -  -  -4x -  -4x -  -  -2x -5x -7x -3x -  -  -  -7x -  -  -4x -  -4x -  -  -2x -9x -8x -8x -3x -  -  -7x -3x -  -5x -  -6x -  -  -2x -1x -1x -1x -  -  -2x -2x -2x -2x -  - 
    'use strict'
    - 
    -// tar -c
    -const hlo = require('./high-level-opt.js')
    - 
    -const Pack = require('./pack.js')
    -const fs = require('fs')
    -const fsm = require('fs-minipass')
    -const t = require('./list.js')
    -const path = require('path')
    - 
    -const c = module.exports = (opt_, files, cb) => {
    -  if (typeof files === 'function')
    -    cb = files
    - 
    -  if (Array.isArray(opt_))
    -    files = opt_, opt_ = {}
    - 
    -  if (!files || !Array.isArray(files) || !files.length)
    -    throw new TypeError('no files or directories specified')
    - 
    -  files = Array.from(files)
    - 
    -  const opt = hlo(opt_)
    - 
    -  if (opt.sync && typeof cb === 'function')
    -    throw new TypeError('callback not supported for sync tar functions')
    - 
    -  if (!opt.file && typeof cb === 'function')
    -    throw new TypeError('callback only supported with file option')
    - 
    -  return opt.file && opt.sync ? createFileSync(opt, files)
    -    : opt.file ? createFile(opt, files, cb)
    -    : opt.sync ? createSync(opt, files)
    -    : create(opt, files)
    -}
    - 
    -const createFileSync = (opt, files) => {
    -  const p = new Pack.Sync(opt)
    -  const stream = new fsm.WriteStreamSync(opt.file, {
    -    mode: opt.mode || 0o666
    -  })
    -  p.pipe(stream)
    -  addFilesSync(p, files)
    -}
    - 
    -const createFile = (opt, files, cb) => {
    -  const p = new Pack(opt)
    -  const stream = new fsm.WriteStream(opt.file, {
    -    mode: opt.mode || 0o666
    -  })
    -  p.pipe(stream)
    - 
    -  const promise = new Promise((res, rej) => {
    -    stream.on('error', rej)
    -    stream.on('close', res)
    -    p.on('error', rej)
    -  })
    - 
    -  addFilesAsync(p, files)
    - 
    -  return cb ? promise.then(cb, cb) : promise
    -}
    - 
    -const addFilesSync = (p, files) => {
    -  files.forEach(file => {
    -    if (file.charAt(0) === '@')
    -      t({
    -        file: path.resolve(p.cwd, file.substr(1)),
    -        sync: true,
    -        noResume: true,
    -        onentry: entry => p.add(entry)
    -      })
    -    else
    -      p.add(file)
    -  })
    -  p.end()
    -}
    - 
    -const addFilesAsync = (p, files) => {
    -  while (files.length) {
    -    const file = files.shift()
    -    if (file.charAt(0) === '@')
    -      return t({
    -        file: path.resolve(p.cwd, file.substr(1)),
    -        noResume: true,
    -        onentry: entry => p.add(entry)
    -      }).then(_ => addFilesAsync(p, files))
    -    else
    -      p.add(file)
    -  }
    -  p.end()
    -}
    - 
    -const createSync = (opt, files) => {
    -  const p = new Pack.Sync(opt)
    -  addFilesSync(p, files)
    -  return p
    -}
    - 
    -const create = (opt, files) => {
    -  const p = new Pack(opt)
    -  addFilesAsync(p, files)
    -  return p
    -}
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/extract.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/extract.js.html deleted file mode 100644 index 96245c73d9f66..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/extract.js.html +++ /dev/null @@ -1,401 +0,0 @@ - - - - Code coverage report for tar/lib/extract.js - - - - - - - -
    -
    -

    - All files / tar/lib extract.js -

    -
    -
    - 100% - Statements - 61/61 -
    -
    - 100% - Branches - 45/45 -
    -
    - 100% - Functions - 12/12 -
    -
    - 100% - Lines - 60/60 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113  -  -  -2x -2x -2x -2x -2x -  -2x -21x -1x -20x -1x -  -21x -3x -  -21x -13x -  -8x -  -21x -  -21x -2x -  -19x -1x -  -18x -7x -  -18x -  -  -  -  -  -  -  -2x -13x -7x -  -7x -87x -87x -  -  -  -87x -87x -  -  -7x -9x -9x -  -  -2x -6x -  -6x -6x -  -6x -  -  -5x -5x -  -  -  -4x -  -  -2x -9x -9x -  -9x -9x -9x -9x -  -  -  -9x -9x -1x -  -8x -  -  -  -8x -8x -  -  -  -9x -  -  -2x -1x -  -  -2x -2x -  - 
    'use strict'
    - 
    -// tar -x
    -const hlo = require('./high-level-opt.js')
    -const Unpack = require('./unpack.js')
    -const fs = require('fs')
    -const fsm = require('fs-minipass')
    -const path = require('path')
    - 
    -const x = module.exports = (opt_, files, cb) => {
    -  if (typeof opt_ === 'function')
    -    cb = opt_, files = null, opt_ = {}
    -  else if (Array.isArray(opt_))
    -    files = opt_, opt_ = {}
    - 
    -  if (typeof files === 'function')
    -    cb = files, files = null
    - 
    -  if (!files)
    -    files = []
    -  else
    -    files = Array.from(files)
    - 
    -  const opt = hlo(opt_)
    - 
    -  if (opt.sync && typeof cb === 'function')
    -    throw new TypeError('callback not supported for sync tar functions')
    - 
    -  if (!opt.file && typeof cb === 'function')
    -    throw new TypeError('callback only supported with file option')
    - 
    -  if (files.length)
    -    filesFilter(opt, files)
    - 
    -  return opt.file && opt.sync ? extractFileSync(opt)
    -    : opt.file ? extractFile(opt, cb)
    -    : opt.sync ? extractSync(opt)
    -    : extract(opt)
    -}
    - 
    -// construct a filter that limits the file entries listed
    -// include child entries if a dir is included
    -const filesFilter = (opt, files) => {
    -  const map = new Map(files.map(f => [f.replace(/\/+$/, ''), true]))
    -  const filter = opt.filter
    - 
    -  const mapHas = (file, r) => {
    -    const root = r || path.parse(file).root || '.'
    -    const ret = file === root ? false
    -      : map.has(file) ? map.get(file)
    -      : mapHas(path.dirname(file), root)
    - 
    -    map.set(file, ret)
    -    return ret
    -  }
    - 
    -  opt.filter = filter
    -    ? (file, entry) => filter(file, entry) && mapHas(file.replace(/\/+$/, ''))
    -    : file => mapHas(file.replace(/\/+$/, ''))
    -}
    - 
    -const extractFileSync = opt => {
    -  const u = new Unpack.Sync(opt)
    - 
    -  const file = opt.file
    -  let threw = true
    -  let fd
    -  const stat = fs.statSync(file)
    -  // This trades a zero-byte read() syscall for a stat
    -  // However, it will usually result in less memory allocation
    -  const readSize = opt.maxReadSize || 16*1024*1024
    -  const stream = new fsm.ReadStreamSync(file, {
    -    readSize: readSize,
    -    size: stat.size
    -  })
    -  stream.pipe(u)
    -}
    - 
    -const extractFile = (opt, cb) => {
    -  const u = new Unpack(opt)
    -  const readSize = opt.maxReadSize || 16*1024*1024
    - 
    -  const file = opt.file
    -  const p = new Promise((resolve, reject) => {
    -    u.on('error', reject)
    -    u.on('close', resolve)
    - 
    -    // This trades a zero-byte read() syscall for a stat
    -    // However, it will usually result in less memory allocation
    -    fs.stat(file, (er, stat) => {
    -      if (er)
    -        reject(er)
    -      else {
    -        const stream = new fsm.ReadStream(file, {
    -          readSize: readSize,
    -          size: stat.size
    -        })
    -        stream.on('error', reject)
    -        stream.pipe(u)
    -      }
    -    })
    -  })
    -  return cb ? p.then(cb, cb) : p
    -}
    - 
    -const extractSync = opt => {
    -  return new Unpack.Sync(opt)
    -}
    - 
    -const extract = opt => {
    -  return new Unpack(opt)
    -}
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/header.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/header.js.html deleted file mode 100644 index 69770d09869e7..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/header.js.html +++ /dev/null @@ -1,881 +0,0 @@ - - - - Code coverage report for tar/lib/header.js - - - - - - - -
    -
    -

    - All files / tar/lib header.js -

    -
    -
    - 100% - Statements - 161/161 -
    -
    - 100% - Branches - 120/120 -
    -
    - 100% - Functions - 20/20 -
    -
    - 100% - Lines - 159/159 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 -270 -271 -272 -273  -  -  -  -  -  -13x -13x -13x -  -13x -  -  -  -13121x -13121x -13121x -  -13121x -13121x -13121x -13121x -13121x -13121x -13121x -13121x -13121x -13121x -13121x -13121x -13121x -13121x -13121x -13121x -  -13121x -6393x -6728x -6726x -  -  -  -6393x -2795x -  -6393x -1x -  -6392x -6392x -6392x -6392x -6392x -6392x -6392x -  -  -6392x -6392x -1990x -6392x -2x -  -  -  -  -  -  -6392x -1594x -  -6392x -6392x -4275x -4275x -4275x -4275x -4275x -  -2x -2x -  -4273x -4273x -295x -4273x -4273x -  -  -  -6392x -6392x -946016x -  -6392x -2275552x -  -6392x -6392x -1860x -  -  -  -6719x -6600x -6600x -  -  -6719x -6717x -  -6719x -1x -  -6718x -6718x -6718x -6718x -6718x -  -6718x -6718x -6718x -6718x -6718x -6718x -6718x -6718x -6718x -6718x -6718x -6718x -6718x -6718x -6718x -2x -  -6716x -6716x -6716x -  -  -6718x -6718x -994264x -  -6718x -2391608x -  -6718x -6718x -6718x -  -6718x -  -  -  -6728x -73451x -66740x -  -  -  -  -8178x -  -  -  -4x -  -  -  -6723x -6719x -  -4x -  -  -  -13x -6718x -6718x -6718x -  -6718x -  -6718x -6683x -  -  -35x -35x -  -35x -  -49x -  -21x -  -  -28x -  -13x -  -  -  -15x -15x -  -  -  -  -35x -1x -  -6718x -  -  -13x -32001x -  -13x -14938x -  -14938x -  -13x -55448x -  -  -55411x -  -13x -55411x -  -  -  -  -13x -  -  -  -  -13x -66910x -  -  -  -  -13x -66615x -  -13x -66615x -  -13x -66615x -  -  -13x -20150x -  -  -  -13x -  -13x -40308x -  -  -  -13x - 
    'use strict'
    -// parse a 512-byte header block to a data object, or vice-versa
    -// encode returns `true` if a pax extended header is needed, because
    -// the data could not be faithfully encoded in a simple header.
    -// (Also, check header.needPax to see if it needs a pax header.)
    - 
    -const types = require('./types.js')
    -const pathModule = require('path')
    -const large = require('./large-numbers.js')
    - 
    -const TYPE = Symbol('type')
    - 
    -class Header {
    -  constructor (data, off) {
    -    this.cksumValid = false
    -    this.needPax = false
    -    this.nullBlock = false
    - 
    -    this.block = null
    -    this.path = null
    -    this.mode = null
    -    this.uid = null
    -    this.gid = null
    -    this.size = null
    -    this.mtime = null
    -    this.cksum = null
    -    this[TYPE] = '0'
    -    this.linkpath = null
    -    this.uname = null
    -    this.gname = null
    -    this.devmaj = 0
    -    this.devmin = 0
    -    this.atime = null
    -    this.ctime = null
    - 
    -    if (Buffer.isBuffer(data)) {
    -      this.decode(data, off || 0)
    -    } else if (data)
    -      this.set(data)
    -  }
    - 
    -  decode (buf, off) {
    -    if (!off)
    -      off = 0
    - 
    -    if (!buf || !(buf.length >= off + 512))
    -      throw new Error('need 512 bytes for header')
    - 
    -    this.path = decString(buf, off, 100)
    -    this.mode = decNumber(buf, off + 100, 8)
    -    this.uid = decNumber(buf, off + 108, 8)
    -    this.gid = decNumber(buf, off + 116, 8)
    -    this.size = decNumber(buf, off + 124, 12)
    -    this.mtime = decDate(buf, off + 136, 12)
    -    this.cksum = decNumber(buf, off + 148, 12)
    - 
    -    // old tar versions marked dirs as a file with a trailing /
    -    this[TYPE] = decString(buf, off + 156, 1)
    -    if (this[TYPE] === '')
    -      this[TYPE] = '0'
    -    if (this[TYPE] === '0' && this.path.substr(-1) === '/')
    -      this[TYPE] = '5'
    - 
    -    // tar implementations sometimes incorrectly put the stat(dir).size
    -    // as the size in the tarball, even though Directory entries are
    -    // not able to have any body at all.  In the very rare chance that
    -    // it actually DOES have a body, we weren't going to do anything with
    -    // it anyway, and it'll just be a warning about an invalid header.
    -    if (this[TYPE] === '5')
    -      this.size = 0
    - 
    -    this.linkpath = decString(buf, off + 157, 100)
    -    if (buf.slice(off + 257, off + 265).toString() === 'ustar\u000000') {
    -      this.uname = decString(buf, off + 265, 32)
    -      this.gname = decString(buf, off + 297, 32)
    -      this.devmaj = decNumber(buf, off + 329, 8)
    -      this.devmin = decNumber(buf, off + 337, 8)
    -      if (buf[off + 475] !== 0) {
    -        // definitely a prefix, definitely >130 chars.
    -        const prefix = decString(buf, off + 345, 155)
    -        this.path = prefix + '/' + this.path
    -      } else {
    -        const prefix = decString(buf, off + 345, 130)
    -        if (prefix)
    -          this.path = prefix + '/' + this.path
    -        this.atime = decDate(buf, off + 476, 12)
    -        this.ctime = decDate(buf, off + 488, 12)
    -      }
    -    }
    - 
    -    let sum = 8 * 0x20
    -    for (let i = off; i < off + 148; i++) {
    -      sum += buf[i]
    -    }
    -    for (let i = off + 156; i < off + 512; i++) {
    -      sum += buf[i]
    -    }
    -    this.cksumValid = sum === this.cksum
    -    if (this.cksum === null && sum === 8 * 0x20)
    -      this.nullBlock = true
    -  }
    - 
    -  encode (buf, off) {
    -    if (!buf) {
    -      buf = this.block = Buffer.alloc(512)
    -      off = 0
    -    }
    - 
    -    if (!off)
    -      off = 0
    - 
    -    if (!(buf.length >= off + 512))
    -      throw new Error('need 512 bytes for header')
    - 
    -    const prefixSize = this.ctime || this.atime ? 130 : 155
    -    const split = splitPrefix(this.path || '', prefixSize)
    -    const path = split[0]
    -    const prefix = split[1]
    -    this.needPax = split[2]
    - 
    -    this.needPax = encString(buf, off, 100, path) || this.needPax
    -    this.needPax = encNumber(buf, off + 100, 8, this.mode) || this.needPax
    -    this.needPax = encNumber(buf, off + 108, 8, this.uid) || this.needPax
    -    this.needPax = encNumber(buf, off + 116, 8, this.gid) || this.needPax
    -    this.needPax = encNumber(buf, off + 124, 12, this.size) || this.needPax
    -    this.needPax = encDate(buf, off + 136, 12, this.mtime) || this.needPax
    -    buf[off + 156] = this[TYPE].charCodeAt(0)
    -    this.needPax = encString(buf, off + 157, 100, this.linkpath) || this.needPax
    -    buf.write('ustar\u000000', off + 257, 8)
    -    this.needPax = encString(buf, off + 265, 32, this.uname) || this.needPax
    -    this.needPax = encString(buf, off + 297, 32, this.gname) || this.needPax
    -    this.needPax = encNumber(buf, off + 329, 8, this.devmaj) || this.needPax
    -    this.needPax = encNumber(buf, off + 337, 8, this.devmin) || this.needPax
    -    this.needPax = encString(buf, off + 345, prefixSize, prefix) || this.needPax
    -    if (buf[off + 475] !== 0)
    -      this.needPax = encString(buf, off + 345, 155, prefix) || this.needPax
    -    else {
    -      this.needPax = encString(buf, off + 345, 130, prefix) || this.needPax
    -      this.needPax = encDate(buf, off + 476, 12, this.atime) || this.needPax
    -      this.needPax = encDate(buf, off + 488, 12, this.ctime) || this.needPax
    -    }
    - 
    -    let sum = 8 * 0x20
    -    for (let i = off; i < off + 148; i++) {
    -      sum += buf[i]
    -    }
    -    for (let i = off + 156; i < off + 512; i++) {
    -      sum += buf[i]
    -    }
    -    this.cksum = sum
    -    encNumber(buf, off + 148, 8, this.cksum)
    -    this.cksumValid = true
    - 
    -    return this.needPax
    -  }
    - 
    -  set (data) {
    -    for (let i in data) {
    -      if (data[i] !== null && data[i] !== undefined)
    -        this[i] = data[i]
    -    }
    -  }
    - 
    -  get type () {
    -    return types.name.get(this[TYPE]) || this[TYPE]
    -  }
    - 
    -  get typeKey () {
    -    return this[TYPE]
    -  }
    - 
    -  set type (type) {
    -    if (types.code.has(type))
    -      this[TYPE] = types.code.get(type)
    -    else
    -      this[TYPE] = type
    -  }
    -}
    - 
    -const splitPrefix = (p, prefixSize) => {
    -  const pathSize = 100
    -  let pp = p
    -  let prefix = ''
    -  let ret
    -  const root = pathModule.parse(p).root || '.'
    - 
    -  if (Buffer.byteLength(pp) < pathSize)
    -    ret = [pp, prefix, false]
    -  else {
    -    // first set prefix to the dir, and path to the base
    -    prefix = pathModule.dirname(pp)
    -    pp = pathModule.basename(pp)
    - 
    -    do {
    -      // both fit!
    -      if (Buffer.byteLength(pp) <= pathSize &&
    -          Buffer.byteLength(prefix) <= prefixSize)
    -        ret = [pp, prefix, false]
    - 
    -      // prefix fits in prefix, but path doesn't fit in path
    -      else if (Buffer.byteLength(pp) > pathSize &&
    -          Buffer.byteLength(prefix) <= prefixSize)
    -        ret = [pp.substr(0, pathSize - 1), prefix, true]
    - 
    -      else {
    -        // make path take a bit from prefix
    -        pp = pathModule.join(pathModule.basename(prefix), pp)
    -        prefix = pathModule.dirname(prefix)
    -      }
    -    } while (prefix !== root && !ret)
    - 
    -    // at this point, found no resolution, just truncate
    -    if (!ret)
    -      ret = [p.substr(0, pathSize - 1), '', true]
    -  }
    -  return ret
    -}
    - 
    -const decString = (buf, off, size) =>
    -  buf.slice(off, off + size).toString('utf8').replace(/\0.*/, '')
    - 
    -const decDate = (buf, off, size) =>
    -  numToDate(decNumber(buf, off, size))
    - 
    -const numToDate = num => num === null ? null : new Date(num * 1000)
    - 
    -const decNumber = (buf, off, size) =>
    -  buf[off] & 0x80 ? large.parse(buf.slice(off, off + size))
    -    : decSmallNumber(buf, off, size)
    - 
    -const nanNull = value => isNaN(value) ? null : value
    - 
    -const decSmallNumber = (buf, off, size) =>
    -  nanNull(parseInt(
    -    buf.slice(off, off + size)
    -      .toString('utf8').replace(/\0.*$/, '').trim(), 8))
    - 
    -// the maximum encodable as a null-terminated octal, by field size
    -const MAXNUM = {
    -  12: 0o77777777777,
    -  8 : 0o7777777
    -}
    - 
    -const encNumber = (buf, off, size, number) =>
    -  number === null ? false :
    -  number > MAXNUM[size] || number < 0
    -    ? (large.encode(number, buf.slice(off, off + size)), true)
    -    : (encSmallNumber(buf, off, size, number), false)
    - 
    -const encSmallNumber = (buf, off, size, number) =>
    -  buf.write(octalString(number, size), off, size, 'ascii')
    - 
    -const octalString = (number, size) =>
    -  padOctal(Math.floor(number).toString(8), size)
    - 
    -const padOctal = (string, size) =>
    -  (string.length === size - 1 ? string
    -  : new Array(size - string.length - 1).join('0') + string + ' ') + '\0'
    - 
    -const encDate = (buf, off, size, date) =>
    -  date === null ? false :
    -  encNumber(buf, off, size, date.getTime() / 1000)
    - 
    -// enough to fill the longest string we've got
    -const NULLS = new Array(156).join('\0')
    -// pad with nulls, return true if it's longer or non-ascii
    -const encString = (buf, off, size, string) =>
    -  string === null ? false :
    -  (buf.write(string + NULLS, off, size, 'utf8'),
    -   string.length !== Buffer.byteLength(string) || string.length > size)
    - 
    -module.exports = Header
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/high-level-opt.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/high-level-opt.js.html deleted file mode 100644 index 0a59596f75769..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/high-level-opt.js.html +++ /dev/null @@ -1,152 +0,0 @@ - - - - Code coverage report for tar/lib/high-level-opt.js - - - - - - - -
    -
    -

    - All files / tar/lib high-level-opt.js -

    -
    -
    - 100% - Statements - 5/5 -
    -
    - 100% - Branches - 4/4 -
    -
    - 100% - Functions - 3/3 -
    -
    - 100% - Lines - 3/3 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30  -  -  -  -7x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -469x -  -469x - 
    'use strict'
    - 
    -// turn tar(1) style args like `C` into the more verbose things like `cwd`
    - 
    -const argmap = new Map([
    -  ['C', 'cwd'],
    -  ['f', 'file'],
    -  ['z', 'gzip'],
    -  ['P', 'preservePaths'],
    -  ['U', 'unlink'],
    -  ['strip-components', 'strip'],
    -  ['stripComponents', 'strip'],
    -  ['keep-newer', 'newer'],
    -  ['keepNewer', 'newer'],
    -  ['keep-newer-files', 'newer'],
    -  ['keepNewerFiles', 'newer'],
    -  ['k', 'keep'],
    -  ['keep-existing', 'keep'],
    -  ['keepExisting', 'keep'],
    -  ['m', 'noMtime'],
    -  ['no-mtime', 'noMtime'],
    -  ['p', 'preserveOwner'],
    -  ['L', 'follow'],
    -  ['h', 'follow']
    -])
    - 
    -const parse = module.exports = opt => opt ? Object.keys(opt).map(k => [
    -  argmap.has(k) ? argmap.get(k) : k, opt[k]
    -]).reduce((set, kv) => (set[kv[0]] = kv[1], set), Object.create(null)) : {}
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/index.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/index.html deleted file mode 100644 index 1f908d1e77c71..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/index.html +++ /dev/null @@ -1,314 +0,0 @@ - - - - Code coverage report for tar/lib - - - - - - - -
    -
    -

    - All files tar/lib -

    -
    -
    - 99.94% - Statements - 1782/1783 -
    -
    - 99.67% - Branches - 1224/1228 -
    -
    - 100% - Functions - 271/271 -
    -
    - 99.94% - Lines - 1735/1736 -
    -
    -
    -
    -
    - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    FileStatementsBranchesFunctionsLines
    create.js
    100%59/59100%35/35100%12/12100%59/59
    extract.js
    100%61/61100%45/45100%12/12100%60/60
    header.js
    100%161/161100%120/120100%20/20100%159/159
    high-level-opt.js
    100%5/5100%4/4100%3/3100%3/3
    large-numbers.js
    100%59/59100%20/20100%8/8100%57/57
    list.js
    100%80/80100%53/53100%14/14100%77/77
    mkdir.js
    100%130/130100%91/91100%15/15100%128/128
    pack.js
    100%228/228100%123/123100%44/44100%222/222
    parse.js
    100%242/242100%155/155100%24/24100%236/236
    pax.js
    100%62/62100%75/75100%9/9100%60/60
    read-entry.js
    100%53/53100%36/36100%3/3100%51/51
    replace.js
    100%131/131100%70/70100%18/18100%128/128
    types.js
    100%3/3100%0/0100%1/1100%2/2
    unpack.js
    100%254/254100%194/194100%44/44100%247/247
    update.js
    100%20/20100%15/15100%4/4100%20/20
    warn-mixin.js
    100%9/9100%4/4100%2/2100%8/8
    winchars.js
    100%12/12100%0/0100%7/7100%8/8
    write-entry.js
    99.53%213/21497.87%184/188100%31/3199.53%210/211
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/large-numbers.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/large-numbers.js.html deleted file mode 100644 index 5b8610f9b52f3..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/large-numbers.js.html +++ /dev/null @@ -1,341 +0,0 @@ - - - - Code coverage report for tar/lib/large-numbers.js - - - - - - - -
    -
    -

    - All files / tar/lib large-numbers.js -

    -
    -
    - 100% - Statements - 59/59 -
    -
    - 100% - Branches - 20/20 -
    -
    - 100% - Functions - 8/8 -
    -
    - 100% - Lines - 57/57 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93  -  -  -  -  -  -14x -17x -17x -6x -  -11x -17x -  -  -14x -11x -11x -86x -31x -  -55x -55x -  -  -  -  -14x -6x -6x -6x -6x -  -60x -42x -  -18x -18x -  -60x -48x -12x -6x -  -6x -6x -  -  -  -  -14x -47x -47x -47x -  -  -  -14x -6x -6x -6x -6x -60x -  -60x -48x -12x -6x -  -6x -6x -  -60x -12x -  -6x -  -  -14x -41x -41x -41x -266x -266x -161x -  -41x -  -  -96x -  -14x - 
    'use strict'
    -// Tar can encode large and negative numbers using a leading byte of
    -// 0xff for negative, and 0x80 for positive.  The trailing byte in the
    -// section will always be 0x20, or in some implementations 0x00.
    -// this module encodes and decodes these things.
    - 
    -const encode = exports.encode = (num, buf) => {
    -  buf[buf.length - 1] = 0x20
    -  if (num < 0)
    -    encodeNegative(num, buf)
    -  else
    -    encodePositive(num, buf)
    -  return buf
    -}
    - 
    -const encodePositive = (num, buf) => {
    -  buf[0] = 0x80
    -  for (var i = buf.length - 2; i > 0; i--) {
    -    if (num === 0)
    -      buf[i] = 0
    -    else {
    -      buf[i] = num % 0x100
    -      num = Math.floor(num / 0x100)
    -    }
    -  }
    -}
    - 
    -const encodeNegative = (num, buf) => {
    -  buf[0] = 0xff
    -  var flipped = false
    -  num = num * -1
    -  for (var i = buf.length - 2; i > 0; i--) {
    -    var byte
    -    if (num === 0)
    -      byte = 0
    -    else {
    -      byte = num % 0x100
    -      num = Math.floor(num / 0x100)
    -    }
    -    if (flipped)
    -      buf[i] = onesComp(byte)
    -    else if (byte === 0)
    -      buf[i] = 0
    -    else {
    -      flipped = true
    -      buf[i] = twosComp(byte)
    -    }
    -  }
    -}
    - 
    -const parse = exports.parse = (buf) => {
    -  var post = buf[buf.length - 1]
    -  var pre = buf[0]
    -  return pre === 0x80 ? pos(buf.slice(1, buf.length - 1))
    -   : twos(buf.slice(1, buf.length - 1))
    -}
    - 
    -const twos = (buf) => {
    -  var len = buf.length
    -  var sum = 0
    -  var flipped = false
    -  for (var i = len - 1; i > -1; i--) {
    -    var byte = buf[i]
    -    var f
    -    if (flipped)
    -      f = onesComp(byte)
    -    else if (byte === 0)
    -      f = byte
    -    else {
    -      flipped = true
    -      f = twosComp(byte)
    -    }
    -    if (f !== 0)
    -      sum += f * Math.pow(256, len - i - 1)
    -  }
    -  return sum * -1
    -}
    - 
    -const pos = (buf) => {
    -  var len = buf.length
    -  var sum = 0
    -  for (var i = len - 1; i > -1; i--) {
    -    var byte = buf[i]
    -    if (byte !== 0)
    -      sum += byte * Math.pow(256, len - i - 1)
    -  }
    -  return sum
    -}
    - 
    -const onesComp = byte => (0xff ^ byte) & 0xff
    - 
    -const twosComp = byte => ((0xff ^ byte) + 1) & 0xff
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/list.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/list.js.html deleted file mode 100644 index 4e6e34e6543a0..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/list.js.html +++ /dev/null @@ -1,449 +0,0 @@ - - - - Code coverage report for tar/lib/list.js - - - - - - - -
    -
    -

    - All files / tar/lib list.js -

    -
    -
    - 100% - Statements - 80/80 -
    -
    - 100% - Branches - 53/53 -
    -
    - 100% - Functions - 14/14 -
    -
    - 100% - Lines - 77/77 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129  -  -  -  -  -  -5x -5x -5x -5x -5x -  -5x -34x -1x -33x -1x -  -34x -5x -  -34x -31x -  -3x -  -34x -  -34x -1x -  -33x -1x -  -32x -3x -  -32x -22x -  -32x -  -  -  -  -5x -22x -22x -255x -255x -72x -  -  -  -  -5x -6x -3x -  -3x -125x -125x -  -  -  -125x -125x -  -  -3x -32x -64x -  -  -5x -13x -13x -13x -  -13x -13x -12x -12x -10x -  -2x -2x -2x -2x -28x -27x -27x -  -1x -  -11x -  -13x -1x -  -  -  -5x -16x -16x -  -16x -16x -16x -16x -  -16x -16x -2x -  -14x -  -  -  -14x -14x -  -  -  -16x -  -  -16x - 
    'use strict'
    - 
    -// XXX: This shares a lot in common with extract.js
    -// maybe some DRY opportunity here?
    - 
    -// tar -t
    -const hlo = require('./high-level-opt.js')
    -const Parser = require('./parse.js')
    -const fs = require('fs')
    -const fsm = require('fs-minipass')
    -const path = require('path')
    - 
    -const t = module.exports = (opt_, files, cb) => {
    -  if (typeof opt_ === 'function')
    -    cb = opt_, files = null, opt_ = {}
    -  else if (Array.isArray(opt_))
    -    files = opt_, opt_ = {}
    - 
    -  if (typeof files === 'function')
    -    cb = files, files = null
    - 
    -  if (!files)
    -    files = []
    -  else
    -    files = Array.from(files)
    - 
    -  const opt = hlo(opt_)
    - 
    -  if (opt.sync && typeof cb === 'function')
    -    throw new TypeError('callback not supported for sync tar functions')
    - 
    -  if (!opt.file && typeof cb === 'function')
    -    throw new TypeError('callback only supported with file option')
    - 
    -  if (files.length)
    -    filesFilter(opt, files)
    - 
    -  if (!opt.noResume)
    -    onentryFunction(opt)
    - 
    -  return opt.file && opt.sync ? listFileSync(opt)
    -    : opt.file ? listFile(opt, cb)
    -    : list(opt)
    -}
    - 
    -const onentryFunction = opt => {
    -  const onentry = opt.onentry
    -  opt.onentry = onentry ? e => {
    -    onentry(e)
    -    e.resume()
    -  } : e => e.resume()
    -}
    - 
    -// construct a filter that limits the file entries listed
    -// include child entries if a dir is included
    -const filesFilter = (opt, files) => {
    -  const map = new Map(files.map(f => [f.replace(/\/+$/, ''), true]))
    -  const filter = opt.filter
    - 
    -  const mapHas = (file, r) => {
    -    const root = r || path.parse(file).root || '.'
    -    const ret = file === root ? false
    -      : map.has(file) ? map.get(file)
    -      : mapHas(path.dirname(file), root)
    - 
    -    map.set(file, ret)
    -    return ret
    -  }
    - 
    -  opt.filter = filter
    -    ? (file, entry) => filter(file, entry) && mapHas(file.replace(/\/+$/, ''))
    -    : file => mapHas(file.replace(/\/+$/, ''))
    -}
    - 
    -const listFileSync = opt => {
    -  const p = list(opt)
    -  const file = opt.file
    -  let threw = true
    -  let fd
    -  try {
    -    const stat = fs.statSync(file)
    -    const readSize = opt.maxReadSize || 16*1024*1024
    -    if (stat.size < readSize) {
    -      p.end(fs.readFileSync(file))
    -    } else {
    -      let pos = 0
    -      const buf = Buffer.allocUnsafe(readSize)
    -      fd = fs.openSync(file, 'r')
    -      while (pos < stat.size) {
    -        let bytesRead = fs.readSync(fd, buf, 0, readSize, pos)
    -        pos += bytesRead
    -        p.write(buf.slice(0, bytesRead))
    -      }
    -      p.end()
    -    }
    -    threw = false
    -  } finally {
    -    if (threw && fd)
    -      try { fs.closeSync(fd) } catch (er) {}
    -  }
    -}
    - 
    -const listFile = (opt, cb) => {
    -  const parse = new Parser(opt)
    -  const readSize = opt.maxReadSize || 16*1024*1024
    - 
    -  const file = opt.file
    -  const p = new Promise((resolve, reject) => {
    -    parse.on('error', reject)
    -    parse.on('end', resolve)
    - 
    -    fs.stat(file, (er, stat) => {
    -      if (er)
    -        reject(er)
    -      else {
    -        const stream = new fsm.ReadStream(file, {
    -          readSize: readSize,
    -          size: stat.size
    -        })
    -        stream.on('error', reject)
    -        stream.pipe(parse)
    -      }
    -    })
    -  })
    -  return cb ? p.then(cb, cb) : p
    -}
    - 
    -const list = opt => new Parser(opt)
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/mkdir.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/mkdir.js.html deleted file mode 100644 index afeb931676293..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/mkdir.js.html +++ /dev/null @@ -1,686 +0,0 @@ - - - - Code coverage report for tar/lib/mkdir.js - - - - - - - -
    -
    -

    - All files / tar/lib mkdir.js -

    -
    -
    - 100% - Statements - 130/130 -
    -
    - 100% - Branches - 91/91 -
    -
    - 100% - Functions - 15/15 -
    -
    - 100% - Lines - 128/128 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208  -  -  -  -  -  -3x -3x -3x -3x -  -  -  -4x -4x -4x -  -  -  -8x -  -  -  -  -  -12x -12x -12x -  -  -  -36x -  -  -  -3x -  -  -451x -451x -451x -  -451x -451x -451x -  -  -  -451x -451x -451x -451x -  -451x -457x -15x -  -442x -442x -6x -436x -1x -  -435x -  -  -  -451x -272x -  -179x -40x -40x -2x -40x -  -  -139x -8x -  -131x -131x -131x -  -  -3x -1062x -119x -943x -943x -943x -723x -220x -  -  -222x -222x -36x -  -4x -  -32x -32x -4x -28x -22x -6x -3x -3x -1x -2x -  -3x -2x -  -1x -  -  -186x -186x -  -  -  -3x -  -  -276x -276x -276x -  -276x -276x -276x -  -  -  -276x -276x -276x -276x -  -276x -266x -266x -6x -266x -1x -266x -  -  -276x -128x -  -148x -34x -34x -34x -34x -  -1x -  -34x -2x -  -32x -32x -  -  -114x -7x -  -107x -107x -107x -107x -  -  -  -792x -608x -  -184x -184x -169x -169x -  -15x -  -4x -  -11x -9x -4x -4x -5x -2x -2x -2x -2x -2x -3x -2x -  -  -  -99x -  - 
    'use strict'
    -// wrapper around mkdirp for tar's needs.
    - 
    -// TODO: This should probably be a class, not functionally
    -// passing around state in a gazillion args.
    - 
    -const mkdirp = require('mkdirp')
    -const fs = require('fs')
    -const path = require('path')
    -const chownr = require('chownr')
    - 
    -class SymlinkError extends Error {
    -  constructor (symlink, path) {
    -    super('Cannot extract through symbolic link')
    -    this.path = path
    -    this.symlink = symlink
    -  }
    - 
    -  get name () {
    -    return 'SylinkError'
    -  }
    -}
    - 
    -class CwdError extends Error {
    -  constructor (path, code) {
    -    super(code + ': Cannot cd into \'' + path + '\'')
    -    this.path = path
    -    this.code = code
    -  }
    - 
    -  get name () {
    -    return 'CwdError'
    -  }
    -}
    - 
    -const mkdir = module.exports = (dir, opt, cb) => {
    -  // if there's any overlap between mask and mode,
    -  // then we'll need an explicit chmod
    -  const umask = opt.umask
    -  const mode = opt.mode | 0o0700
    -  const needChmod = (mode & umask) !== 0
    - 
    -  const uid = opt.uid
    -  const gid = opt.gid
    -  const doChown = typeof uid === 'number' &&
    -    typeof gid === 'number' &&
    -    ( uid !== opt.processUid || gid !== opt.processGid )
    - 
    -  const preserve = opt.preserve
    -  const unlink = opt.unlink
    -  const cache = opt.cache
    -  const cwd = opt.cwd
    - 
    -  const done = (er, created) => {
    -    if (er)
    -      cb(er)
    -    else {
    -      cache.set(dir, true)
    -      if (created && doChown)
    -        chownr(created, uid, gid, er => done(er))
    -      else if (needChmod)
    -        fs.chmod(dir, mode, cb)
    -      else
    -        cb()
    -    }
    -  }
    - 
    -  if (cache && cache.get(dir) === true)
    -    return done()
    - 
    -  if (dir === cwd)
    -    return fs.lstat(dir, (er, st) => {
    -      if (er || !st.isDirectory())
    -        er = new CwdError(dir, er && er.code || 'ENOTDIR')
    -      done(er)
    -    })
    - 
    -  if (preserve)
    -    return mkdirp(dir, mode, done)
    - 
    -  const sub = path.relative(cwd, dir)
    -  const parts = sub.split(/\/|\\/)
    -  mkdir_(cwd, parts, mode, cache, unlink, cwd, null, done)
    -}
    - 
    -const mkdir_ = (base, parts, mode, cache, unlink, cwd, created, cb) => {
    -  if (!parts.length)
    -    return cb(null, created)
    -  const p = parts.shift()
    -  const part = base + '/' + p
    -  if (cache.get(part))
    -    return mkdir_(part, parts, mode, cache, unlink, cwd, created, cb)
    -  fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb))
    -}
    - 
    -const onmkdir = (part, parts, mode, cache, unlink, cwd, created, cb) => er => {
    -  if (er) {
    -    if (er.path && path.dirname(er.path) === cwd &&
    -        (er.code === 'ENOTDIR' || er.code === 'ENOENT'))
    -      return cb(new CwdError(cwd, er.code))
    - 
    -    fs.lstat(part, (statEr, st) => {
    -      if (statEr)
    -        cb(statEr)
    -      else if (st.isDirectory())
    -        mkdir_(part, parts, mode, cache, unlink, cwd, created, cb)
    -      else if (unlink)
    -        fs.unlink(part, er => {
    -          if (er)
    -            return cb(er)
    -          fs.mkdir(part, mode, onmkdir(part, parts, mode, cache, unlink, cwd, created, cb))
    -        })
    -      else if (st.isSymbolicLink())
    -        return cb(new SymlinkError(part, part + '/' + parts.join('/')))
    -      else
    -        cb(er)
    -    })
    -  } else {
    -    created = created || part
    -    mkdir_(part, parts, mode, cache, unlink, cwd, created, cb)
    -  }
    -}
    - 
    -const mkdirSync = module.exports.sync = (dir, opt) => {
    -  // if there's any overlap between mask and mode,
    -  // then we'll need an explicit chmod
    -  const umask = opt.umask
    -  const mode = opt.mode | 0o0700
    -  const needChmod = (mode & umask) !== 0
    - 
    -  const uid = opt.uid
    -  const gid = opt.gid
    -  const doChown = typeof uid === 'number' &&
    -    typeof gid === 'number' &&
    -    ( uid !== opt.processUid || gid !== opt.processGid )
    - 
    -  const preserve = opt.preserve
    -  const unlink = opt.unlink
    -  const cache = opt.cache
    -  const cwd = opt.cwd
    - 
    -  const done = (created) => {
    -    cache.set(dir, true)
    -    if (created && doChown)
    -      chownr.sync(created, uid, gid)
    -    if (needChmod)
    -      fs.chmodSync(dir, mode)
    -    cache.set(dir, true)
    -  }
    - 
    -  if (cache && cache.get(dir) === true)
    -    return done()
    - 
    -  if (dir === cwd) {
    -    let ok = false
    -    let code = 'ENOTDIR'
    -    try {
    -      ok = fs.lstatSync(dir).isDirectory()
    -    } catch (er) {
    -      code = er.code
    -    } finally {
    -      if (!ok)
    -        throw new CwdError(dir, code)
    -    }
    -    done()
    -    return
    -  }
    - 
    -  if (preserve)
    -    return done(mkdirp.sync(dir, mode))
    - 
    -  const sub = path.relative(cwd, dir)
    -  const parts = sub.split(/\/|\\/)
    -  let created = null
    -  for (let p = parts.shift(), part = cwd;
    -       p && (part += '/' + p);
    -       p = parts.shift()) {
    - 
    -    if (cache.get(part))
    -      continue
    - 
    -    try {
    -      fs.mkdirSync(part, mode)
    -      created = created || part
    -      cache.set(part, true)
    -    } catch (er) {
    -      if (er.path && path.dirname(er.path) === cwd &&
    -          (er.code === 'ENOTDIR' || er.code === 'ENOENT'))
    -        return new CwdError(cwd, er.code)
    - 
    -      const st = fs.lstatSync(part)
    -      if (st.isDirectory()) {
    -        cache.set(part, true)
    -        continue
    -      } else if (unlink) {
    -        fs.unlinkSync(part)
    -        fs.mkdirSync(part, mode)
    -        created = created || part
    -        cache.set(part, true)
    -        continue
    -      } else if (st.isSymbolicLink())
    -        return new SymlinkError(part, part + '/' + parts.join('/'))
    -    }
    -  }
    - 
    -  return done(created)
    -}
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pack.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pack.js.html deleted file mode 100644 index d46f96d8fcbd4..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pack.js.html +++ /dev/null @@ -1,1268 +0,0 @@ - - - - Code coverage report for tar/lib/pack.js - - - - - - - -
    -
    -

    - All files / tar/lib pack.js -

    -
    -
    - 100% - Statements - 228/228 -
    -
    - 100% - Branches - 123/123 -
    -
    - 100% - Functions - 44/44 -
    -
    - 100% - Lines - 222/222 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 -270 -271 -272 -273 -274 -275 -276 -277 -278 -279 -280 -281 -282 -283 -284 -285 -286 -287 -288 -289 -290 -291 -292 -293 -294 -295 -296 -297 -298 -299 -300 -301 -302 -303 -304 -305 -306 -307 -308 -309 -310 -311 -312 -313 -314 -315 -316 -317 -318 -319 -320 -321 -322 -323 -324 -325 -326 -327 -328 -329 -330 -331 -332 -333 -334 -335 -336 -337 -338 -339 -340 -341 -342 -343 -344 -345 -346 -347 -348 -349 -350 -351 -352 -353 -354 -355 -356 -357 -358 -359 -360 -361 -362 -363 -364 -365 -366 -367 -368 -369 -370 -371 -372 -373 -374 -375 -376 -377 -378 -379 -380 -381 -382 -383 -384 -385 -386 -387 -388 -389 -390 -391 -392 -393 -394 -395 -396 -397 -398 -399 -400 -401 -402  -  -  -  -  -  -  -  -  -  -  -  -  -6566x -6566x -6566x -6566x -6566x -6566x -6566x -6566x -  -  -  -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -5x -  -5x -5x -5x -  -5x -  -122x -122x -122x -122x -122x -122x -122x -122x -122x -122x -122x -122x -122x -122x -3x -  -122x -122x -5x -4x -5x -503x -5x -146x -219x -  -117x -  -122x -122x -122x -122x -  -  -6507x -  -122x -122x -122x -122x -122x -  -  -  -106x -  -  -  -107x -103x -  -  -  -100x -21x -99x -99x -99x -  -  -  -128x -1x -  -127x -27x -  -100x -123x -  -  -  -27x -27x -1x -  -  -27x -2x -  -25x -25x -25x -25x -25x -  -  -27x -  -  -  -6541x -6541x -34x -  -6541x -6541x -  -  -  -6453x -6453x -6453x -6453x -6453x -6453x -6453x -1x -  -6452x -  -  -  -  -6538x -6538x -  -  -6538x -24x -  -6538x -  -  -  -821x -821x -821x -821x -821x -821x -1x -820x -  -  -  -  -858x -858x -858x -  -  -  -20596x -9093x -  -11503x -11503x -  -  -38739x -38735x -25x -25x -25x -  -  -  -11499x -  -11499x -96x -4x -  -92x -92x -  -  -  -  -  -25863x -  -  -  -6533x -6533x -6533x -  -  -  -38739x -6156x -  -32583x -18770x -4954x -18770x -  -  -13813x -6541x -4x -  -6537x -  -13811x -6453x -  -  -7358x -24x -  -7334x -860x -2x -  -858x -859x -821x -  -  -  -6512x -6511x -1x -1x -  -  -6510x -1581x -  -  -  -6537x -  -1x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -6512x -6512x -6512x -6508x -1x -  -2x -  -  -  -  -248x -158x -  -  -  -  -6448x -  -6448x -820x -6393x -  -  -  -6393x -6393x -  -  -6448x -6448x -  -6448x -6336x -11830x -156x -  -  -112x -199x -53x -  -  -  -  -265x -214x -265x -  -  -  -  -  -47x -47x -  -  -  -  -  -  -  -84x -84x -  -  -  -37x -  -  -  -  -87x -87x -  -87x -38x -48x -  -  -  -  -48x -48x -  -  -87x -31x -39x -  -  -56x -106x -  -  -  -  -5x -  -5x - 
    'use strict'
    - 
    -// A readable tar stream creator
    -// Technically, this is a transform stream that you write paths into,
    -// and tar format comes out of.
    -// The `add()` method is like `write()` but returns this,
    -// and end() return `this` as well, so you can
    -// do `new Pack(opt).add('files').add('dir').end().pipe(output)
    -// You could also do something like:
    -// streamOfPaths().pipe(new Pack()).pipe(new fs.WriteStream('out.tar'))
    - 
    -class PackJob {
    -  constructor (path, absolute) {
    -    this.path = path || './'
    -    this.absolute = absolute
    -    this.entry = null
    -    this.stat = null
    -    this.readdir = null
    -    this.pending = false
    -    this.ignore = false
    -    this.piped = false
    -  }
    -}
    - 
    -const MiniPass = require('minipass')
    -const zlib = require('minizlib')
    -const ReadEntry = require('./read-entry.js')
    -const WriteEntry = require('./write-entry.js')
    -const WriteEntrySync = WriteEntry.Sync
    -const WriteEntryTar = WriteEntry.Tar
    -const Yallist = require('yallist')
    -const EOF = Buffer.alloc(1024)
    -const ONSTAT = Symbol('onStat')
    -const ENDED = Symbol('ended')
    -const QUEUE = Symbol('queue')
    -const CURRENT = Symbol('current')
    -const PROCESS = Symbol('process')
    -const PROCESSING = Symbol('processing')
    -const PROCESSJOB = Symbol('processJob')
    -const JOBS = Symbol('jobs')
    -const JOBDONE = Symbol('jobDone')
    -const ADDFSENTRY = Symbol('addFSEntry')
    -const ADDTARENTRY = Symbol('addTarEntry')
    -const STAT = Symbol('stat')
    -const READDIR = Symbol('readdir')
    -const ONREADDIR = Symbol('onreaddir')
    -const PIPE = Symbol('pipe')
    -const ENTRY = Symbol('entry')
    -const ENTRYOPT = Symbol('entryOpt')
    -const WRITEENTRYCLASS = Symbol('writeEntryClass')
    -const WRITE = Symbol('write')
    -const ONDRAIN = Symbol('ondrain')
    - 
    -const fs = require('fs')
    -const path = require('path')
    -const warner = require('./warn-mixin.js')
    - 
    -const Pack = warner(class Pack extends MiniPass {
    -  constructor (opt) {
    -    super(opt)
    -    opt = opt || Object.create(null)
    -    this.opt = opt
    -    this.cwd = opt.cwd || process.cwd()
    -    this.maxReadSize = opt.maxReadSize
    -    this.preservePaths = !!opt.preservePaths
    -    this.strict = !!opt.strict
    -    this.noPax = !!opt.noPax
    -    this.prefix = (opt.prefix || '').replace(/(\\|\/)+$/, '')
    -    this.linkCache = opt.linkCache || new Map()
    -    this.statCache = opt.statCache || new Map()
    -    this.readdirCache = opt.readdirCache || new Map()
    -    this[WRITEENTRYCLASS] = WriteEntry
    -    if (typeof opt.onwarn === 'function')
    -      this.on('warn', opt.onwarn)
    - 
    -    this.zip = null
    -    if (opt.gzip) {
    -      if (typeof opt.gzip !== 'object')
    -        opt.gzip = {}
    -      this.zip = new zlib.Gzip(opt.gzip)
    -      this.zip.on('data', chunk => super.write(chunk))
    -      this.zip.on('end', _ => super.end())
    -      this.zip.on('drain', _ => this[ONDRAIN]())
    -      this.on('resume', _ => this.zip.resume())
    -    } else
    -      this.on('drain', this[ONDRAIN])
    - 
    -    this.portable = !!opt.portable
    -    this.noDirRecurse = !!opt.noDirRecurse
    -    this.follow = !!opt.follow
    -    this.noMtime = !!opt.noMtime
    - 
    - 
    -    this.filter = typeof opt.filter === 'function' ? opt.filter : _ => true
    - 
    -    this[QUEUE] = new Yallist
    -    this[JOBS] = 0
    -    this.jobs = +opt.jobs || 4
    -    this[PROCESSING] = false
    -    this[ENDED] = false
    -  }
    - 
    -  [WRITE] (chunk) {
    -    return super.write(chunk)
    -  }
    - 
    -  add (path) {
    -    this.write(path)
    -    return this
    -  }
    - 
    -  end (path) {
    -    if (path)
    -      this.write(path)
    -    this[ENDED] = true
    -    this[PROCESS]()
    -    return this
    -  }
    - 
    -  write (path) {
    -    if (this[ENDED])
    -      throw new Error('write after end')
    - 
    -    if (path instanceof ReadEntry)
    -      this[ADDTARENTRY](path)
    -    else
    -      this[ADDFSENTRY](path)
    -    return this.flowing
    -  }
    - 
    -  [ADDTARENTRY] (p) {
    -    const absolute = path.resolve(this.cwd, p.path)
    -    if (this.prefix)
    -      p.path = this.prefix + '/' + p.path.replace(/^\.(\/+|$)/, '')
    - 
    -    // in this case, we don't have to wait for the stat
    -    if (!this.filter(p.path, p))
    -      p.resume()
    -    else {
    -      const job = new PackJob(p.path, absolute, false)
    -      job.entry = new WriteEntryTar(p, this[ENTRYOPT](job))
    -      job.entry.on('end', _ => this[JOBDONE](job))
    -      this[JOBS] += 1
    -      this[QUEUE].push(job)
    -    }
    - 
    -    this[PROCESS]()
    -  }
    - 
    -  [ADDFSENTRY] (p) {
    -    const absolute = path.resolve(this.cwd, p)
    -    if (this.prefix)
    -      p = this.prefix + '/' + p.replace(/^\.(\/+|$)/, '')
    - 
    -    this[QUEUE].push(new PackJob(p, absolute))
    -    this[PROCESS]()
    -  }
    - 
    -  [STAT] (job) {
    -    job.pending = true
    -    this[JOBS] += 1
    -    const stat = this.follow ? 'stat' : 'lstat'
    -    fs[stat](job.absolute, (er, stat) => {
    -      job.pending = false
    -      this[JOBS] -= 1
    -      if (er)
    -        this.emit('error', er)
    -      else
    -        this[ONSTAT](job, stat)
    -    })
    -  }
    - 
    -  [ONSTAT] (job, stat) {
    -    this.statCache.set(job.absolute, stat)
    -    job.stat = stat
    - 
    -    // now we have the stat, we can filter it.
    -    if (!this.filter(job.path, stat))
    -      job.ignore = true
    - 
    -    this[PROCESS]()
    -  }
    - 
    -  [READDIR] (job) {
    -    job.pending = true
    -    this[JOBS] += 1
    -    fs.readdir(job.absolute, (er, entries) => {
    -      job.pending = false
    -      this[JOBS] -= 1
    -      if (er)
    -        return this.emit('error', er)
    -      this[ONREADDIR](job, entries)
    -    })
    -  }
    - 
    -  [ONREADDIR] (job, entries) {
    -    this.readdirCache.set(job.absolute, entries)
    -    job.readdir = entries
    -    this[PROCESS]()
    -  }
    - 
    -  [PROCESS] () {
    -    if (this[PROCESSING])
    -      return
    - 
    -    this[PROCESSING] = true
    -    for (let w = this[QUEUE].head;
    -         w !== null && this[JOBS] < this.jobs;
    -         w = w.next) {
    -      this[PROCESSJOB](w.value)
    -      if (w.value.ignore) {
    -        const p = w.next
    -        this[QUEUE].removeNode(w)
    -        w.next = p
    -      }
    -    }
    - 
    -    this[PROCESSING] = false
    - 
    -    if (this[ENDED] && !this[QUEUE].length && this[JOBS] === 0) {
    -      if (this.zip)
    -        this.zip.end(EOF)
    -      else {
    -        super.write(EOF)
    -        super.end()
    -      }
    -    }
    -  }
    - 
    -  get [CURRENT] () {
    -    return this[QUEUE] && this[QUEUE].head && this[QUEUE].head.value
    -  }
    - 
    -  [JOBDONE] (job) {
    -    this[QUEUE].shift()
    -    this[JOBS] -= 1
    -    this[PROCESS]()
    -  }
    - 
    -  [PROCESSJOB] (job) {
    -    if (job.pending)
    -      return
    - 
    -    if (job.entry) {
    -      if (job === this[CURRENT] && !job.piped)
    -        this[PIPE](job)
    -      return
    -    }
    - 
    -    if (!job.stat) {
    -      if (this.statCache.has(job.absolute))
    -        this[ONSTAT](job, this.statCache.get(job.absolute))
    -      else
    -        this[STAT](job)
    -    }
    -    if (!job.stat)
    -      return
    - 
    -    // filtered out!
    -    if (job.ignore)
    -      return
    - 
    -    if (!this.noDirRecurse && job.stat.isDirectory() && !job.readdir) {
    -      if (this.readdirCache.has(job.absolute))
    -        this[ONREADDIR](job, this.readdirCache.get(job.absolute))
    -      else
    -        this[READDIR](job)
    -      if (!job.readdir)
    -        return
    -    }
    - 
    -    // we know it doesn't have an entry, because that got checked above
    -    job.entry = this[ENTRY](job)
    -    if (!job.entry) {
    -      job.ignore = true
    -      return
    -    }
    - 
    -    if (job === this[CURRENT] && !job.piped)
    -      this[PIPE](job)
    -  }
    - 
    -  [ENTRYOPT] (job) {
    -    return {
    -      onwarn: (msg, data) => {
    -        this.warn(msg, data)
    -      },
    -      noPax: this.noPax,
    -      cwd: this.cwd,
    -      absolute: job.absolute,
    -      preservePaths: this.preservePaths,
    -      maxReadSize: this.maxReadSize,
    -      strict: this.strict,
    -      portable: this.portable,
    -      linkCache: this.linkCache,
    -      statCache: this.statCache,
    -      noMtime: this.noMtime
    -    }
    -  }
    - 
    -  [ENTRY] (job) {
    -    this[JOBS] += 1
    -    try {
    -      return new this[WRITEENTRYCLASS](job.path, this[ENTRYOPT](job))
    -        .on('end', () => this[JOBDONE](job))
    -        .on('error', er => this.emit('error', er))
    -    } catch (er) {
    -      this.emit('error', er)
    -    }
    -  }
    - 
    -  [ONDRAIN] () {
    -    if (this[CURRENT] && this[CURRENT].entry)
    -      this[CURRENT].entry.resume()
    -  }
    - 
    -  // like .pipe() but using super, because our write() is special
    -  [PIPE] (job) {
    -    job.piped = true
    - 
    -    if (job.readdir)
    -      job.readdir.forEach(entry => {
    -        const p = this.prefix ?
    -          job.path.slice(this.prefix.length + 1) || './'
    -          : job.path
    - 
    -        const base = p === './' ? '' : p.replace(/\/*$/, '/')
    -        this[ADDFSENTRY](base + entry)
    -      })
    - 
    -    const source = job.entry
    -    const zip = this.zip
    - 
    -    if (zip)
    -      source.on('data', chunk => {
    -        if (!zip.write(chunk))
    -          source.pause()
    -      })
    -    else
    -      source.on('data', chunk => {
    -        if (!super.write(chunk))
    -          source.pause()
    -      })
    -  }
    - 
    -  pause () {
    -    if (this.zip)
    -      this.zip.pause()
    -    return super.pause()
    -  }
    -})
    - 
    -class PackSync extends Pack {
    -  constructor (opt) {
    -    super(opt)
    -    this[WRITEENTRYCLASS] = WriteEntrySync
    -  }
    - 
    -  // pause/resume are no-ops in sync streams.
    -  pause () {}
    -  resume () {}
    - 
    -  [STAT] (job) {
    -    const stat = this.follow ? 'statSync' : 'lstatSync'
    -    this[ONSTAT](job, fs[stat](job.absolute))
    -  }
    - 
    -  [READDIR] (job, stat) {
    -    this[ONREADDIR](job, fs.readdirSync(job.absolute))
    -  }
    - 
    -  // gotta get it all in this tick
    -  [PIPE] (job) {
    -    const source = job.entry
    -    const zip = this.zip
    - 
    -    if (job.readdir)
    -      job.readdir.forEach(entry => {
    -        const p = this.prefix ?
    -          job.path.slice(this.prefix.length + 1) || './'
    -          : job.path
    - 
    - 
    -        const base = p === './' ? '' : p.replace(/\/*$/, '/')
    -        this[ADDFSENTRY](base + entry)
    -      })
    - 
    -    if (zip)
    -      source.on('data', chunk => {
    -        zip.write(chunk)
    -      })
    -    else
    -      source.on('data', chunk => {
    -        super[WRITE](chunk)
    -      })
    -  }
    -}
    - 
    -Pack.Sync = PackSync
    - 
    -module.exports = Pack
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/parse.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/parse.js.html deleted file mode 100644 index 1d505abe68199..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/parse.js.html +++ /dev/null @@ -1,1310 +0,0 @@ - - - - Code coverage report for tar/lib/parse.js - - - - - - - -
    -
    -

    - All files / tar/lib parse.js -

    -
    -
    - 100% - Statements - 242/242 -
    -
    - 100% - Branches - 155/155 -
    -
    - 100% - Functions - 24/24 -
    -
    - 100% - Lines - 236/236 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 -270 -271 -272 -273 -274 -275 -276 -277 -278 -279 -280 -281 -282 -283 -284 -285 -286 -287 -288 -289 -290 -291 -292 -293 -294 -295 -296 -297 -298 -299 -300 -301 -302 -303 -304 -305 -306 -307 -308 -309 -310 -311 -312 -313 -314 -315 -316 -317 -318 -319 -320 -321 -322 -323 -324 -325 -326 -327 -328 -329 -330 -331 -332 -333 -334 -335 -336 -337 -338 -339 -340 -341 -342 -343 -344 -345 -346 -347 -348 -349 -350 -351 -352 -353 -354 -355 -356 -357 -358 -359 -360 -361 -362 -363 -364 -365 -366 -367 -368 -369 -370 -371 -372 -373 -374 -375 -376 -377 -378 -379 -380 -381 -382 -383 -384 -385 -386 -387 -388 -389 -390 -391 -392 -393 -394 -395 -396 -397 -398 -399 -400 -401 -402 -403 -404 -405 -406 -407 -408 -409 -410 -411 -412 -413 -414 -415 -416  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -9x -9x -9x -9x -9x -9x -9x -9x -9x -  -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -9x -  -2032x -  -9x -  -742x -742x -  -742x -134x -  -608x -589x -589x -589x -589x -  -  -742x -742x -742x -  -  -742x -742x -  -742x -742x -742x -742x -742x -742x -742x -742x -742x -742x -742x -742x -36x -742x -34x -  -  -  -6101x -  -6101x -1834x -4267x -160x -4107x -40x -  -4067x -4067x -40x -4027x -40x -  -3987x -  -3987x -759x -260x -260x -260x -499x -455x -475x -455x -  -  -  -3228x -3228x -3228x -1070x -1070x -  -2158x -1028x -  -1130x -1130x -  -  -2158x -1675x -1675x -  -483x -  -  -  -  -  -  -  -4299x -  -4299x -1653x -1653x -2646x -490x -  -2156x -2156x -2150x -1288x -1288x -  -  -  -4293x -  -  -  -2947x -  -2941x -  -  -  -  -  -  -  -2478x -2478x -2478x -2468x -516x -  -10x -  -  -  -  -  -2194x -2194x -2194x -  -  -2194x -  -2194x -2121x -2121x -2121x -  -  -2194x -  -  -  -475x -475x -  -  -475x -455x -  -475x -  -  -  -4328x -3815x -  -513x -  -  -  -455x -455x -  -  -351x -351x -  -  -44x -44x -  -  -  -40x -40x -40x -  -  -20x -20x -20x -  -  -  -  -  -  -  -2x -2x -2x -  -  -  -669590x -1x -  -  -669589x -944x -224x -224x -  -944x -224x -224x -  -720x -947x -493x -  -720x -227x -227x -227x -20164x -227x -2x -227x -226x -226x -  -227x -  -  -  -669138x -669138x -33586x -  -635552x -669132x -  -  -  -669132x -  -  -  -  -669132x -63x -  -669132x -  -  -  -652869x -652866x -  -  -  -3449x -709x -709x -709x -2x -2x -  -2x -1x -2x -  -709x -  -  -  -  -655942x -10x -655932x -381x -  -655551x -655551x -652859x -652859x -652859x -652859x -  -2692x -  -  -655545x -2x -2x -2x -  -655545x -  -  -655936x -3068x -  -  -  -  -  -655553x -655553x -655553x -8295x -  -6101x -6095x -6095x -  -  -  -1719x -1719x -  -  -475x -475x -  -  -  -  -  -  -  -655547x -652863x -1x -  -652862x -  -  -  -  -718x -717x -113x -  -604x -604x -  -  -  -  - 
    'use strict'
    - 
    -// this[BUFFER] is the remainder of a chunk if we're waiting for
    -// the full 512 bytes of a header to come in.  We will Buffer.concat()
    -// it to the next write(), which is a mem copy, but a small one.
    -//
    -// this[QUEUE] is a Yallist of entries that haven't been emitted
    -// yet this can only get filled up if the user keeps write()ing after
    -// a write() returns false, or does a write() with more than one entry
    -//
    -// We don't buffer chunks, we always parse them and either create an
    -// entry, or push it into the active entry.  The ReadEntry class knows
    -// to throw data away if .ignore=true
    -//
    -// Shift entry off the buffer when it emits 'end', and emit 'entry' for
    -// the next one in the list.
    -//
    -// At any time, we're pushing body chunks into the entry at WRITEENTRY,
    -// and waiting for 'end' on the entry at READENTRY
    -//
    -// ignored entries get .resume() called on them straight away
    - 
    -const warner = require('./warn-mixin.js')
    -const path = require('path')
    -const Header = require('./header.js')
    -const EE = require('events')
    -const Yallist = require('yallist')
    -const maxMetaEntrySize = 1024 * 1024
    -const Entry = require('./read-entry.js')
    -const Pax = require('./pax.js')
    -const zlib = require('minizlib')
    - 
    -const gzipHeader = new Buffer([0x1f, 0x8b])
    -const STATE = Symbol('state')
    -const WRITEENTRY = Symbol('writeEntry')
    -const READENTRY = Symbol('readEntry')
    -const NEXTENTRY = Symbol('nextEntry')
    -const PROCESSENTRY = Symbol('processEntry')
    -const EX = Symbol('extendedHeader')
    -const GEX = Symbol('globalExtendedHeader')
    -const META = Symbol('meta')
    -const EMITMETA = Symbol('emitMeta')
    -const BUFFER = Symbol('buffer')
    -const QUEUE = Symbol('queue')
    -const ENDED = Symbol('ended')
    -const EMITTEDEND = Symbol('emittedEnd')
    -const EMIT = Symbol('emit')
    -const UNZIP = Symbol('unzip')
    -const CONSUMECHUNK = Symbol('consumeChunk')
    -const CONSUMECHUNKSUB = Symbol('consumeChunkSub')
    -const CONSUMEBODY = Symbol('consumeBody')
    -const CONSUMEMETA = Symbol('consumeMeta')
    -const CONSUMEHEADER = Symbol('consumeHeader')
    -const CONSUMING = Symbol('consuming')
    -const BUFFERCONCAT = Symbol('bufferConcat')
    -const MAYBEEND = Symbol('maybeEnd')
    -const WRITING = Symbol('writing')
    -const ABORTED = Symbol('aborted')
    -const DONE = Symbol('onDone')
    - 
    -const noop = _ => true
    - 
    -module.exports = warner(class Parser extends EE {
    -  constructor (opt) {
    -    opt = opt || {}
    -    super(opt)
    - 
    -    if (opt.ondone)
    -      this.on(DONE, opt.ondone)
    -    else
    -      this.on(DONE, _ => {
    -        this.emit('prefinish')
    -        this.emit('finish')
    -        this.emit('end')
    -        this.emit('close')
    -      })
    - 
    -    this.strict = !!opt.strict
    -    this.maxMetaEntrySize = opt.maxMetaEntrySize || maxMetaEntrySize
    -    this.filter = typeof opt.filter === 'function' ? opt.filter : noop
    - 
    -    // have to set this so that streams are ok piping into it
    -    this.writable = true
    -    this.readable = false
    - 
    -    this[QUEUE] = new Yallist()
    -    this[BUFFER] = null
    -    this[READENTRY] = null
    -    this[WRITEENTRY] = null
    -    this[STATE] = 'begin'
    -    this[META] = ''
    -    this[EX] = null
    -    this[GEX] = null
    -    this[ENDED] = false
    -    this[UNZIP] = null
    -    this[ABORTED] = false
    -    if (typeof opt.onwarn === 'function')
    -      this.on('warn', opt.onwarn)
    -    if (typeof opt.onentry === 'function')
    -      this.on('entry', opt.onentry)
    -  }
    - 
    -  [CONSUMEHEADER] (chunk, position) {
    -    const header = new Header(chunk, position)
    - 
    -    if (header.nullBlock)
    -      this[EMIT]('nullBlock')
    -    else if (!header.cksumValid)
    -      this.warn('invalid entry', header)
    -    else if (!header.path)
    -      this.warn('invalid: path is required', header)
    -    else {
    -      const type = header.type
    -      if (/^(Symbolic)?Link$/.test(type) && !header.linkpath)
    -        this.warn('invalid: linkpath required', header)
    -      else if (!/^(Symbolic)?Link$/.test(type) && header.linkpath)
    -        this.warn('invalid: linkpath forbidden', header)
    -      else {
    -        const entry = this[WRITEENTRY] = new Entry(header, this[EX], this[GEX])
    - 
    -        if (entry.meta) {
    -          if (entry.size > this.maxMetaEntrySize) {
    -            entry.ignore = true
    -            this[EMIT]('ignoredEntry', entry)
    -            this[STATE] = 'ignore'
    -          } else if (entry.size > 0) {
    -            this[META] = ''
    -            entry.on('data', c => this[META] += c)
    -            this[STATE] = 'meta'
    -          }
    -        } else {
    - 
    -          this[EX] = null
    -          entry.ignore = entry.ignore || !this.filter(entry.path, entry)
    -          if (entry.ignore) {
    -            this[EMIT]('ignoredEntry', entry)
    -            this[STATE] = entry.remain ? 'ignore' : 'begin'
    -          } else {
    -            if (entry.remain)
    -              this[STATE] = 'body'
    -            else {
    -              this[STATE] = 'begin'
    -              entry.end()
    -            }
    - 
    -            if (!this[READENTRY]) {
    -              this[QUEUE].push(entry)
    -              this[NEXTENTRY]()
    -            } else
    -              this[QUEUE].push(entry)
    -          }
    -        }
    -      }
    -    }
    -  }
    - 
    -  [PROCESSENTRY] (entry) {
    -    let go = true
    - 
    -    if (!entry) {
    -      this[READENTRY] = null
    -      go = false
    -    } else if (Array.isArray(entry))
    -      this.emit.apply(this, entry)
    -    else {
    -      this[READENTRY] = entry
    -      this.emit('entry', entry)
    -      if (!entry.emittedEnd) {
    -        entry.on('end', _ => this[NEXTENTRY]())
    -        go = false
    -      }
    -    }
    - 
    -    return go
    -  }
    - 
    -  [NEXTENTRY] () {
    -    do {} while (this[PROCESSENTRY](this[QUEUE].shift()))
    - 
    -    if (!this[QUEUE].length) {
    -      // At this point, there's nothing in the queue, but we may have an
    -      // entry which is being consumed (readEntry).
    -      // If we don't, then we definitely can handle more data.
    -      // If we do, and either it's flowing, or it has never had any data
    -      // written to it, then it needs more.
    -      // The only other possibility is that it has returned false from a
    -      // write() call, so we wait for the next drain to continue.
    -      const re = this[READENTRY]
    -      const drainNow = !re || re.flowing || re.size === re.remain
    -      if (drainNow) {
    -        if (!this[WRITING])
    -          this.emit('drain')
    -      } else
    -        re.once('drain', _ => this.emit('drain'))
    -     }
    -  }
    - 
    -  [CONSUMEBODY] (chunk, position) {
    -    // write up to but no  more than writeEntry.blockRemain
    -    const entry = this[WRITEENTRY]
    -    const br = entry.blockRemain
    -    const c = (br >= chunk.length && position === 0) ? chunk
    -      : chunk.slice(position, position + br)
    - 
    -    entry.write(c)
    - 
    -    if (!entry.blockRemain) {
    -      this[STATE] = 'begin'
    -      this[WRITEENTRY] = null
    -      entry.end()
    -    }
    - 
    -    return c.length
    -  }
    - 
    -  [CONSUMEMETA] (chunk, position) {
    -    const entry = this[WRITEENTRY]
    -    const ret = this[CONSUMEBODY](chunk, position)
    - 
    -    // if we finished, then the entry is reset
    -    if (!this[WRITEENTRY])
    -      this[EMITMETA](entry)
    - 
    -    return ret
    -  }
    - 
    -  [EMIT] (ev, data, extra) {
    -    if (!this[QUEUE].length && !this[READENTRY])
    -      this.emit(ev, data, extra)
    -    else
    -      this[QUEUE].push([ev, data, extra])
    -  }
    - 
    -  [EMITMETA] (entry) {
    -    this[EMIT]('meta', this[META])
    -    switch (entry.type) {
    -      case 'ExtendedHeader':
    -      case 'OldExtendedHeader':
    -        this[EX] = Pax.parse(this[META], this[EX], false)
    -        break
    - 
    -      case 'GlobalExtendedHeader':
    -        this[GEX] = Pax.parse(this[META], this[GEX], true)
    -        break
    - 
    -      case 'NextFileHasLongPath':
    -      case 'OldGnuLongPath':
    -        this[EX] = this[EX] || Object.create(null)
    -        this[EX].path = this[META].replace(/\0.*/, '')
    -        break
    - 
    -      case 'NextFileHasLongLinkpath':
    -        this[EX] = this[EX] || Object.create(null)
    -        this[EX].linkpath = this[META].replace(/\0.*/, '')
    -        break
    - 
    -      /* istanbul ignore next */
    -      default: throw new Error('unknown meta: ' + entry.type)
    -    }
    -  }
    - 
    -  abort (msg, error) {
    -    this[ABORTED] = true
    -    this.warn(msg, error)
    -    this.emit('abort')
    -  }
    - 
    -  write (chunk) {
    -    if (this[ABORTED])
    -      return
    - 
    -    // first write, might be gzipped
    -    if (this[UNZIP] === null && chunk) {
    -      if (this[BUFFER]) {
    -        chunk = Buffer.concat([this[BUFFER], chunk])
    -        this[BUFFER] = null
    -      }
    -      if (chunk.length < gzipHeader.length) {
    -        this[BUFFER] = chunk
    -        return true
    -      }
    -      for (let i = 0; this[UNZIP] === null && i < gzipHeader.length; i++) {
    -        if (chunk[i] !== gzipHeader[i])
    -          this[UNZIP] = false
    -      }
    -      if (this[UNZIP] === null) {
    -        const ended = this[ENDED]
    -        this[ENDED] = false
    -        this[UNZIP] = new zlib.Unzip()
    -        this[UNZIP].on('data', chunk => this[CONSUMECHUNK](chunk))
    -        this[UNZIP].on('error', er =>
    -          this.abort('zlib error: ' + er.message, er))
    -        this[UNZIP].on('end', _ => {
    -          this[ENDED] = true
    -          this[CONSUMECHUNK]()
    -        })
    -        return ended ? this[UNZIP].end(chunk) : this[UNZIP].write(chunk)
    -      }
    -    }
    - 
    -    this[WRITING] = true
    -    if (this[UNZIP])
    -      this[UNZIP].write(chunk)
    -    else
    -      this[CONSUMECHUNK](chunk)
    -    this[WRITING] = false
    - 
    -    // return false if there's a queue, or if the current entry isn't flowing
    -    const ret =
    -      this[QUEUE].length ? false :
    -      this[READENTRY] ? this[READENTRY].flowing :
    -      true
    - 
    -    // if we have no queue, then that means a clogged READENTRY
    -    if (!ret && !this[QUEUE].length)
    -      this[READENTRY].once('drain', _ => this.emit('drain'))
    - 
    -    return ret
    -  }
    - 
    -  [BUFFERCONCAT] (c) {
    -    if (c && !this[ABORTED])
    -      this[BUFFER] = this[BUFFER] ? Buffer.concat([this[BUFFER], c]) : c
    -  }
    - 
    -  [MAYBEEND] () {
    -    if (this[ENDED] && !this[EMITTEDEND] && !this[ABORTED]) {
    -      this[EMITTEDEND] = true
    -      const entry = this[WRITEENTRY]
    -      if (entry && entry.blockRemain) {
    -        const have = this[BUFFER] ? this[BUFFER].length : 0
    -        this.warn('Truncated input (needed ' + entry.blockRemain +
    -                  ' more bytes, only ' + have + ' available)', entry)
    -        if (this[BUFFER])
    -          entry.write(this[BUFFER])
    -        entry.end()
    -      }
    -      this[EMIT](DONE)
    -    }
    -  }
    - 
    -  [CONSUMECHUNK] (chunk) {
    -    if (this[CONSUMING]) {
    -      this[BUFFERCONCAT](chunk)
    -    } else if (!chunk && !this[BUFFER]) {
    -      this[MAYBEEND]()
    -    } else {
    -      this[CONSUMING] = true
    -      if (this[BUFFER]) {
    -        this[BUFFERCONCAT](chunk)
    -        const c = this[BUFFER]
    -        this[BUFFER] = null
    -        this[CONSUMECHUNKSUB](c)
    -      } else {
    -        this[CONSUMECHUNKSUB](chunk)
    -      }
    - 
    -      while (this[BUFFER] && this[BUFFER].length >= 512 && !this[ABORTED]) {
    -        const c = this[BUFFER]
    -        this[BUFFER] = null
    -        this[CONSUMECHUNKSUB](c)
    -      }
    -      this[CONSUMING] = false
    -    }
    - 
    -    if (!this[BUFFER] || this[ENDED])
    -      this[MAYBEEND]()
    -  }
    - 
    -  [CONSUMECHUNKSUB] (chunk) {
    -    // we know that we are in CONSUMING mode, so anything written goes into
    -    // the buffer.  Advance the position and put any remainder in the buffer.
    -    let position = 0
    -    let length = chunk.length
    -    while (position + 512 <= length && !this[ABORTED]) {
    -      switch (this[STATE]) {
    -        case 'begin':
    -          this[CONSUMEHEADER](chunk, position)
    -          position += 512
    -          break
    - 
    -        case 'ignore':
    -        case 'body':
    -          position += this[CONSUMEBODY](chunk, position)
    -          break
    - 
    -        case 'meta':
    -          position += this[CONSUMEMETA](chunk, position)
    -          break
    - 
    -        /* istanbul ignore next */
    -        default:
    -          throw new Error('invalid state: ' + this[STATE])
    -      }
    -    }
    - 
    -    if (position < length) {
    -      if (this[BUFFER])
    -        this[BUFFER] = Buffer.concat([chunk.slice(position), this[BUFFER]])
    -      else
    -        this[BUFFER] = chunk.slice(position)
    -    }
    -  }
    - 
    -  end (chunk) {
    -    if (!this[ABORTED]) {
    -      if (this[UNZIP])
    -        this[UNZIP].end(chunk)
    -      else {
    -        this[ENDED] = true
    -        this.write(chunk)
    -      }
    -    }
    -  }
    -})
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pax.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pax.js.html deleted file mode 100644 index ed0e937a1290d..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/pax.js.html +++ /dev/null @@ -1,500 +0,0 @@ - - - - Code coverage report for tar/lib/pax.js - - - - - - - -
    -
    -

    - All files / tar/lib pax.js -

    -
    -
    - 100% - Statements - 62/62 -
    -
    - 100% - Branches - 75/75 -
    -
    - 100% - Functions - 9/9 -
    -
    - 100% - Lines - 60/60 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146  -11x -11x -  -  -  -435x -435x -435x -435x -435x -435x -435x -435x -435x -435x -435x -435x -435x -435x -435x -435x -  -  -  -34x -34x -1x -  -33x -  -  -33x -33x -  -  -33x -16896x -  -  -33x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -33x -  -  -33x -8949x -  -  -33x -  -  -  -34x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -510x -204x -306x -  -306x -  -  -  -306x -  -  -  -306x -306x -30x -306x -306x -  -  -  -401x -  -11x -401x -  -11x -401x -  -  -  -  -11x -2259x -  -  -  -2259x -5x -  -2254x -2254x -2254x -2254x -1x -  -2253x -2253x -  -  -  -2253x -  -  -11x - 
    'use strict'
    -const Header = require('./header.js')
    -const path = require('path')
    - 
    -class Pax {
    -  constructor (obj, global) {
    -    this.atime = obj.atime || null
    -    this.charset = obj.charset || null
    -    this.comment = obj.comment || null
    -    this.ctime = obj.ctime || null
    -    this.gid = obj.gid || null
    -    this.gname = obj.gname || null
    -    this.linkpath = obj.linkpath || null
    -    this.mtime = obj.mtime || null
    -    this.path = obj.path || null
    -    this.size = obj.size || null
    -    this.uid = obj.uid || null
    -    this.uname = obj.uname || null
    -    this.dev = obj.dev || null
    -    this.ino = obj.ino || null
    -    this.nlink = obj.nlink || null
    -    this.global = global || false
    -  }
    - 
    -  encode () {
    -    const body = this.encodeBody()
    -    if (body === '')
    -      return null
    - 
    -    const bodyLen = Buffer.byteLength(body)
    -    // round up to 512 bytes
    -    // add 512 for header
    -    const bufLen = 512 * Math.ceil(1 + bodyLen / 512)
    -    const buf = Buffer.allocUnsafe(bufLen)
    - 
    -    // 0-fill the header section, it might not hit every field
    -    for (let i = 0; i < 512; i++) {
    -      buf[i] = 0
    -    }
    - 
    -    new Header({
    -      // XXX split the path
    -      // then the path should be PaxHeader + basename, but less than 99,
    -      // prepend with the dirname
    -      path: ('PaxHeader/' + path.basename(this.path)).slice(0, 99),
    -      mode: this.mode || 0o644,
    -      uid: this.uid || null,
    -      gid: this.gid || null,
    -      size: bodyLen,
    -      mtime: this.mtime || null,
    -      type: this.global ? 'GlobalExtendedHeader' : 'ExtendedHeader',
    -      linkpath: '',
    -      uname: this.uname || '',
    -      gname: this.gname || '',
    -      devmaj: 0,
    -      devmin: 0,
    -      atime: this.atime || null,
    -      ctime: this.ctime || null
    -    }).encode(buf)
    - 
    -    buf.write(body, 512, bodyLen, 'utf8')
    - 
    -    // null pad after the body
    -    for (let i = bodyLen + 512; i < buf.length; i++) {
    -      buf[i] = 0
    -    }
    - 
    -    return buf
    -  }
    - 
    -  encodeBody () {
    -    return (
    -      this.encodeField('path') +
    -      this.encodeField('ctime') +
    -      this.encodeField('atime') +
    -      this.encodeField('dev') +
    -      this.encodeField('ino') +
    -      this.encodeField('nlink') +
    -      this.encodeField('charset') +
    -      this.encodeField('comment') +
    -      this.encodeField('gid') +
    -      this.encodeField('gname') +
    -      this.encodeField('linkpath') +
    -      this.encodeField('mtime') +
    -      this.encodeField('size') +
    -      this.encodeField('uid') +
    -      this.encodeField('uname')
    -    )
    -  }
    - 
    -  encodeField (field) {
    -    if (this[field] === null || this[field] === undefined)
    -      return ''
    -    const v = this[field] instanceof Date ? this[field].getTime() / 1000
    -      : this[field]
    -    const s = ' ' +
    -      (field === 'dev' || field === 'ino' || field === 'nlink'
    -       ? 'SCHILY.' : '') +
    -      field + '=' + v + '\n'
    -    const byteLen = Buffer.byteLength(s)
    -    // the digits includes the length of the digits in ascii base-10
    -    // so if it's 9 characters, then adding 1 for the 9 makes it 10
    -    // which makes it 11 chars.
    -    let digits = Math.floor(Math.log(byteLen) / Math.log(10)) + 1
    -    if (byteLen + digits >= Math.pow(10, digits))
    -      digits += 1
    -    const len = digits + byteLen
    -    return len + s
    -  }
    -}
    - 
    -Pax.parse = (string, ex, g) => new Pax(merge(parseKV(string), ex), g)
    - 
    -const merge = (a, b) =>
    -  b ? Object.keys(a).reduce((s, k) => (s[k] = a[k], s), b) : a
    - 
    -const parseKV = string =>
    -  string
    -    .replace(/\n$/, '')
    -    .split('\n')
    -    .reduce(parseKVLine, Object.create(null))
    - 
    -const parseKVLine = (set, line) => {
    -  const n = parseInt(line, 10)
    - 
    -  // XXX Values with \n in them will fail this.
    -  // Refactor to not be a naive line-by-line parse.
    -  if (n !== Buffer.byteLength(line) + 1)
    -    return set
    - 
    -  line = line.substr((n + ' ').length)
    -  const kv = line.split('=')
    -  const k = kv.shift().replace(/^SCHILY\.(dev|ino|nlink)/, '$1')
    -  if (!k)
    -    return set
    - 
    -  const v = kv.join('=')
    -  set[k] = /^([A-Z]+\.)?([mac]|birth|creation)time$/.test(k)
    -    ?  new Date(v * 1000)
    -    : /^[0-9]+$/.test(v) ? +v
    -    : v
    -  return set
    -}
    - 
    -module.exports = Pax
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/read-entry.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/read-entry.js.html deleted file mode 100644 index 9fca327a291bf..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/read-entry.js.html +++ /dev/null @@ -1,347 +0,0 @@ - - - - Code coverage report for tar/lib/read-entry.js - - - - - - - -
    -
    -

    - All files / tar/lib read-entry.js -

    -
    -
    - 100% - Statements - 53/53 -
    -
    - 100% - Branches - 36/36 -
    -
    - 100% - Functions - 3/3 -
    -
    - 100% - Lines - 51/51 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95  -11x -11x -  -11x -11x -  -4004x -4004x -4004x -4004x -4004x -4004x -4004x -4004x -4004x -4004x -4004x -  -  -  -  -  -  -  -  -  -  -3241x -  -  -  -  -  -  -  -760x -760x -  -  -  -  -3x -  -  -4004x -4004x -4004x -3720x -4004x -4004x -4004x -4004x -4004x -4004x -4004x -4004x -4004x -4004x -4004x -  -4004x -4004x -  -  -  -2222x -2222x -2x -  -2220x -2220x -2220x -2220x -2220x -673x -  -1547x -132x -  -  -1415x -  -  -  -457x -  -  -6384x -  -2657x -  -  -  - 
    'use strict'
    -const types = require('./types.js')
    -const MiniPass = require('minipass')
    - 
    -const SLURP = Symbol('slurp')
    -module.exports = class ReadEntry extends MiniPass {
    -  constructor (header, ex, gex) {
    -    super()
    -    this.extended = ex
    -    this.globalExtended = gex
    -    this.header = header
    -    this.startBlockSize = 512 * Math.ceil(header.size / 512)
    -    this.blockRemain = this.startBlockSize
    -    this.remain = header.size
    -    this.type = header.type
    -    this.meta = false
    -    this.ignore = false
    -    switch (this.type) {
    -      case 'File':
    -      case 'OldFile':
    -      case 'Link':
    -      case 'SymbolicLink':
    -      case 'CharacterDevice':
    -      case 'BlockDevice':
    -      case 'Directory':
    -      case 'FIFO':
    -      case 'ContiguousFile':
    -      case 'GNUDumpDir':
    -        break
    - 
    -      case 'NextFileHasLongLinkpath':
    -      case 'NextFileHasLongPath':
    -      case 'OldGnuLongPath':
    -      case 'GlobalExtendedHeader':
    -      case 'ExtendedHeader':
    -      case 'OldExtendedHeader':
    -        this.meta = true
    -        break
    - 
    -      // NOTE: gnutar and bsdtar treat unrecognized types as 'File'
    -      // it may be worth doing the same, but with a warning.
    -      default:
    -        this.ignore = true
    -    }
    - 
    -    this.path = header.path
    -    this.mode = header.mode
    -    if (this.mode)
    -      this.mode = this.mode & 0o7777
    -    this.uid = header.uid
    -    this.gid = header.gid
    -    this.uname = header.uname
    -    this.gname = header.gname
    -    this.size = header.size
    -    this.mtime = header.mtime
    -    this.atime = header.atime
    -    this.ctime = header.ctime
    -    this.linkpath = header.linkpath
    -    this.uname = header.uname
    -    this.gname = header.gname
    - 
    -    if (ex) this[SLURP](ex)
    -    if (gex) this[SLURP](gex, true)
    -  }
    - 
    -  write (data) {
    -    const writeLen = data.length
    -    if (writeLen > this.blockRemain)
    -      throw new Error('writing more to entry than is appropriate')
    - 
    -    const r = this.remain
    -    const br = this.blockRemain
    -    this.remain = Math.max(0, r - writeLen)
    -    this.blockRemain = Math.max(0, br - writeLen)
    -    if (this.ignore)
    -      return true
    - 
    -    if (r >= writeLen)
    -      return super.write(data)
    - 
    -    // r < writeLen
    -    return super.write(data.slice(0, r))
    -  }
    - 
    -  [SLURP] (ex, global) {
    -    for (let k in ex) {
    -      // we slurp in everything except for the path attribute in
    -      // a global extended header, because that's weird.
    -      if (ex[k] !== null && ex[k] !== undefined &&
    -          !(global && k === 'path'))
    -        this[k] = ex[k]
    -    }
    -  }
    -}
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/replace.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/replace.js.html deleted file mode 100644 index e764c04fbfc45..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/replace.js.html +++ /dev/null @@ -1,722 +0,0 @@ - - - - Code coverage report for tar/lib/replace.js - - - - - - - -
    -
    -

    - All files / tar/lib replace.js -

    -
    -
    - 100% - Statements - 131/131 -
    -
    - 100% - Branches - 70/70 -
    -
    - 100% - Functions - 18/18 -
    -
    - 100% - Lines - 128/128 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220  -  -  -3x -3x -3x -3x -3x -3x -3x -  -  -  -  -  -  -  -3x -  -3x -70x -  -70x -1x -  -69x -1x -  -68x -1x -  -67x -  -67x -  -  -  -3x -26x -  -26x -  -  -  -26x -26x -26x -  -4x -2x -  -2x -  -  -24x -22x -  -22x -61x -63x -  -  -  -61x -2x -  -59x -2x -  -  -55x -55x -8x -47x -47x -2x -  -  -45x -45x -28x -  -18x -  -18x -  -26x -8x -  -  -  -3x -18x -  -  -  -18x -18x -  -  -3x -41x -41x -  -41x -37x -37x -4x -  -33x -  -  -37x -37x -8x -  -29x -29x -29x -112x -2x -110x -110x -6x -  -  -  -  -104x -2x -  -  -102x -4x -  -98x -98x -13x -  -85x -85x -4x -  -81x -81x -4x -  -77x -46x -77x -77x -  -29x -  -  -41x -41x -41x -41x -45x -4x -4x -  -  -41x -2x -  -39x -39x -2x -37x -37x -4x -33x -  -  -  -33x -33x -33x -33x -  -  -  -41x -  -  -41x -  -  -3x -18x -19x -1x -  -  -  -3x -  -  -18x -  -18x -  -  -3x -34x -33x -33x -1x -  -  -3x -1x -  -32x -  -33x -  - 
    'use strict'
    - 
    -// tar -r
    -const hlo = require('./high-level-opt.js')
    -const Pack = require('./pack.js')
    -const Parse = require('./parse.js')
    -const fs = require('fs')
    -const fsm = require('fs-minipass')
    -const t = require('./list.js')
    -const path = require('path')
    - 
    -// starting at the head of the file, read a Header
    -// If the checksum is invalid, that's our position to start writing
    -// If it is, jump forward by the specified size (round up to 512)
    -// and try again.
    -// Write the new Pack stream starting there.
    - 
    -const Header = require('./header.js')
    - 
    -const r = module.exports = (opt_, files, cb) => {
    -  const opt = hlo(opt_)
    - 
    -  if (!opt.file)
    -    throw new TypeError('file is required')
    - 
    -  if (opt.gzip)
    -    throw new TypeError('cannot append to compressed archives')
    - 
    -  if (!files || !Array.isArray(files) || !files.length)
    -    throw new TypeError('no files or directories specified')
    - 
    -  files = Array.from(files)
    - 
    -  return opt.sync ? replaceSync(opt, files)
    -    : replace(opt, files, cb)
    -}
    - 
    -const replaceSync = (opt, files) => {
    -  const p = new Pack.Sync(opt)
    - 
    -  let threw = true
    -  let fd
    -  let position
    - 
    -  try {
    -    try {
    -      fd = fs.openSync(opt.file, 'r+')
    -    } catch (er) {
    -      if (er.code === 'ENOENT')
    -        fd = fs.openSync(opt.file, 'w+')
    -      else
    -        throw er
    -    }
    - 
    -    const st = fs.fstatSync(fd)
    -    const headBuf = Buffer.alloc(512)
    - 
    -    POSITION: for (position = 0; position < st.size; position += 512) {
    -      for (let bufPos = 0, bytes = 0; bufPos < 512; bufPos += bytes) {
    -        bytes = fs.readSync(
    -          fd, headBuf, bufPos, headBuf.length - bufPos, position + bufPos
    -        )
    - 
    -        if (position === 0 && headBuf[0] === 0x1f && headBuf[1] === 0x8b)
    -          throw new Error('cannot append to compressed archives')
    - 
    -        if (!bytes)
    -          break POSITION
    -      }
    - 
    -      let h = new Header(headBuf)
    -      if (!h.cksumValid)
    -        break
    -      let entryBlockSize = 512 * Math.ceil(h.size / 512)
    -      if (position + entryBlockSize + 512 > st.size)
    -        break
    -      // the 512 for the header we just parsed will be added as well
    -      // also jump ahead all the blocks for the body
    -      position += entryBlockSize
    -      if (opt.mtimeCache)
    -        opt.mtimeCache.set(h.path, h.mtime)
    -    }
    -    threw = false
    - 
    -    streamSync(opt, p, position, fd, files)
    -  } finally {
    -    if (threw)
    -      try { fs.closeSync(fd) } catch (er) {}
    -  }
    -}
    - 
    -const streamSync = (opt, p, position, fd, files) => {
    -  const stream = new fsm.WriteStreamSync(opt.file, {
    -    fd: fd,
    -    start: position
    -  })
    -  p.pipe(stream)
    -  addFilesSync(p, files)
    -}
    - 
    -const replace = (opt, files, cb) => {
    -  files = Array.from(files)
    -  const p = new Pack(opt)
    - 
    -  const getPos = (fd, size, cb_) => {
    -    const cb = (er, pos) => {
    -      if (er)
    -        fs.close(fd, _ => cb_(er))
    -      else
    -        cb_(null, pos)
    -    }
    - 
    -    let position = 0
    -    if (size === 0)
    -      return cb(null, 0)
    - 
    -    let bufPos = 0
    -    const headBuf = Buffer.alloc(512)
    -    const onread = (er, bytes) => {
    -      if (er)
    -        return cb(er)
    -      bufPos += bytes
    -      if (bufPos < 512 && bytes)
    -        return fs.read(
    -          fd, headBuf, bufPos, headBuf.length - bufPos,
    -          position + bufPos, onread
    -        )
    - 
    -      if (position === 0 && headBuf[0] === 0x1f && headBuf[1] === 0x8b)
    -        return cb(new Error('cannot append to compressed archives'))
    - 
    -      // truncated header
    -      if (bufPos < 512)
    -        return cb(null, position)
    - 
    -      const h = new Header(headBuf)
    -      if (!h.cksumValid)
    -        return cb(null, position)
    - 
    -      const entryBlockSize = 512 * Math.ceil(h.size / 512)
    -      if (position + entryBlockSize + 512 > size)
    -        return cb(null, position)
    - 
    -      position += entryBlockSize + 512
    -      if (position >= size)
    -        return cb(null, position)
    - 
    -      if (opt.mtimeCache)
    -        opt.mtimeCache.set(h.path, h.mtime)
    -      bufPos = 0
    -      fs.read(fd, headBuf, 0, 512, position, onread)
    -    }
    -    fs.read(fd, headBuf, 0, 512, position, onread)
    -  }
    - 
    -  const promise = new Promise((resolve, reject) => {
    -    p.on('error', reject)
    -    let flag = 'r+'
    -    const onopen = (er, fd) => {
    -      if (er && er.code === 'ENOENT' && flag === 'r+') {
    -        flag = 'w+'
    -        return fs.open(opt.file, flag, onopen)
    -      }
    - 
    -      if (er)
    -        return reject(er)
    - 
    -      fs.fstat(fd, (er, st) => {
    -        if (er)
    -          return reject(er)
    -        getPos(fd, st.size, (er, position) => {
    -          if (er)
    -            return reject(er)
    -          const stream = new fsm.WriteStream(opt.file, {
    -            fd: fd,
    -            start: position
    -          })
    -          p.pipe(stream)
    -          stream.on('error', reject)
    -          stream.on('close', resolve)
    -          addFilesAsync(p, files)
    -        })
    -      })
    -    }
    -    fs.open(opt.file, flag, onopen)
    -  })
    - 
    -  return cb ? promise.then(cb, cb) : promise
    -}
    - 
    -const addFilesSync = (p, files) => {
    -  files.forEach(file => {
    -    if (file.charAt(0) === '@')
    -      t({
    -        file: path.resolve(p.cwd, file.substr(1)),
    -        sync: true,
    -        noResume: true,
    -        onentry: entry => p.add(entry)
    -      })
    -    else
    -      p.add(file)
    -  })
    -  p.end()
    -}
    - 
    -const addFilesAsync = (p, files) => {
    -  while (files.length) {
    -    const file = files.shift()
    -    if (file.charAt(0) === '@')
    -      return t({
    -        file: path.resolve(p.cwd, file.substr(1)),
    -        noResume: true,
    -        onentry: entry => p.add(entry)
    -      }).then(_ => addFilesAsync(p, files))
    -    else
    -      p.add(file)
    -  }
    -  p.end()
    -}
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/types.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/types.js.html deleted file mode 100644 index ad8de07618248..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/types.js.html +++ /dev/null @@ -1,197 +0,0 @@ - - - - Code coverage report for tar/lib/types.js - - - - - - - -
    -
    -

    - All files / tar/lib types.js -

    -
    -
    - 100% - Statements - 3/3 -
    -
    - 100% - Branches - 0/0 -
    -
    - 100% - Functions - 1/1 -
    -
    - 100% - Lines - 2/2 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45  -  -14x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -294x - 
    'use strict'
    -// map types from key to human-friendly name
    -exports.name = new Map([
    -  ['0', 'File'],
    -  // same as File
    -  ['', 'OldFile'],
    -  ['1', 'Link'],
    -  ['2', 'SymbolicLink'],
    -  // Devices and FIFOs aren't fully supported
    -  // they are parsed, but skipped when unpacking
    -  ['3', 'CharacterDevice'],
    -  ['4', 'BlockDevice'],
    -  ['5', 'Directory'],
    -  ['6', 'FIFO'],
    -  // same as File
    -  ['7', 'ContiguousFile'],
    -  // pax headers
    -  ['g', 'GlobalExtendedHeader'],
    -  ['x', 'ExtendedHeader'],
    -  // vendor-specific stuff
    -  // skip
    -  ['A', 'SolarisACL'],
    -  // like 5, but with data, which should be skipped
    -  ['D', 'GNUDumpDir'],
    -  // metadata only, skip
    -  ['I', 'Inode'],
    -  // data = link path of next file
    -  ['K', 'NextFileHasLongLinkpath'],
    -  // data = path of next file
    -  ['L', 'NextFileHasLongPath'],
    -  // skip
    -  ['M', 'ContinuationFile'],
    -  // like L
    -  ['N', 'OldGnuLongPath'],
    -  // skip
    -  ['S', 'SparseFile'],
    -  // skip
    -  ['V', 'TapeVolumeHeader'],
    -  // like x
    -  ['X', 'OldExtendedHeader']
    -])
    - 
    -// map the other direction
    -exports.code = new Map(Array.from(exports.name).map(kv => [kv[1], kv[0]]))
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/unpack.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/unpack.js.html deleted file mode 100644 index 240a6fa310f66..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/unpack.js.html +++ /dev/null @@ -1,1604 +0,0 @@ - - - - Code coverage report for tar/lib/unpack.js - - - - - - - -
    -
    -

    - All files / tar/lib unpack.js -

    -
    -
    - 100% - Statements - 254/254 -
    -
    - 100% - Branches - 194/194 -
    -
    - 100% - Functions - 44/44 -
    -
    - 100% - Lines - 247/247 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 -270 -271 -272 -273 -274 -275 -276 -277 -278 -279 -280 -281 -282 -283 -284 -285 -286 -287 -288 -289 -290 -291 -292 -293 -294 -295 -296 -297 -298 -299 -300 -301 -302 -303 -304 -305 -306 -307 -308 -309 -310 -311 -312 -313 -314 -315 -316 -317 -318 -319 -320 -321 -322 -323 -324 -325 -326 -327 -328 -329 -330 -331 -332 -333 -334 -335 -336 -337 -338 -339 -340 -341 -342 -343 -344 -345 -346 -347 -348 -349 -350 -351 -352 -353 -354 -355 -356 -357 -358 -359 -360 -361 -362 -363 -364 -365 -366 -367 -368 -369 -370 -371 -372 -373 -374 -375 -376 -377 -378 -379 -380 -381 -382 -383 -384 -385 -386 -387 -388 -389 -390 -391 -392 -393 -394 -395 -396 -397 -398 -399 -400 -401 -402 -403 -404 -405 -406 -407 -408 -409 -410 -411 -412 -413 -414 -415 -416 -417 -418 -419 -420 -421 -422 -423 -424 -425 -426 -427 -428 -429 -430 -431 -432 -433 -434 -435 -436 -437 -438 -439 -440 -441 -442 -443 -444 -445 -446 -447 -448 -449 -450 -451 -452 -453 -454 -455 -456 -457 -458 -459 -460 -461 -462 -463 -464 -465 -466 -467 -468 -469 -470 -471 -472 -473 -474 -475 -476 -477 -478 -479 -480 -481 -482 -483 -484 -485 -486 -487 -488 -489 -490 -491 -492 -493 -494 -495 -496 -497 -498 -499 -500 -501 -502 -503 -504 -505 -506 -507 -508 -509 -510 -511 -512 -513 -514  -  -3x -3x -3x -3x -3x -3x -3x -3x -3x -  -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -3x -  -  -3x -60x -  -  -  -  -  -134x -4x -  -134x -109x -109x -  -  -134x -  -134x -134x -  -134x -134x -  -134x -  -134x -  -9x -2x -7x -1x -  -6x -6x -6x -  -125x -125x -125x -  -  -  -131x -119x -  -12x -  -131x -  -131x -  -  -  -131x -  -  -131x -  -  -131x -  -  -131x -  -  -  -  -131x -  -  -  -131x -  -131x -131x -131x -131x -  -131x -131x -571x -  -  -  -473x -98x -98x -98x -98x -  -  -  -  -571x -144x -144x -9x -135x -  -  -562x -545x -545x -2x -2x -  -  -  -  -543x -2x -2x -2x -  -  -  -  -560x -3x -3x -  -  -  -560x -2x -  -558x -  -560x -  -  -  -571x -11x -  -560x -  -560x -  -  -179x -140x -  -  -  -  -  -  -554x -  -  -  -  -6x -  -  -  -  -  -  -  -39x -12x -  -27x -27x -27x -  -  -  -  -451x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -473x -  -  -  -  -  -  -  -  -30x -  -  -  -30x -  -  -  -221x -221x -  -  -  -221x -  -221x -221x -421x -1x -1x -  -  -421x -219x -  -  -221x -219x -192x -192x -  -  -219x -10x -10x -  -  -219x -  -  -221x -  -  -  -97x -97x -97x -3x -  -94x -94x -171x -94x -94x -  -  -  -94x -73x -73x -  -  -94x -4x -4x -  -  -94x -  -  -  -  -6x -6x -  -  -  -21x -  -  -  -19x -  -  -  -354x -  -  -  -364x -364x -  -  -  -4x -4x -  -  -  -  -354x -354x -354x -12x -342x -342x -2x -340x -318x -22x -16x -11x -9x -  -2x -  -5x -  -6x -  -  -  -  -  -528x -1x -  -527x -  -  -  -314x -  -  -19x -  -  -21x -  -  -  -173x -  -  -  -  -  -21x -21x -1x -20x -20x -  -  -  -  -  -  -59x -  -  -  -200x -200x -9x -191x -191x -17x -2x -15x -2x -  -13x -13x -6x -3x -2x -  -3x -  -7x -12x -  -1x -  -  -  -174x -  -  -  -  -93x -  -93x -6x -6x -  -  -  -  -93x -93x -  -1x -  -  -92x -86x -86x -  -1x -  -  -  -92x -86x -86x -58x -  -85x -12x -  -82x -  -4x -  -  -  -  -  -  -76x -76x -76x -1x -75x -56x -56x -  -  -75x -4x -4x -  -  -75x -  -  -  -276x -276x -  -  -  -  -  -  -  -  -  -  -  -  -4x -  -  -  -  -19x -19x -17x -  -2x -  -  -  -  -3x -3x - 
    'use strict'
    - 
    -const assert = require('assert')
    -const EE = require('events').EventEmitter
    -const Parser = require('./parse.js')
    -const fs = require('fs')
    -const fsm = require('fs-minipass')
    -const path = require('path')
    -const mkdir = require('./mkdir.js')
    -const mkdirSync = mkdir.sync
    -const wc = require('./winchars.js')
    - 
    -const ONENTRY = Symbol('onEntry')
    -const CHECKFS = Symbol('checkFs')
    -const MAKEFS = Symbol('makeFs')
    -const FILE = Symbol('file')
    -const DIRECTORY = Symbol('directory')
    -const LINK = Symbol('link')
    -const SYMLINK = Symbol('symlink')
    -const HARDLINK = Symbol('hardlink')
    -const UNSUPPORTED = Symbol('unsupported')
    -const UNKNOWN = Symbol('unknown')
    -const CHECKPATH = Symbol('checkPath')
    -const MKDIR = Symbol('mkdir')
    -const ONERROR = Symbol('onError')
    -const PENDING = Symbol('pending')
    -const PEND = Symbol('pend')
    -const UNPEND = Symbol('unpend')
    -const ENDED = Symbol('ended')
    -const MAYBECLOSE = Symbol('maybeClose')
    -const SKIP = Symbol('skip')
    -const DOCHOWN = Symbol('doChown')
    -const UID = Symbol('uid')
    -const GID = Symbol('gid')
    - 
    -// this.gid, entry.gid, this.processUid
    -const uint32 = (a, b, c) =>
    -  a === a >>> 0 ? a
    -  : b === b >>> 0 ? b
    -  : c
    - 
    -class Unpack extends Parser {
    -  constructor (opt) {
    -    if (!opt)
    -      opt = {}
    - 
    -    opt.ondone = _ => {
    -      this[ENDED] = true
    -      this[MAYBECLOSE]()
    -    }
    - 
    -    super(opt)
    - 
    -    this.writable = true
    -    this.readable = false
    - 
    -    this[PENDING] = 0
    -    this[ENDED] = false
    - 
    -    this.dirCache = opt.dirCache || new Map()
    - 
    -    if (typeof opt.uid === 'number' || typeof opt.gid === 'number') {
    -      // need both or neither
    -      if (typeof opt.uid !== 'number' || typeof opt.gid !== 'number')
    -        throw new TypeError('cannot set owner without number uid and gid')
    -      if (opt.preserveOwner)
    -        throw new TypeError(
    -          'cannot preserve owner in archive and also set owner explicitly')
    -      this.uid = opt.uid
    -      this.gid = opt.gid
    -      this.setOwner = true
    -    } else {
    -      this.uid = null
    -      this.gid = null
    -      this.setOwner = false
    -    }
    - 
    -    // default true for root
    -    if (opt.preserveOwner === undefined && typeof opt.uid !== 'number')
    -      this.preserveOwner = process.getuid && process.getuid() === 0
    -    else
    -      this.preserveOwner = !!opt.preserveOwner
    - 
    -    this.processUid = (this.preserveOwner || this.setOwner) && process.getuid ?
    -      process.getuid() : null
    -    this.processGid = (this.preserveOwner || this.setOwner) && process.getgid ?
    -      process.getgid() : null
    - 
    -    // turn ><?| in filenames into 0xf000-higher encoded forms
    -    this.win32 = !!opt.win32 || process.platform === 'win32'
    - 
    -    // do not unpack over files that are newer than what's in the archive
    -    this.newer = !!opt.newer
    - 
    -    // do not unpack over ANY files
    -    this.keep = !!opt.keep
    - 
    -    // do not set mtime/atime of extracted entries
    -    this.noMtime = !!opt.noMtime
    - 
    -    // allow .., absolute path entries, and unpacking through symlinks
    -    // without this, warn and skip .., relativize absolutes, and error
    -    // on symlinks in extraction path
    -    this.preservePaths = !!opt.preservePaths
    - 
    -    // unlink files and links before writing. This breaks existing hard
    -    // links, and removes symlink directories rather than erroring
    -    this.unlink = !!opt.unlink
    - 
    -    this.cwd = path.resolve(opt.cwd || process.cwd())
    -    this.strip = +opt.strip || 0
    -    this.processUmask = process.umask()
    -    this.umask = typeof opt.umask === 'number' ? opt.umask : this.processUmask
    -    // default mode for dirs created as parents
    -    this.dmode = opt.dmode || (0o0777 & (~this.umask))
    -    this.fmode = opt.fmode || (0o0666 & (~this.umask))
    -    this.on('entry', entry => this[ONENTRY](entry))
    -  }
    - 
    -  [MAYBECLOSE] () {
    -    if (this[ENDED] && this[PENDING] === 0) {
    -      this.emit('prefinish')
    -      this.emit('finish')
    -      this.emit('end')
    -      this.emit('close')
    -    }
    -  }
    - 
    -  [CHECKPATH] (entry) {
    -    if (this.strip) {
    -      const parts = entry.path.split(/\/|\\/)
    -      if (parts.length < this.strip)
    -        return false
    -      entry.path = parts.slice(this.strip).join('/')
    -    }
    - 
    -    if (!this.preservePaths) {
    -      const p = entry.path
    -      if (p.match(/(^|\/|\\)\.\.(\\|\/|$)/)) {
    -        this.warn('path contains \'..\'', p)
    -        return false
    -      }
    - 
    -      // absolutes on posix are also absolutes on win32
    -      // so we only need to test this one to get both
    -      if (path.win32.isAbsolute(p)) {
    -        const parsed = path.win32.parse(p)
    -        this.warn('stripping ' + parsed.root + ' from absolute path', p)
    -        entry.path = p.substr(parsed.root.length)
    -      }
    -    }
    - 
    -    // only encode : chars that aren't drive letter indicators
    -    if (this.win32) {
    -      const parsed = path.win32.parse(entry.path)
    -      entry.path = parsed.root === '' ? wc.encode(entry.path)
    -        : parsed.root + wc.encode(entry.path.substr(parsed.root.length))
    -    }
    - 
    -    if (path.isAbsolute(entry.path))
    -      entry.absolute = entry.path
    -    else
    -      entry.absolute = path.resolve(this.cwd, entry.path)
    - 
    -    return true
    -  }
    - 
    -  [ONENTRY] (entry) {
    -    if (!this[CHECKPATH](entry))
    -      return entry.resume()
    - 
    -    assert.equal(typeof entry.absolute, 'string')
    - 
    -    switch (entry.type) {
    -      case 'Directory':
    -      case 'GNUDumpDir':
    -        if (entry.mode)
    -          entry.mode = entry.mode | 0o700
    - 
    -      case 'File':
    -      case 'OldFile':
    -      case 'ContiguousFile':
    -      case 'Link':
    -      case 'SymbolicLink':
    -        return this[CHECKFS](entry)
    - 
    -      case 'CharacterDevice':
    -      case 'BlockDevice':
    -      case 'FIFO':
    -        return this[UNSUPPORTED](entry)
    -    }
    -  }
    - 
    -  [ONERROR] (er, entry) {
    -    // Cwd has to exist, or else nothing works. That's serious.
    -    // Other errors are warnings, which raise the error in strict
    -    // mode, but otherwise continue on.
    -    if (er.name === 'CwdError')
    -      this.emit('error', er)
    -    else {
    -      this.warn(er.message, er)
    -      this[UNPEND]()
    -      entry.resume()
    -    }
    -  }
    - 
    -  [MKDIR] (dir, mode, cb) {
    -    mkdir(dir, {
    -      uid: this.uid,
    -      gid: this.gid,
    -      processUid: this.processUid,
    -      processGid: this.processGid,
    -      umask: this.processUmask,
    -      preserve: this.preservePaths,
    -      unlink: this.unlink,
    -      cache: this.dirCache,
    -      cwd: this.cwd,
    -      mode: mode
    -    }, cb)
    -  }
    - 
    -  [DOCHOWN] (entry) {
    -    // in preserve owner mode, chown if the entry doesn't match process
    -    // in set owner mode, chown if setting doesn't match process
    -    return this.preserveOwner &&
    -      ( typeof entry.uid === 'number' && entry.uid !== this.processUid ||
    -        typeof entry.gid === 'number' && entry.gid !== this.processGid )
    -      ||
    -      ( typeof this.uid === 'number' && this.uid !== this.processUid ||
    -        typeof this.gid === 'number' && this.gid !== this.processGid )
    -  }
    - 
    -  [UID] (entry) {
    -    return uint32(this.uid, entry.uid, this.processUid)
    -  }
    - 
    -  [GID] (entry) {
    -    return uint32(this.gid, entry.gid, this.processGid)
    -  }
    - 
    -  [FILE] (entry) {
    -    const mode = entry.mode & 0o7777 || this.fmode
    -    const stream = new fsm.WriteStream(entry.absolute, {
    -      mode: mode,
    -      autoClose: false
    -    })
    -    stream.on('error', er => this[ONERROR](er, entry))
    - 
    -    let actions = 1
    -    const done = er => {
    -      if (er) {
    -        this[ONERROR](er, entry)
    -        actions = 1
    -      }
    - 
    -      if (--actions === 0)
    -        fs.close(stream.fd, _ => this[UNPEND]())
    -    }
    - 
    -    stream.on('finish', _ => {
    -      if (entry.mtime && !this.noMtime) {
    -        actions++
    -        fs.futimes(stream.fd, entry.atime || new Date(), entry.mtime, done)
    -      }
    - 
    -      if (this[DOCHOWN](entry)) {
    -        actions++
    -        fs.fchown(stream.fd, this[UID](entry), this[GID](entry), done)
    -      }
    - 
    -      done()
    -    })
    - 
    -    entry.pipe(stream)
    -  }
    - 
    -  [DIRECTORY] (entry) {
    -    const mode = entry.mode & 0o7777 || this.dmode
    -    this[MKDIR](entry.absolute, mode, er => {
    -      if (er)
    -        return this[ONERROR](er, entry)
    - 
    -      let actions = 1
    -      const done = _ => {
    -        if (--actions === 0) {
    -          this[UNPEND]()
    -          entry.resume()
    -        }
    -      }
    - 
    -      if (entry.mtime && !this.noMtime) {
    -        actions++
    -        fs.utimes(entry.absolute, entry.atime || new Date(), entry.mtime, done)
    -      }
    - 
    -      if (this[DOCHOWN](entry)) {
    -        actions++
    -        fs.chown(entry.absolute, this[UID](entry), this[GID](entry), done)
    -      }
    - 
    -      done()
    -    })
    -  }
    - 
    -  [UNSUPPORTED] (entry) {
    -    this.warn('unsupported entry type: ' + entry.type, entry)
    -    entry.resume()
    -  }
    - 
    -  [SYMLINK] (entry) {
    -    this[LINK](entry, entry.linkpath, 'symlink')
    -  }
    - 
    -  [HARDLINK] (entry) {
    -    this[LINK](entry, path.resolve(this.cwd, entry.linkpath), 'link')
    -  }
    - 
    -  [PEND] () {
    -    this[PENDING]++
    -  }
    - 
    -  [UNPEND] () {
    -    this[PENDING]--
    -    this[MAYBECLOSE]()
    -  }
    - 
    -  [SKIP] (entry) {
    -    this[UNPEND]()
    -    entry.resume()
    -  }
    - 
    -  // check if a thing is there, and if so, try to clobber it
    -  [CHECKFS] (entry) {
    -    this[PEND]()
    -    this[MKDIR](path.dirname(entry.absolute), this.dmode, er => {
    -      if (er)
    -        return this[ONERROR](er, entry)
    -      fs.lstat(entry.absolute, (er, st) => {
    -        if (st && (this.keep || this.newer && st.mtime > entry.mtime))
    -          this[SKIP](entry)
    -        else if (er || (entry.type === 'File' && !this.unlink && st.isFile()))
    -          this[MAKEFS](null, entry)
    -        else if (st.isDirectory()) {
    -          if (entry.type === 'Directory') {
    -            if (!entry.mode || (st.mode & 0o7777) === entry.mode)
    -              this[MAKEFS](null, entry)
    -            else
    -              fs.chmod(entry.absolute, entry.mode, er => this[MAKEFS](er, entry))
    -          } else
    -            fs.rmdir(entry.absolute, er => this[MAKEFS](er, entry))
    -        } else
    -          fs.unlink(entry.absolute, er => this[MAKEFS](er, entry))
    -      })
    -    })
    -  }
    - 
    -  [MAKEFS] (er, entry) {
    -    if (er)
    -      return this[ONERROR](er, entry)
    - 
    -    switch (entry.type) {
    -      case 'File':
    -      case 'OldFile':
    -      case 'ContiguousFile':
    -        return this[FILE](entry)
    - 
    -      case 'Link':
    -        return this[HARDLINK](entry)
    - 
    -      case 'SymbolicLink':
    -        return this[SYMLINK](entry)
    - 
    -      case 'Directory':
    -      case 'GNUDumpDir':
    -        return this[DIRECTORY](entry)
    -    }
    -  }
    - 
    -  [LINK] (entry, linkpath, link) {
    -    // XXX: get the type ('file' or 'dir') for windows
    -    fs[link](linkpath, entry.absolute, er => {
    -      if (er)
    -        return this[ONERROR](er, entry)
    -      this[UNPEND]()
    -      entry.resume()
    -    })
    -  }
    -}
    - 
    -class UnpackSync extends Unpack {
    -  constructor (opt) {
    -    super(opt)
    -  }
    - 
    -  [CHECKFS] (entry) {
    -    const er = this[MKDIR](path.dirname(entry.absolute), this.dmode)
    -    if (er)
    -      return this[ONERROR](er, entry)
    -    try {
    -      const st = fs.lstatSync(entry.absolute)
    -      if (this.keep || this.newer && st.mtime > entry.mtime)
    -        return this[SKIP](entry)
    -      else if (entry.type === 'File' && !this.unlink && st.isFile())
    -        return this[MAKEFS](null, entry)
    -      else {
    -        try {
    -          if (st.isDirectory()) {
    -            if (entry.type === 'Directory') {
    -              if (entry.mode && (st.mode & 0o7777) !== entry.mode)
    -                fs.chmodSync(entry.absolute, entry.mode)
    -            } else
    -              fs.rmdirSync(entry.absolute)
    -          } else
    -            fs.unlinkSync(entry.absolute)
    -          return this[MAKEFS](null, entry)
    -        } catch (er) {
    -          return this[ONERROR](er, entry)
    -        }
    -      }
    -    } catch (er) {
    -      return this[MAKEFS](null, entry)
    -    }
    -  }
    - 
    -  [FILE] (entry) {
    -    const mode = entry.mode & 0o7777 || this.fmode
    - 
    -    const oner = er => {
    -      try { fs.closeSync(fd) } catch (_) {}
    -      this[ONERROR](er, entry)
    -    }
    - 
    -    let stream
    -    let fd
    -    try {
    -      fd = fs.openSync(entry.absolute, 'w', mode)
    -    } catch (er) {
    -      return oner(er)
    -    }
    - 
    -    entry.on('data', chunk => {
    -      try {
    -        fs.writeSync(fd, chunk, 0, chunk.length)
    -      } catch (er) {
    -        oner(er)
    -      }
    -    })
    - 
    -    entry.on('end', _ => {
    -      try {
    -        if (entry.mtime && !this.noMtime)
    -          fs.futimesSync(fd, entry.atime || new Date(), entry.mtime)
    - 
    -        if (this[DOCHOWN](entry))
    -          fs.fchownSync(fd, this[UID](entry), this[GID](entry))
    - 
    -        fs.closeSync(fd)
    -      } catch (er) {
    -        return oner(er)
    -      }
    -    })
    - 
    -  }
    - 
    -  [DIRECTORY] (entry) {
    -    const mode = entry.mode & 0o7777 || this.dmode
    -    const er = this[MKDIR](entry.absolute, mode)
    -    if (er)
    -      return this[ONERROR](er, entry)
    -    if (entry.mtime && !this.noMtime) {
    -      try {
    -        fs.utimesSync(entry.absolute, entry.atime || new Date(), entry.mtime)
    -      } catch (er) {}
    -    }
    -    if (this[DOCHOWN](entry)) {
    -      try {
    -        fs.chownSync(entry.absolute, this[UID](entry), this[GID](entry))
    -      } catch (er) {}
    -    }
    -    entry.resume()
    -  }
    - 
    -  [MKDIR] (dir, mode) {
    -    try {
    -      return mkdir.sync(dir, {
    -        uid: this.uid,
    -        gid: this.gid,
    -        processUid: this.processUid,
    -        processGid: this.processGid,
    -        umask: this.processUmask,
    -        preserve: this.preservePaths,
    -        unlink: this.unlink,
    -        cache: this.dirCache,
    -        cwd: this.cwd,
    -        mode: mode
    -      })
    -    } catch (er) {
    -      return er
    -    }
    -  }
    - 
    -  [LINK] (entry, linkpath, link) {
    -    try {
    -      fs[link + 'Sync'](linkpath, entry.absolute)
    -      entry.resume()
    -    } catch (er) {
    -      return this[ONERROR](er, entry)
    -    }
    -  }
    -}
    - 
    -Unpack.Sync = UnpackSync
    -module.exports = Unpack
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/update.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/update.js.html deleted file mode 100644 index 531cddef483e9..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/update.js.html +++ /dev/null @@ -1,173 +0,0 @@ - - - - Code coverage report for tar/lib/update.js - - - - - - - -
    -
    -

    - All files / tar/lib update.js -

    -
    -
    - 100% - Statements - 20/20 -
    -
    - 100% - Branches - 15/15 -
    -
    - 100% - Functions - 4/4 -
    -
    - 100% - Lines - 20/20 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37  -  -  -  -2x -2x -  -  -2x -36x -  -36x -1x -  -35x -1x -  -34x -1x -  -33x -  -33x -33x -  -  -2x -33x -  -33x -32x -  -33x -2x -24x -  - 
    'use strict'
    - 
    -// tar -u
    - 
    -const hlo = require('./high-level-opt.js')
    -const r = require('./replace.js')
    -// just call tar.r with the filter and mtimeCache
    - 
    -const u = module.exports = (opt_, files, cb) => {
    -  const opt = hlo(opt_)
    - 
    -  if (!opt.file)
    -    throw new TypeError('file is required')
    - 
    -  if (opt.gzip)
    -    throw new TypeError('cannot append to compressed archives')
    - 
    -  if (!files || !Array.isArray(files) || !files.length)
    -    throw new TypeError('no files or directories specified')
    - 
    -  files = Array.from(files)
    - 
    -  mtimeFilter(opt)
    -  return r(opt, files, cb)
    -}
    - 
    -const mtimeFilter = opt => {
    -  const filter = opt.filter
    - 
    -  if (!opt.mtimeCache)
    -    opt.mtimeCache = new Map()
    - 
    -  opt.filter = filter ? (path, stat) =>
    -    filter(path, stat) && !(opt.mtimeCache.get(path) > stat.mtime)
    -    : (path, stat) => !(opt.mtimeCache.get(path) > stat.mtime)
    -}
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/warn-mixin.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/warn-mixin.js.html deleted file mode 100644 index 99aa9f3498cc8..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/warn-mixin.js.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - Code coverage report for tar/lib/warn-mixin.js - - - - - - - -
    -
    -

    - All files / tar/lib warn-mixin.js -

    -
    -
    - 100% - Statements - 9/9 -
    -
    - 100% - Branches - 4/4 -
    -
    - 100% - Functions - 2/2 -
    -
    - 100% - Lines - 8/8 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15  -27x -  -333x -184x -149x -2x -  -147x -147x -147x -  -  -  - 
    'use strict'
    -module.exports = Base => class extends Base {
    -  warn (msg, data) {
    -    if (!this.strict)
    -      this.emit('warn', msg, data)
    -    else if (data instanceof Error)
    -      this.emit('error', data)
    -    else {
    -      const er = new Error(msg)
    -      er.data = data
    -      this.emit('error', er)
    -    }
    -  }
    -}
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/winchars.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/winchars.js.html deleted file mode 100644 index 8e9fb65904602..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/winchars.js.html +++ /dev/null @@ -1,134 +0,0 @@ - - - - Code coverage report for tar/lib/winchars.js - - - - - - - -
    -
    -

    - All files / tar/lib winchars.js -

    -
    -
    - 100% - Statements - 12/12 -
    -
    - 100% - Branches - 0/0 -
    -
    - 100% - Functions - 7/7 -
    -
    - 100% - Lines - 8/8 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24  -  -  -  -  -9x -  -  -  -  -  -  -  -9x -45x -  -45x -45x -  -9x -30x -20x -  - 
    'use strict'
    - 
    -// When writing files on Windows, translate the characters to their
    -// 0xf000 higher-encoded versions.
    - 
    -const raw = [
    -  '|',
    -  '<',
    -  '>',
    -  '?',
    -  ':'
    -]
    - 
    -const win = raw.map(char =>
    -  String.fromCharCode(0xf000 + char.charCodeAt(0)))
    - 
    -const toWin = new Map(raw.map((char, i) => [char, win[i]]))
    -const toRaw = new Map(win.map((char, i) => [char, raw[i]]))
    - 
    -module.exports = {
    -  encode: s => raw.reduce((s, c) => s.split(c).join(toWin.get(c)), s),
    -  decode: s => win.reduce((s, c) => s.split(c).join(toRaw.get(c)), s)
    -}
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/write-entry.js.html b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/write-entry.js.html deleted file mode 100644 index ba22b99475455..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov-report/tar/lib/write-entry.js.html +++ /dev/null @@ -1,1268 +0,0 @@ - - - - Code coverage report for tar/lib/write-entry.js - - - - - - - -
    -
    -

    - All files / tar/lib write-entry.js -

    -
    -
    - 99.53% - Statements - 213/214 -
    -
    - 97.87% - Branches - 184/188 -
    -
    - 100% - Functions - 31/31 -
    -
    - 99.53% - Lines - 210/211 -
    -
    -
    -
    -
    
    -
    -
    1 -2 -3 -4 -5 -6 -7 -8 -9 -10 -11 -12 -13 -14 -15 -16 -17 -18 -19 -20 -21 -22 -23 -24 -25 -26 -27 -28 -29 -30 -31 -32 -33 -34 -35 -36 -37 -38 -39 -40 -41 -42 -43 -44 -45 -46 -47 -48 -49 -50 -51 -52 -53 -54 -55 -56 -57 -58 -59 -60 -61 -62 -63 -64 -65 -66 -67 -68 -69 -70 -71 -72 -73 -74 -75 -76 -77 -78 -79 -80 -81 -82 -83 -84 -85 -86 -87 -88 -89 -90 -91 -92 -93 -94 -95 -96 -97 -98 -99 -100 -101 -102 -103 -104 -105 -106 -107 -108 -109 -110 -111 -112 -113 -114 -115 -116 -117 -118 -119 -120 -121 -122 -123 -124 -125 -126 -127 -128 -129 -130 -131 -132 -133 -134 -135 -136 -137 -138 -139 -140 -141 -142 -143 -144 -145 -146 -147 -148 -149 -150 -151 -152 -153 -154 -155 -156 -157 -158 -159 -160 -161 -162 -163 -164 -165 -166 -167 -168 -169 -170 -171 -172 -173 -174 -175 -176 -177 -178 -179 -180 -181 -182 -183 -184 -185 -186 -187 -188 -189 -190 -191 -192 -193 -194 -195 -196 -197 -198 -199 -200 -201 -202 -203 -204 -205 -206 -207 -208 -209 -210 -211 -212 -213 -214 -215 -216 -217 -218 -219 -220 -221 -222 -223 -224 -225 -226 -227 -228 -229 -230 -231 -232 -233 -234 -235 -236 -237 -238 -239 -240 -241 -242 -243 -244 -245 -246 -247 -248 -249 -250 -251 -252 -253 -254 -255 -256 -257 -258 -259 -260 -261 -262 -263 -264 -265 -266 -267 -268 -269 -270 -271 -272 -273 -274 -275 -276 -277 -278 -279 -280 -281 -282 -283 -284 -285 -286 -287 -288 -289 -290 -291 -292 -293 -294 -295 -296 -297 -298 -299 -300 -301 -302 -303 -304 -305 -306 -307 -308 -309 -310 -311 -312 -313 -314 -315 -316 -317 -318 -319 -320 -321 -322 -323 -324 -325 -326 -327 -328 -329 -330 -331 -332 -333 -334 -335 -336 -337 -338 -339 -340 -341 -342 -343 -344 -345 -346 -347 -348 -349 -350 -351 -352 -353 -354 -355 -356 -357 -358 -359 -360 -361 -362 -363 -364 -365 -366 -367 -368 -369 -370 -371 -372 -373 -374 -375 -376 -377 -378 -379 -380 -381 -382 -383 -384 -385 -386 -387 -388 -389 -390 -391 -392 -393 -394 -395 -396 -397 -398 -399 -400 -401 -402  -6x -6x -6x -6x -6x -6x -  -6x -6x -6x -6x -6x -6x -6x -6x -6x -6x -6x -6x -6x -6x -6x -6x -6x -6x -  -6x -  -6570x -6570x -6570x -1x -6569x -  -6569x -  -6569x -6569x -6569x -6569x -6569x -6569x -6569x -6569x -6569x -6569x -  -6569x -6515x -  -6569x -  -  -4x -4x -2x -  -  -6567x -6567x -2x -2x -  -  -6567x -  -6567x -1x -  -6567x -6513x -  -54x -  -  -  -34x -34x -1x -33x -  -  -  -  -6566x -6566x -6566x -902x -6566x -6566x -6566x -  -  -  -6566x -5664x -867x -34x -  -1x -  -  -  -  -6563x -4x -  -6563x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -6563x -17x -  -  -  -  -  -  -  -  -  -  -  -  -  -6563x -  -  -  -867x -859x -867x -867x -867x -  -  -  -32x -32x -1x -31x -  -  -  -  -32x -32x -32x -  -  -  -1x -1x -1x -1x -1x -  -  -  -5664x -7x -7x -2x -2x -1x -  -6x -  -  -5663x -5663x -42x -  -5621x -  -  -  -5568x -5568x -2x -5566x -  -  -  -  -5617x -5617x -5617x -5617x -  -  -  -7336x -7336x -1x -7335x -  -  -  -  -5566x -  -  -  -7393x -2x -2x -2x -2x -2x -  -  -  -7392x -5614x -1700449x -1700449x -1700449x -  -  -  -7392x -  -7392x -7392x -7392x -7392x -  -7392x -  -7392x -5614x -2x -5614x -5614x -5614x -  -  -1778x -1754x -1754x -  -1778x -1778x -  -  -  -  -  -99x -  -  -  -20x -  -  -  -2x -  -  -  -53x -  -  -  -59x -59x -59x -58x -57x -  -59x -2x -  -  -  -  -51x -  -  -  -6x -  -33x -33x -33x -33x -33x -33x -33x -  -33x -33x -33x -  -  -33x -33x -33x -26x -33x -33x -33x -33x -33x -33x -33x -33x -33x -  -33x -27x -  -33x -2x -2x -  -  -  -1x -  -  -32x -32x -  -32x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -  -32x -14x -  -  -  -  -  -  -  -  -  -  -  -  -  -  -32x -32x -  -  -  -52x -52x -1x -51x -51x -  -  -  -29x -22x -29x -  -  -  -6x -6x -  -6x -6566x -  -  -  -  -6x - 
    'use strict'
    -const MiniPass = require('minipass')
    -const Pax = require('./pax.js')
    -const Header = require('./header.js')
    -const ReadEntry = require('./read-entry.js')
    -const fs = require('fs')
    -const path = require('path')
    - 
    -const types = require('./types.js')
    -const maxReadSize = 16 * 1024 * 1024
    -const PROCESS = Symbol('process')
    -const FILE = Symbol('file')
    -const DIRECTORY = Symbol('directory')
    -const SYMLINK = Symbol('symlink')
    -const HARDLINK = Symbol('hardlink')
    -const HEADER = Symbol('header')
    -const READ = Symbol('read')
    -const LSTAT = Symbol('lstat')
    -const ONLSTAT = Symbol('onlstat')
    -const ONREAD = Symbol('onread')
    -const ONREADLINK = Symbol('onreadlink')
    -const OPENFILE = Symbol('openfile')
    -const ONOPENFILE = Symbol('onopenfile')
    -const CLOSE = Symbol('close')
    -const warner = require('./warn-mixin.js')
    -const winchars = require('./winchars.js')
    - 
    -const WriteEntry = warner(class WriteEntry extends MiniPass {
    -  constructor (p, opt) {
    -    opt = opt || {}
    -    super(opt)
    -    if (typeof p !== 'string')
    -      throw new TypeError('path is required')
    -    this.path = p
    -    // suppress atime, ctime, uid, gid, uname, gname
    -    this.portable = !!opt.portable
    -    // until node has builtin pwnam functions, this'll have to do
    -    this.myuid = process.getuid && process.getuid()
    -    this.myuser = process.env.USER || ''
    -    this.maxReadSize = opt.maxReadSize || maxReadSize
    -    this.linkCache = opt.linkCache || new Map()
    -    this.statCache = opt.statCache || new Map()
    -    this.preservePaths = !!opt.preservePaths
    -    this.cwd = opt.cwd || process.cwd()
    -    this.strict = !!opt.strict
    -    this.noPax = !!opt.noPax
    -    this.noMtime = !!opt.noMtime
    - 
    -    if (typeof opt.onwarn === 'function')
    -      this.on('warn', opt.onwarn)
    - 
    -    if (!this.preservePaths && path.win32.isAbsolute(p)) {
    -      // absolutes on posix are also absolutes on win32
    -      // so we only need to test this one to get both
    -      const parsed = path.win32.parse(p)
    -      this.warn('stripping ' + parsed.root + ' from absolute path', p)
    -      this.path = p.substr(parsed.root.length)
    -    }
    - 
    -    this.win32 = !!opt.win32 || process.platform === 'win32'
    -    if (this.win32) {
    -      this.path = winchars.decode(this.path.replace(/\\/g, '/'))
    -      p = p.replace(/\\/g, '/')
    -    }
    - 
    -    this.absolute = opt.absolute || path.resolve(this.cwd, p)
    - 
    -    if (this.path === '')
    -      this.path = './'
    - 
    -    if (this.statCache.has(this.absolute))
    -      this[ONLSTAT](this.statCache.get(this.absolute))
    -    else
    -      this[LSTAT]()
    -  }
    - 
    -  [LSTAT] () {
    -    fs.lstat(this.absolute, (er, stat) => {
    -      if (er)
    -        return this.emit('error', er)
    -      this[ONLSTAT](stat)
    -    })
    -  }
    - 
    -  [ONLSTAT] (stat) {
    -    this.statCache.set(this.absolute, stat)
    -    this.stat = stat
    -    if (!stat.isFile())
    -      stat.size = 0
    -    this.type = getType(stat)
    -    this.emit('stat', stat)
    -    this[PROCESS]()
    -  }
    - 
    -  [PROCESS] () {
    -    switch (this.type) {
    -      case 'File': return this[FILE]()
    -      case 'Directory': return this[DIRECTORY]()
    -      case 'SymbolicLink': return this[SYMLINK]()
    -      // unsupported types are ignored.
    -      default: return this.end()
    -    }
    -  }
    - 
    -  [HEADER] () {
    -    if (this.type === 'Directory' && this.portable)
    -      this.noMtime = true
    - 
    -    this.header = new Header({
    -      path: this.path,
    -      linkpath: this.linkpath,
    -      // only the permissions and setuid/setgid/sticky bitflags
    -      // not the higher-order bits that specify file type
    -      mode: this.stat.mode & 0o7777,
    -      uid: this.portable ? null : this.stat.uid,
    -      gid: this.portable ? null : this.stat.gid,
    -      size: this.stat.size,
    -      mtime: this.noMtime ? null : this.stat.mtime,
    -      type: this.type,
    -      uname: this.portable ? null :
    -        this.stat.uid === this.myuid ? this.myuser : '',
    -      atime: this.portable ? null : this.stat.atime,
    -      ctime: this.portable ? null : this.stat.ctime
    -    })
    - 
    -    if (this.header.encode() && !this.noPax)
    -      this.write(new Pax({
    -        atime: this.portable ? null : this.header.atime,
    -        ctime: this.portable ? null : this.header.ctime,
    -        gid: this.portable ? null : this.header.gid,
    -        mtime: this.noMtime ? null : this.header.mtime,
    -        path: this.path,
    -        linkpath: this.linkpath,
    -        size: this.header.size,
    -        uid: this.portable ? null : this.header.uid,
    -        uname: this.portable ? null : this.header.uname,
    -        dev: this.portable ? null : this.stat.dev,
    -        ino: this.portable ? null : this.stat.ino,
    -        nlink: this.portable ? null : this.stat.nlink
    -      }).encode())
    -    this.write(this.header.block)
    -  }
    - 
    -  [DIRECTORY] () {
    -    if (this.path.substr(-1) !== '/')
    -      this.path += '/'
    -    this.stat.size = 0
    -    this[HEADER]()
    -    this.end()
    -  }
    - 
    -  [SYMLINK] () {
    -    fs.readlink(this.absolute, (er, linkpath) => {
    -      if (er)
    -        return this.emit('error', er)
    -      this[ONREADLINK](linkpath)
    -    })
    -  }
    - 
    -  [ONREADLINK] (linkpath) {
    -    this.linkpath = linkpath
    -    this[HEADER]()
    -    this.end()
    -  }
    - 
    -  [HARDLINK] (linkpath) {
    -    this.type = 'Link'
    -    this.linkpath = path.relative(this.cwd, linkpath)
    -    this.stat.size = 0
    -    this[HEADER]()
    -    this.end()
    -  }
    - 
    -  [FILE] () {
    -    if (this.stat.nlink > 1) {
    -      const linkKey = this.stat.dev + ':' + this.stat.ino
    -      if (this.linkCache.has(linkKey)) {
    -        const linkpath = this.linkCache.get(linkKey)
    -        if (linkpath.indexOf(this.cwd) === 0)
    -          return this[HARDLINK](linkpath)
    -      }
    -      this.linkCache.set(linkKey, this.absolute)
    -    }
    - 
    -    this[HEADER]()
    -    if (this.stat.size === 0)
    -      return this.end()
    - 
    -    this[OPENFILE]()
    -  }
    - 
    -  [OPENFILE] () {
    -    fs.open(this.absolute, 'r', (er, fd) => {
    -      if (er)
    -        return this.emit('error', er)
    -      this[ONOPENFILE](fd)
    -    })
    -  }
    - 
    -  [ONOPENFILE] (fd) {
    -    const blockLen = 512 * Math.ceil(this.stat.size / 512)
    -    const bufLen = Math.min(blockLen, this.maxReadSize)
    -    const buf = Buffer.allocUnsafe(bufLen)
    -    this[READ](fd, buf, 0, buf.length, 0, this.stat.size, blockLen)
    -  }
    - 
    -  [READ] (fd, buf, offset, length, pos, remain, blockRemain) {
    -    fs.read(fd, buf, offset, length, pos, (er, bytesRead) => {
    -      if (er)
    -        return this[CLOSE](fd, _ => this.emit('error', er))
    -      this[ONREAD](fd, buf, offset, length, pos, remain, blockRemain, bytesRead)
    -    })
    -  }
    - 
    -  [CLOSE] (fd, cb) {
    -    fs.close(fd, cb)
    -  }
    - 
    -  [ONREAD] (fd, buf, offset, length, pos, remain, blockRemain, bytesRead) {
    -    if (bytesRead <= 0 && remain > 0) {
    -      const er = new Error('unexpected EOF')
    -      er.path = this.absolute
    -      er.syscall = 'read'
    -      er.code = 'EOF'
    -      this.emit('error', er)
    -    }
    - 
    -    // null out the rest of the buffer, if we could fit the block padding
    -    if (bytesRead === remain) {
    -      for (let i = bytesRead; i < length && bytesRead < blockRemain; i++) {
    -        buf[i + offset] = 0
    -        bytesRead ++
    -        remain ++
    -      }
    -    }
    - 
    -    const writeBuf = offset === 0 && bytesRead === buf.length ?
    -      buf : buf.slice(offset, offset + bytesRead)
    -    remain -= bytesRead
    -    blockRemain -= bytesRead
    -    pos += bytesRead
    -    offset += bytesRead
    - 
    -    this.write(writeBuf)
    - 
    -    if (!remain) {
    -      if (blockRemain)
    -        this.write(Buffer.alloc(blockRemain))
    -      this.end()
    -      this[CLOSE](fd, _ => _)
    -      return
    -    }
    - 
    -    if (offset >= length) {
    -      buf = Buffer.allocUnsafe(length)
    -      offset = 0
    -    }
    -    length = buf.length - offset
    -    this[READ](fd, buf, offset, length, pos, remain, blockRemain)
    -  }
    -})
    - 
    -class WriteEntrySync extends WriteEntry {
    -  constructor (path, opt) {
    -    super(path, opt)
    -  }
    - 
    -  [LSTAT] () {
    -    this[ONLSTAT](fs.lstatSync(this.absolute))
    -  }
    - 
    -  [SYMLINK] () {
    -    this[ONREADLINK](fs.readlinkSync(this.absolute))
    -  }
    - 
    -  [OPENFILE] () {
    -    this[ONOPENFILE](fs.openSync(this.absolute, 'r'))
    -  }
    - 
    -  [READ] (fd, buf, offset, length, pos, remain, blockRemain) {
    -    let threw = true
    -    try {
    -      const bytesRead = fs.readSync(fd, buf, offset, length, pos)
    -      this[ONREAD](fd, buf, offset, length, pos, remain, blockRemain, bytesRead)
    -      threw = false
    -    } finally {
    -      if (threw)
    -        try { this[CLOSE](fd) } catch (er) {}
    -    }
    -  }
    - 
    -  [CLOSE] (fd) {
    -    fs.closeSync(fd)
    -  }
    -}
    - 
    -const WriteEntryTar = warner(class WriteEntryTar extends MiniPass {
    -  constructor (readEntry, opt) {
    -    opt = opt || {}
    -    super(opt)
    -    this.preservePaths = !!opt.preservePaths
    -    this.portable = !!opt.portable
    -    this.strict = !!opt.strict
    -    this.noPax = !!opt.noPax
    -    this.noMtime = !!opt.noMtime
    - 
    -    this.readEntry = readEntry
    -    this.type = readEntry.type
    -    Iif (this.type === 'Directory' && this.portable)
    -      this.noMtime = true
    - 
    -    this.path = readEntry.path
    -    this.mode = readEntry.mode
    -    if (this.mode)
    -      this.mode = this.mode & 0o7777
    -    this.uid = this.portable ? null : readEntry.uid
    -    this.gid = this.portable ? null : readEntry.gid
    -    this.uname = this.portable ? null : readEntry.uname
    -    this.gname = this.portable ? null : readEntry.gname
    -    this.size = readEntry.size
    -    this.mtime = this.noMtime ? null : readEntry.mtime
    -    this.atime = this.portable ? null : readEntry.atime
    -    this.ctime = this.portable ? null : readEntry.ctime
    -    this.linkpath = readEntry.linkpath
    - 
    -    if (typeof opt.onwarn === 'function')
    -      this.on('warn', opt.onwarn)
    - 
    -    if (path.isAbsolute(this.path) && !this.preservePaths) {
    -      const parsed = path.parse(this.path)
    -      this.warn(
    -        'stripping ' + parsed.root + ' from absolute path',
    -        this.path
    -      )
    -      this.path = this.path.substr(parsed.root.length)
    -    }
    - 
    -    this.remain = readEntry.size
    -    this.blockRemain = readEntry.startBlockSize
    - 
    -    this.header = new Header({
    -      path: this.path,
    -      linkpath: this.linkpath,
    -      // only the permissions and setuid/setgid/sticky bitflags
    -      // not the higher-order bits that specify file type
    -      mode: this.mode,
    -      uid: this.portable ? null : this.uid,
    -      gid: this.portable ? null : this.gid,
    -      size: this.size,
    -      mtime: this.noMtime ? null : this.mtime,
    -      type: this.type,
    -      uname: this.portable ? null : this.uname,
    -      atime: this.portable ? null : this.atime,
    -      ctime: this.portable ? null : this.ctime
    -    })
    - 
    -    if (this.header.encode() && !this.noPax)
    -      super.write(new Pax({
    -        atime: this.portable ? null : this.atime,
    -        ctime: this.portable ? null : this.ctime,
    -        gid: this.portable ? null : this.gid,
    -        mtime: this.noMtime ? null : this.mtime,
    -        path: this.path,
    -        linkpath: this.linkpath,
    -        size: this.size,
    -        uid: this.portable ? null : this.uid,
    -        uname: this.portable ? null : this.uname,
    -        dev: this.portable ? null : this.readEntry.dev,
    -        ino: this.portable ? null : this.readEntry.ino,
    -        nlink: this.portable ? null : this.readEntry.nlink
    -      }).encode())
    - 
    -    super.write(this.header.block)
    -    readEntry.pipe(this)
    -  }
    - 
    -  write (data) {
    -    const writeLen = data.length
    -    if (writeLen > this.blockRemain)
    -      throw new Error('writing more to entry than is appropriate')
    -    this.blockRemain -= writeLen
    -    return super.write(data)
    -  }
    - 
    -  end () {
    -    if (this.blockRemain)
    -      this.write(Buffer.alloc(this.blockRemain))
    -    return super.end()
    -  }
    -})
    - 
    -WriteEntry.Sync = WriteEntrySync
    -WriteEntry.Tar = WriteEntryTar
    - 
    -const getType = stat =>
    -  stat.isFile() ? 'File'
    -  : stat.isDirectory() ? 'Directory'
    -  : stat.isSymbolicLink() ? 'SymbolicLink'
    -  : 'Unsupported'
    - 
    -module.exports = WriteEntry
    - 
    -
    -
    - - - - - - - diff --git a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov.info b/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov.info deleted file mode 100644 index 19aa7c2206221..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/coverage/lcov.info +++ /dev/null @@ -1,3690 +0,0 @@ -TN: -SF:/Users/isaacs/dev/js/tar/index.js -FNF:0 -FNH:0 -DA:4,1 -DA:5,1 -DA:6,1 -DA:7,1 -DA:8,1 -DA:11,1 -DA:12,1 -DA:13,1 -DA:14,1 -DA:15,1 -DA:16,1 -DA:17,1 -DA:18,1 -LF:13 -LH:13 -BRF:0 -BRH:0 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/create.js -FN:12,(anonymous_0) -FN:38,(anonymous_1) -FN:47,(anonymous_2) -FN:54,(anonymous_3) -FN:65,(anonymous_4) -FN:66,(anonymous_5) -FN:72,(anonymous_6) -FN:80,(anonymous_7) -FN:87,(anonymous_8) -FN:88,(anonymous_9) -FN:95,(anonymous_10) -FN:101,(anonymous_11) -FNF:12 -FNH:12 -FNDA:15,(anonymous_0) -FNDA:4,(anonymous_1) -FNDA:4,(anonymous_2) -FNDA:4,(anonymous_3) -FNDA:5,(anonymous_4) -FNDA:7,(anonymous_5) -FNDA:7,(anonymous_6) -FNDA:9,(anonymous_7) -FNDA:7,(anonymous_8) -FNDA:3,(anonymous_9) -FNDA:1,(anonymous_10) -FNDA:2,(anonymous_11) -DA:4,2 -DA:6,2 -DA:7,2 -DA:8,2 -DA:9,2 -DA:10,2 -DA:12,2 -DA:13,15 -DA:14,1 -DA:16,15 -DA:17,1 -DA:19,15 -DA:20,2 -DA:22,13 -DA:24,13 -DA:26,13 -DA:27,1 -DA:29,12 -DA:30,1 -DA:32,11 -DA:38,2 -DA:39,4 -DA:40,4 -DA:43,4 -DA:44,4 -DA:47,2 -DA:48,4 -DA:49,4 -DA:52,4 -DA:54,4 -DA:55,4 -DA:56,4 -DA:57,4 -DA:60,4 -DA:62,4 -DA:65,2 -DA:66,5 -DA:67,7 -DA:68,3 -DA:72,7 -DA:75,4 -DA:77,4 -DA:80,2 -DA:81,9 -DA:82,8 -DA:83,8 -DA:84,3 -DA:87,7 -DA:88,3 -DA:90,5 -DA:92,6 -DA:95,2 -DA:96,1 -DA:97,1 -DA:98,1 -DA:101,2 -DA:102,2 -DA:103,2 -DA:104,2 -LF:59 -LH:59 -BRDA:13,0,0,1 -BRDA:13,0,1,14 -BRDA:16,1,0,1 -BRDA:16,1,1,14 -BRDA:19,2,0,2 -BRDA:19,2,1,13 -BRDA:19,3,0,15 -BRDA:19,3,1,14 -BRDA:19,3,2,13 -BRDA:26,4,0,1 -BRDA:26,4,1,12 -BRDA:26,5,0,13 -BRDA:26,5,1,6 -BRDA:29,6,0,1 -BRDA:29,6,1,11 -BRDA:29,7,0,12 -BRDA:29,7,1,4 -BRDA:32,8,0,4 -BRDA:32,8,1,7 -BRDA:32,9,0,11 -BRDA:32,9,1,8 -BRDA:33,10,0,4 -BRDA:33,10,1,3 -BRDA:34,11,0,1 -BRDA:34,11,1,2 -BRDA:41,12,0,4 -BRDA:41,12,1,3 -BRDA:50,13,0,4 -BRDA:50,13,1,3 -BRDA:62,14,0,3 -BRDA:62,14,1,1 -BRDA:67,15,0,3 -BRDA:67,15,1,4 -BRDA:83,16,0,3 -BRDA:83,16,1,5 -BRF:35 -BRH:35 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/extract.js -FN:10,(anonymous_0) -FN:43,(anonymous_1) -FN:44,(anonymous_2) -FN:47,(anonymous_3) -FN:58,(anonymous_4) -FN:59,(anonymous_5) -FN:62,(anonymous_6) -FN:79,(anonymous_7) -FN:84,(anonymous_8) -FN:90,(anonymous_9) -FN:106,(anonymous_10) -FN:110,(anonymous_11) -FNF:12 -FNH:12 -FNDA:21,(anonymous_0) -FNDA:7,(anonymous_1) -FNDA:13,(anonymous_2) -FNDA:87,(anonymous_3) -FNDA:9,(anonymous_4) -FNDA:9,(anonymous_5) -FNDA:6,(anonymous_6) -FNDA:9,(anonymous_7) -FNDA:9,(anonymous_8) -FNDA:9,(anonymous_9) -FNDA:1,(anonymous_10) -FNDA:2,(anonymous_11) -DA:4,2 -DA:5,2 -DA:6,2 -DA:7,2 -DA:8,2 -DA:10,2 -DA:11,21 -DA:12,1 -DA:13,20 -DA:14,1 -DA:16,21 -DA:17,3 -DA:19,21 -DA:20,13 -DA:22,8 -DA:24,21 -DA:26,21 -DA:27,2 -DA:29,19 -DA:30,1 -DA:32,18 -DA:33,7 -DA:35,18 -DA:43,2 -DA:44,13 -DA:45,7 -DA:47,7 -DA:48,87 -DA:49,87 -DA:53,87 -DA:54,87 -DA:57,7 -DA:58,9 -DA:59,9 -DA:62,2 -DA:63,6 -DA:65,6 -DA:66,6 -DA:68,6 -DA:71,5 -DA:72,5 -DA:76,4 -DA:79,2 -DA:80,9 -DA:81,9 -DA:83,9 -DA:84,9 -DA:85,9 -DA:86,9 -DA:90,9 -DA:91,9 -DA:92,1 -DA:94,8 -DA:98,8 -DA:99,8 -DA:103,9 -DA:106,2 -DA:107,1 -DA:110,2 -DA:111,2 -LF:60 -LH:60 -BRDA:11,0,0,1 -BRDA:11,0,1,20 -BRDA:13,1,0,1 -BRDA:13,1,1,19 -BRDA:16,2,0,3 -BRDA:16,2,1,18 -BRDA:19,3,0,13 -BRDA:19,3,1,8 -BRDA:26,4,0,2 -BRDA:26,4,1,19 -BRDA:26,5,0,21 -BRDA:26,5,1,9 -BRDA:29,6,0,1 -BRDA:29,6,1,18 -BRDA:29,7,0,19 -BRDA:29,7,1,4 -BRDA:32,8,0,7 -BRDA:32,8,1,11 -BRDA:35,9,0,6 -BRDA:35,9,1,12 -BRDA:35,10,0,18 -BRDA:35,10,1,15 -BRDA:36,11,0,9 -BRDA:36,11,1,3 -BRDA:37,12,0,1 -BRDA:37,12,1,2 -BRDA:48,13,0,87 -BRDA:48,13,1,12 -BRDA:48,13,2,12 -BRDA:49,14,0,3 -BRDA:49,14,1,84 -BRDA:50,15,0,9 -BRDA:50,15,1,75 -BRDA:57,16,0,3 -BRDA:57,16,1,4 -BRDA:58,17,0,9 -BRDA:58,17,1,3 -BRDA:71,18,0,5 -BRDA:71,18,1,3 -BRDA:81,19,0,9 -BRDA:81,19,1,7 -BRDA:91,20,0,1 -BRDA:91,20,1,8 -BRDA:103,21,0,4 -BRDA:103,21,1,5 -BRF:45 -BRH:45 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/header.js -FN:14,(anonymous_0) -FN:42,(anonymous_1) -FN:103,(anonymous_2) -FN:157,(anonymous_3) -FN:164,(anonymous_4) -FN:168,(anonymous_5) -FN:172,(anonymous_6) -FN:180,(anonymous_7) -FN:219,(anonymous_8) -FN:222,(anonymous_9) -FN:225,(anonymous_10) -FN:227,(anonymous_11) -FN:231,(anonymous_12) -FN:233,(anonymous_13) -FN:244,(anonymous_14) -FN:250,(anonymous_15) -FN:253,(anonymous_16) -FN:256,(anonymous_17) -FN:260,(anonymous_18) -FN:267,(anonymous_19) -FNF:20 -FNH:20 -FNDA:13121,(anonymous_0) -FNDA:6393,(anonymous_1) -FNDA:6719,(anonymous_2) -FNDA:6728,(anonymous_3) -FNDA:8178,(anonymous_4) -FNDA:4,(anonymous_5) -FNDA:6723,(anonymous_6) -FNDA:6718,(anonymous_7) -FNDA:32001,(anonymous_8) -FNDA:14938,(anonymous_9) -FNDA:14938,(anonymous_10) -FNDA:55448,(anonymous_11) -FNDA:55411,(anonymous_12) -FNDA:55411,(anonymous_13) -FNDA:66910,(anonymous_14) -FNDA:66615,(anonymous_15) -FNDA:66615,(anonymous_16) -FNDA:66615,(anonymous_17) -FNDA:20150,(anonymous_18) -FNDA:40308,(anonymous_19) -DA:7,13 -DA:8,13 -DA:9,13 -DA:11,13 -DA:15,13121 -DA:16,13121 -DA:17,13121 -DA:19,13121 -DA:20,13121 -DA:21,13121 -DA:22,13121 -DA:23,13121 -DA:24,13121 -DA:25,13121 -DA:26,13121 -DA:27,13121 -DA:28,13121 -DA:29,13121 -DA:30,13121 -DA:31,13121 -DA:32,13121 -DA:33,13121 -DA:34,13121 -DA:36,13121 -DA:37,6393 -DA:38,6728 -DA:39,6726 -DA:43,6393 -DA:44,2795 -DA:46,6393 -DA:47,1 -DA:49,6392 -DA:50,6392 -DA:51,6392 -DA:52,6392 -DA:53,6392 -DA:54,6392 -DA:55,6392 -DA:58,6392 -DA:59,6392 -DA:60,1990 -DA:61,6392 -DA:62,2 -DA:69,6392 -DA:70,1594 -DA:72,6392 -DA:73,6392 -DA:74,4275 -DA:75,4275 -DA:76,4275 -DA:77,4275 -DA:78,4275 -DA:80,2 -DA:81,2 -DA:83,4273 -DA:84,4273 -DA:85,295 -DA:86,4273 -DA:87,4273 -DA:91,6392 -DA:92,6392 -DA:93,946016 -DA:95,6392 -DA:96,2275552 -DA:98,6392 -DA:99,6392 -DA:100,1860 -DA:104,6719 -DA:105,6600 -DA:106,6600 -DA:109,6719 -DA:110,6717 -DA:112,6719 -DA:113,1 -DA:115,6718 -DA:116,6718 -DA:117,6718 -DA:118,6718 -DA:119,6718 -DA:121,6718 -DA:122,6718 -DA:123,6718 -DA:124,6718 -DA:125,6718 -DA:126,6718 -DA:127,6718 -DA:128,6718 -DA:129,6718 -DA:130,6718 -DA:131,6718 -DA:132,6718 -DA:133,6718 -DA:134,6718 -DA:135,6718 -DA:136,2 -DA:138,6716 -DA:139,6716 -DA:140,6716 -DA:143,6718 -DA:144,6718 -DA:145,994264 -DA:147,6718 -DA:148,2391608 -DA:150,6718 -DA:151,6718 -DA:152,6718 -DA:154,6718 -DA:158,6728 -DA:159,73451 -DA:160,66740 -DA:165,8178 -DA:169,4 -DA:173,6723 -DA:174,6719 -DA:176,4 -DA:180,13 -DA:181,6718 -DA:182,6718 -DA:183,6718 -DA:185,6718 -DA:187,6718 -DA:188,6683 -DA:191,35 -DA:192,35 -DA:194,35 -DA:196,49 -DA:198,21 -DA:201,28 -DA:203,13 -DA:207,15 -DA:208,15 -DA:213,35 -DA:214,1 -DA:216,6718 -DA:219,13 -DA:220,32001 -DA:222,13 -DA:223,14938 -DA:225,14938 -DA:227,13 -DA:228,55448 -DA:231,55411 -DA:233,13 -DA:234,55411 -DA:239,13 -DA:244,13 -DA:245,66910 -DA:250,13 -DA:251,66615 -DA:253,13 -DA:254,66615 -DA:256,13 -DA:257,66615 -DA:260,13 -DA:261,20150 -DA:265,13 -DA:267,13 -DA:268,40308 -DA:272,13 -LF:159 -LH:159 -BRDA:36,0,0,6393 -BRDA:36,0,1,6728 -BRDA:37,1,0,6393 -BRDA:37,1,1,2795 -BRDA:38,2,0,6726 -BRDA:38,2,1,2 -BRDA:43,3,0,2795 -BRDA:43,3,1,3598 -BRDA:46,4,0,1 -BRDA:46,4,1,6392 -BRDA:46,5,0,6393 -BRDA:46,5,1,6393 -BRDA:59,6,0,1990 -BRDA:59,6,1,4402 -BRDA:61,7,0,2 -BRDA:61,7,1,6390 -BRDA:61,8,0,6392 -BRDA:61,8,1,3769 -BRDA:69,9,0,1594 -BRDA:69,9,1,4798 -BRDA:73,10,0,4275 -BRDA:73,10,1,2117 -BRDA:78,11,0,2 -BRDA:78,11,1,4273 -BRDA:84,12,0,295 -BRDA:84,12,1,3978 -BRDA:99,13,0,1860 -BRDA:99,13,1,4532 -BRDA:99,14,0,6392 -BRDA:99,14,1,1994 -BRDA:104,15,0,6600 -BRDA:104,15,1,119 -BRDA:109,16,0,6717 -BRDA:109,16,1,2 -BRDA:112,17,0,1 -BRDA:112,17,1,6718 -BRDA:115,18,0,6623 -BRDA:115,18,1,95 -BRDA:115,19,0,6718 -BRDA:115,19,1,95 -BRDA:116,20,0,6718 -BRDA:116,20,1,1 -BRDA:121,21,0,6718 -BRDA:121,21,1,6678 -BRDA:122,22,0,6718 -BRDA:122,22,1,6718 -BRDA:123,23,0,6718 -BRDA:123,23,1,6715 -BRDA:124,24,0,6718 -BRDA:124,24,1,6715 -BRDA:125,25,0,6718 -BRDA:125,25,1,6717 -BRDA:126,26,0,6718 -BRDA:126,26,1,6718 -BRDA:128,27,0,6718 -BRDA:128,27,1,6718 -BRDA:130,28,0,6718 -BRDA:130,28,1,6718 -BRDA:131,29,0,6718 -BRDA:131,29,1,6718 -BRDA:132,30,0,6718 -BRDA:132,30,1,6718 -BRDA:133,31,0,6718 -BRDA:133,31,1,6718 -BRDA:134,32,0,6718 -BRDA:134,32,1,6718 -BRDA:135,33,0,2 -BRDA:135,33,1,6716 -BRDA:136,34,0,2 -BRDA:136,34,1,2 -BRDA:138,35,0,6716 -BRDA:138,35,1,6716 -BRDA:139,36,0,6716 -BRDA:139,36,1,6716 -BRDA:140,37,0,6716 -BRDA:140,37,1,6716 -BRDA:159,38,0,66740 -BRDA:159,38,1,6711 -BRDA:159,39,0,73451 -BRDA:159,39,1,73273 -BRDA:165,40,0,8178 -BRDA:165,40,1,6 -BRDA:173,41,0,6719 -BRDA:173,41,1,4 -BRDA:185,42,0,6718 -BRDA:185,42,1,6712 -BRDA:187,43,0,6683 -BRDA:187,43,1,35 -BRDA:210,44,0,49 -BRDA:210,44,1,34 -BRDA:196,45,0,21 -BRDA:196,45,1,28 -BRDA:196,46,0,49 -BRDA:196,46,1,35 -BRDA:201,47,0,13 -BRDA:201,47,1,15 -BRDA:201,48,0,28 -BRDA:201,48,1,14 -BRDA:213,49,0,1 -BRDA:213,49,1,34 -BRDA:225,50,0,10449 -BRDA:225,50,1,4489 -BRDA:228,51,0,37 -BRDA:228,51,1,55411 -BRDA:231,52,0,21489 -BRDA:231,52,1,33922 -BRDA:245,53,0,288 -BRDA:245,53,1,66622 -BRDA:246,54,0,7 -BRDA:246,54,1,66615 -BRDA:246,55,0,66622 -BRDA:246,55,1,66615 -BRDA:257,56,0,19852 -BRDA:257,56,1,46763 -BRDA:261,57,0,266 -BRDA:261,57,1,19884 -BRDA:268,58,0,13394 -BRDA:268,58,1,26914 -BRDA:270,59,0,26914 -BRDA:270,59,1,26874 -BRF:120 -BRH:120 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/high-level-opt.js -FN:27,(anonymous_0) -FN:27,(anonymous_1) -FN:29,(anonymous_2) -FNF:3 -FNH:3 -FNDA:177,(anonymous_0) -FNDA:469,(anonymous_1) -FNDA:469,(anonymous_2) -DA:5,7 -DA:27,469 -DA:29,469 -LF:3 -LH:3 -BRDA:27,0,0,174 -BRDA:27,0,1,3 -BRDA:28,1,0,26 -BRDA:28,1,1,443 -BRF:4 -BRH:4 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/large-numbers.js -FN:7,(anonymous_0) -FN:16,(anonymous_1) -FN:28,(anonymous_2) -FN:51,(anonymous_3) -FN:58,(anonymous_4) -FN:79,(anonymous_5) -FN:90,(anonymous_6) -FN:92,(anonymous_7) -FNF:8 -FNH:8 -FNDA:17,(anonymous_0) -FNDA:11,(anonymous_1) -FNDA:6,(anonymous_2) -FNDA:47,(anonymous_3) -FNDA:6,(anonymous_4) -FNDA:41,(anonymous_5) -FNDA:96,(anonymous_6) -FNDA:12,(anonymous_7) -DA:7,14 -DA:8,17 -DA:9,17 -DA:10,6 -DA:12,11 -DA:13,17 -DA:16,14 -DA:17,11 -DA:18,11 -DA:19,86 -DA:20,31 -DA:22,55 -DA:23,55 -DA:28,14 -DA:29,6 -DA:30,6 -DA:31,6 -DA:32,6 -DA:34,60 -DA:35,42 -DA:37,18 -DA:38,18 -DA:40,60 -DA:41,48 -DA:42,12 -DA:43,6 -DA:45,6 -DA:46,6 -DA:51,14 -DA:52,47 -DA:53,47 -DA:54,47 -DA:58,14 -DA:59,6 -DA:60,6 -DA:61,6 -DA:62,6 -DA:63,60 -DA:65,60 -DA:66,48 -DA:67,12 -DA:68,6 -DA:70,6 -DA:71,6 -DA:73,60 -DA:74,12 -DA:76,6 -DA:79,14 -DA:80,41 -DA:81,41 -DA:82,41 -DA:83,266 -DA:84,266 -DA:85,161 -DA:87,41 -DA:90,96 -DA:92,14 -LF:57 -LH:57 -BRDA:9,0,0,6 -BRDA:9,0,1,11 -BRDA:19,1,0,31 -BRDA:19,1,1,55 -BRDA:34,2,0,42 -BRDA:34,2,1,18 -BRDA:40,3,0,48 -BRDA:40,3,1,12 -BRDA:42,4,0,6 -BRDA:42,4,1,6 -BRDA:54,5,0,41 -BRDA:54,5,1,6 -BRDA:65,6,0,48 -BRDA:65,6,1,12 -BRDA:67,7,0,6 -BRDA:67,7,1,6 -BRDA:73,8,0,12 -BRDA:73,8,1,48 -BRDA:84,9,0,161 -BRDA:84,9,1,105 -BRF:20 -BRH:20 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/list.js -FN:13,(anonymous_0) -FN:46,(anonymous_1) -FN:48,(anonymous_2) -FN:51,(anonymous_3) -FN:56,(anonymous_4) -FN:57,(anonymous_5) -FN:60,(anonymous_6) -FN:71,(anonymous_7) -FN:72,(anonymous_8) -FN:75,(anonymous_9) -FN:103,(anonymous_10) -FN:108,(anonymous_11) -FN:112,(anonymous_12) -FN:128,(anonymous_13) -FNF:14 -FNH:14 -FNDA:34,(anonymous_0) -FNDA:22,(anonymous_1) -FNDA:255,(anonymous_2) -FNDA:72,(anonymous_3) -FNDA:3,(anonymous_4) -FNDA:6,(anonymous_5) -FNDA:125,(anonymous_6) -FNDA:32,(anonymous_7) -FNDA:64,(anonymous_8) -FNDA:13,(anonymous_9) -FNDA:16,(anonymous_10) -FNDA:16,(anonymous_11) -FNDA:16,(anonymous_12) -FNDA:16,(anonymous_13) -DA:7,5 -DA:8,5 -DA:9,5 -DA:10,5 -DA:11,5 -DA:13,5 -DA:14,34 -DA:15,1 -DA:16,33 -DA:17,1 -DA:19,34 -DA:20,5 -DA:22,34 -DA:23,31 -DA:25,3 -DA:27,34 -DA:29,34 -DA:30,1 -DA:32,33 -DA:33,1 -DA:35,32 -DA:36,3 -DA:38,32 -DA:39,22 -DA:41,32 -DA:46,5 -DA:47,22 -DA:48,22 -DA:49,255 -DA:50,255 -DA:51,72 -DA:56,5 -DA:57,6 -DA:58,3 -DA:60,3 -DA:61,125 -DA:62,125 -DA:66,125 -DA:67,125 -DA:70,3 -DA:71,32 -DA:72,64 -DA:75,5 -DA:76,13 -DA:77,13 -DA:78,13 -DA:80,13 -DA:81,13 -DA:82,12 -DA:83,12 -DA:84,10 -DA:86,2 -DA:87,2 -DA:88,2 -DA:89,2 -DA:90,28 -DA:91,27 -DA:92,27 -DA:94,1 -DA:96,11 -DA:98,13 -DA:99,1 -DA:103,5 -DA:104,16 -DA:105,16 -DA:107,16 -DA:108,16 -DA:109,16 -DA:110,16 -DA:112,16 -DA:113,16 -DA:114,2 -DA:116,14 -DA:120,14 -DA:121,14 -DA:125,16 -DA:128,16 -LF:77 -LH:77 -BRDA:14,0,0,1 -BRDA:14,0,1,33 -BRDA:16,1,0,1 -BRDA:16,1,1,32 -BRDA:19,2,0,5 -BRDA:19,2,1,29 -BRDA:22,3,0,31 -BRDA:22,3,1,3 -BRDA:29,4,0,1 -BRDA:29,4,1,33 -BRDA:29,5,0,34 -BRDA:29,5,1,15 -BRDA:32,6,0,1 -BRDA:32,6,1,32 -BRDA:32,7,0,33 -BRDA:32,7,1,4 -BRDA:35,8,0,3 -BRDA:35,8,1,29 -BRDA:38,9,0,22 -BRDA:38,9,1,10 -BRDA:41,10,0,13 -BRDA:41,10,1,19 -BRDA:41,11,0,32 -BRDA:41,11,1,29 -BRDA:42,12,0,16 -BRDA:42,12,1,3 -BRDA:48,13,0,13 -BRDA:48,13,1,9 -BRDA:61,14,0,125 -BRDA:61,14,1,65 -BRDA:61,14,2,65 -BRDA:62,15,0,6 -BRDA:62,15,1,119 -BRDA:63,16,0,59 -BRDA:63,16,1,60 -BRDA:70,17,0,1 -BRDA:70,17,1,2 -BRDA:71,18,0,32 -BRDA:71,18,1,1 -BRDA:82,19,0,12 -BRDA:82,19,1,10 -BRDA:83,20,0,10 -BRDA:83,20,1,2 -BRDA:98,21,0,1 -BRDA:98,21,1,12 -BRDA:98,22,0,13 -BRDA:98,22,1,2 -BRDA:105,23,0,16 -BRDA:105,23,1,14 -BRDA:113,24,0,2 -BRDA:113,24,1,14 -BRDA:125,25,0,4 -BRDA:125,25,1,12 -BRF:53 -BRH:53 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/mkdir.js -FN:13,(anonymous_0) -FN:19,(anonymous_1) -FN:25,(anonymous_2) -FN:31,(anonymous_3) -FN:36,(anonymous_4) -FN:54,(anonymous_5) -FN:60,(anonymous_6) -FN:72,(anonymous_7) -FN:86,(anonymous_8) -FN:96,(anonymous_9) -FN:96,(anonymous_10) -FN:102,(anonymous_11) -FN:108,(anonymous_12) -FN:124,(anonymous_13) -FN:142,(anonymous_14) -FNF:15 -FNH:15 -FNDA:4,(anonymous_0) -FNDA:8,(anonymous_1) -FNDA:12,(anonymous_2) -FNDA:36,(anonymous_3) -FNDA:451,(anonymous_4) -FNDA:457,(anonymous_5) -FNDA:6,(anonymous_6) -FNDA:40,(anonymous_7) -FNDA:1062,(anonymous_8) -FNDA:222,(anonymous_9) -FNDA:222,(anonymous_10) -FNDA:32,(anonymous_11) -FNDA:3,(anonymous_12) -FNDA:276,(anonymous_13) -FNDA:266,(anonymous_14) -DA:7,3 -DA:8,3 -DA:9,3 -DA:10,3 -DA:14,4 -DA:15,4 -DA:16,4 -DA:20,8 -DA:26,12 -DA:27,12 -DA:28,12 -DA:32,36 -DA:36,3 -DA:39,451 -DA:40,451 -DA:41,451 -DA:43,451 -DA:44,451 -DA:45,451 -DA:49,451 -DA:50,451 -DA:51,451 -DA:52,451 -DA:54,451 -DA:55,457 -DA:56,15 -DA:58,442 -DA:59,442 -DA:60,6 -DA:61,436 -DA:62,1 -DA:64,435 -DA:68,451 -DA:69,272 -DA:71,179 -DA:72,40 -DA:73,40 -DA:74,2 -DA:75,40 -DA:78,139 -DA:79,8 -DA:81,131 -DA:82,131 -DA:83,131 -DA:86,3 -DA:87,1062 -DA:88,119 -DA:89,943 -DA:90,943 -DA:91,943 -DA:92,723 -DA:93,220 -DA:96,222 -DA:97,222 -DA:98,36 -DA:100,4 -DA:102,32 -DA:103,32 -DA:104,4 -DA:105,28 -DA:106,22 -DA:107,6 -DA:108,3 -DA:109,3 -DA:110,1 -DA:111,2 -DA:113,3 -DA:114,2 -DA:116,1 -DA:119,186 -DA:120,186 -DA:124,3 -DA:127,276 -DA:128,276 -DA:129,276 -DA:131,276 -DA:132,276 -DA:133,276 -DA:137,276 -DA:138,276 -DA:139,276 -DA:140,276 -DA:142,276 -DA:143,266 -DA:144,266 -DA:145,6 -DA:146,266 -DA:147,1 -DA:148,266 -DA:151,276 -DA:152,128 -DA:154,148 -DA:155,34 -DA:156,34 -DA:157,34 -DA:158,34 -DA:160,1 -DA:162,34 -DA:163,2 -DA:165,32 -DA:166,32 -DA:169,114 -DA:170,7 -DA:172,107 -DA:173,107 -DA:174,107 -DA:175,107 -DA:179,792 -DA:180,608 -DA:182,184 -DA:183,184 -DA:184,169 -DA:185,169 -DA:187,15 -DA:189,4 -DA:191,11 -DA:192,9 -DA:193,4 -DA:194,4 -DA:195,5 -DA:196,2 -DA:197,2 -DA:198,2 -DA:199,2 -DA:200,2 -DA:201,3 -DA:202,2 -DA:206,99 -LF:128 -LH:128 -BRDA:45,0,0,451 -BRDA:45,0,1,6 -BRDA:45,0,2,6 -BRDA:45,0,3,2 -BRDA:55,1,0,15 -BRDA:55,1,1,442 -BRDA:59,2,0,6 -BRDA:59,2,1,436 -BRDA:59,3,0,442 -BRDA:59,3,1,114 -BRDA:61,4,0,1 -BRDA:61,4,1,435 -BRDA:68,5,0,272 -BRDA:68,5,1,179 -BRDA:68,6,0,451 -BRDA:68,6,1,451 -BRDA:71,7,0,40 -BRDA:71,7,1,139 -BRDA:73,8,0,2 -BRDA:73,8,1,38 -BRDA:73,9,0,40 -BRDA:73,9,1,39 -BRDA:74,10,0,2 -BRDA:74,10,1,1 -BRDA:74,10,2,1 -BRDA:78,11,0,8 -BRDA:78,11,1,131 -BRDA:87,12,0,119 -BRDA:87,12,1,943 -BRDA:91,13,0,723 -BRDA:91,13,1,220 -BRDA:97,14,0,36 -BRDA:97,14,1,186 -BRDA:98,15,0,4 -BRDA:98,15,1,32 -BRDA:98,16,0,36 -BRDA:98,16,1,35 -BRDA:98,16,2,16 -BRDA:98,16,3,14 -BRDA:103,17,0,4 -BRDA:103,17,1,28 -BRDA:105,18,0,22 -BRDA:105,18,1,6 -BRDA:107,19,0,3 -BRDA:107,19,1,3 -BRDA:109,20,0,1 -BRDA:109,20,1,2 -BRDA:113,21,0,2 -BRDA:113,21,1,1 -BRDA:119,22,0,186 -BRDA:119,22,1,108 -BRDA:133,23,0,276 -BRDA:133,23,1,6 -BRDA:133,23,2,6 -BRDA:133,23,3,2 -BRDA:144,24,0,6 -BRDA:144,24,1,260 -BRDA:144,25,0,266 -BRDA:144,25,1,101 -BRDA:146,26,0,1 -BRDA:146,26,1,265 -BRDA:151,27,0,128 -BRDA:151,27,1,148 -BRDA:151,28,0,276 -BRDA:151,28,1,276 -BRDA:154,29,0,34 -BRDA:154,29,1,114 -BRDA:162,30,0,2 -BRDA:162,30,1,32 -BRDA:169,31,0,7 -BRDA:169,31,1,107 -BRDA:176,32,0,891 -BRDA:176,32,1,792 -BRDA:179,33,0,608 -BRDA:179,33,1,184 -BRDA:184,34,0,169 -BRDA:184,34,1,93 -BRDA:187,35,0,4 -BRDA:187,35,1,11 -BRDA:187,36,0,15 -BRDA:187,36,1,14 -BRDA:187,36,2,5 -BRDA:187,36,3,3 -BRDA:192,37,0,4 -BRDA:192,37,1,5 -BRDA:195,38,0,2 -BRDA:195,38,1,3 -BRDA:198,39,0,2 -BRDA:198,39,1,2 -BRDA:201,40,0,2 -BRDA:201,40,1,1 -BRF:91 -BRH:91 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/pack.js -FN:13,(anonymous_0) -FN:59,(anonymous_1) -FN:81,(anonymous_2) -FN:82,(anonymous_3) -FN:83,(anonymous_4) -FN:84,(anonymous_5) -FN:94,(anonymous_6) -FN:103,(anonymous_7) -FN:107,(anonymous_8) -FN:112,(anonymous_9) -FN:120,(anonymous_10) -FN:131,(anonymous_11) -FN:142,(anonymous_12) -FN:150,(anonymous_13) -FN:159,(anonymous_14) -FN:163,(anonymous_15) -FN:173,(anonymous_16) -FN:184,(anonymous_17) -FN:187,(anonymous_18) -FN:196,(anonymous_19) -FN:202,(anonymous_20) -FN:230,(anonymous_21) -FN:234,(anonymous_22) -FN:240,(anonymous_23) -FN:283,(anonymous_24) -FN:285,(anonymous_25) -FN:301,(anonymous_26) -FN:305,(anonymous_27) -FN:306,(anonymous_28) -FN:312,(anonymous_29) -FN:318,(anonymous_30) -FN:322,(anonymous_31) -FN:335,(anonymous_32) -FN:340,(anonymous_33) -FN:346,(anonymous_34) -FN:354,(anonymous_35) -FN:360,(anonymous_36) -FN:361,(anonymous_37) -FN:363,(anonymous_38) -FN:368,(anonymous_39) -FN:373,(anonymous_40) -FN:378,(anonymous_41) -FN:389,(anonymous_42) -FN:393,(anonymous_43) -FNF:44 -FNH:44 -FNDA:6566,(anonymous_0) -FNDA:122,(anonymous_1) -FNDA:503,(anonymous_2) -FNDA:4,(anonymous_3) -FNDA:146,(anonymous_4) -FNDA:219,(anonymous_5) -FNDA:6507,(anonymous_6) -FNDA:106,(anonymous_7) -FNDA:107,(anonymous_8) -FNDA:100,(anonymous_9) -FNDA:128,(anonymous_10) -FNDA:27,(anonymous_11) -FNDA:25,(anonymous_12) -FNDA:6541,(anonymous_13) -FNDA:6453,(anonymous_14) -FNDA:6453,(anonymous_15) -FNDA:6538,(anonymous_16) -FNDA:821,(anonymous_17) -FNDA:821,(anonymous_18) -FNDA:858,(anonymous_19) -FNDA:20596,(anonymous_20) -FNDA:25863,(anonymous_21) -FNDA:6533,(anonymous_22) -FNDA:38739,(anonymous_23) -FNDA:6537,(anonymous_24) -FNDA:1,(anonymous_25) -FNDA:6512,(anonymous_26) -FNDA:6508,(anonymous_27) -FNDA:1,(anonymous_28) -FNDA:248,(anonymous_29) -FNDA:6448,(anonymous_30) -FNDA:6393,(anonymous_31) -FNDA:11830,(anonymous_32) -FNDA:199,(anonymous_33) -FNDA:265,(anonymous_34) -FNDA:47,(anonymous_35) -FNDA:1,(anonymous_36) -FNDA:1,(anonymous_37) -FNDA:84,(anonymous_38) -FNDA:37,(anonymous_39) -FNDA:87,(anonymous_40) -FNDA:48,(anonymous_41) -FNDA:39,(anonymous_42) -FNDA:106,(anonymous_43) -DA:14,6566 -DA:15,6566 -DA:16,6566 -DA:17,6566 -DA:18,6566 -DA:19,6566 -DA:20,6566 -DA:21,6566 -DA:25,5 -DA:26,5 -DA:27,5 -DA:28,5 -DA:29,5 -DA:30,5 -DA:31,5 -DA:32,5 -DA:33,5 -DA:34,5 -DA:35,5 -DA:36,5 -DA:37,5 -DA:38,5 -DA:39,5 -DA:40,5 -DA:41,5 -DA:42,5 -DA:43,5 -DA:44,5 -DA:45,5 -DA:46,5 -DA:47,5 -DA:48,5 -DA:49,5 -DA:50,5 -DA:51,5 -DA:52,5 -DA:54,5 -DA:55,5 -DA:56,5 -DA:58,5 -DA:60,122 -DA:61,122 -DA:62,122 -DA:63,122 -DA:64,122 -DA:65,122 -DA:66,122 -DA:67,122 -DA:68,122 -DA:69,122 -DA:70,122 -DA:71,122 -DA:72,122 -DA:73,122 -DA:74,3 -DA:76,122 -DA:77,122 -DA:78,5 -DA:79,4 -DA:80,5 -DA:81,503 -DA:82,5 -DA:83,146 -DA:84,219 -DA:86,117 -DA:88,122 -DA:89,122 -DA:90,122 -DA:91,122 -DA:94,6507 -DA:96,122 -DA:97,122 -DA:98,122 -DA:99,122 -DA:100,122 -DA:104,106 -DA:108,107 -DA:109,103 -DA:113,100 -DA:114,21 -DA:115,99 -DA:116,99 -DA:117,99 -DA:121,128 -DA:122,1 -DA:124,127 -DA:125,27 -DA:127,100 -DA:128,123 -DA:132,27 -DA:133,27 -DA:134,1 -DA:137,27 -DA:138,2 -DA:140,25 -DA:141,25 -DA:142,25 -DA:143,25 -DA:144,25 -DA:147,27 -DA:151,6541 -DA:152,6541 -DA:153,34 -DA:155,6541 -DA:156,6541 -DA:160,6453 -DA:161,6453 -DA:162,6453 -DA:163,6453 -DA:164,6453 -DA:165,6453 -DA:166,6453 -DA:167,1 -DA:169,6452 -DA:174,6538 -DA:175,6538 -DA:178,6538 -DA:179,24 -DA:181,6538 -DA:185,821 -DA:186,821 -DA:187,821 -DA:188,821 -DA:189,821 -DA:190,821 -DA:191,1 -DA:192,820 -DA:197,858 -DA:198,858 -DA:199,858 -DA:203,20596 -DA:204,9093 -DA:206,11503 -DA:207,11503 -DA:210,38739 -DA:211,38735 -DA:212,25 -DA:213,25 -DA:214,25 -DA:218,11499 -DA:220,11499 -DA:221,96 -DA:222,4 -DA:224,92 -DA:225,92 -DA:231,25863 -DA:235,6533 -DA:236,6533 -DA:237,6533 -DA:241,38739 -DA:242,6156 -DA:244,32583 -DA:245,18770 -DA:246,4954 -DA:247,18770 -DA:250,13813 -DA:251,6541 -DA:252,4 -DA:254,6537 -DA:256,13811 -DA:257,6453 -DA:260,7358 -DA:261,24 -DA:263,7334 -DA:264,860 -DA:265,2 -DA:267,858 -DA:268,859 -DA:269,821 -DA:273,6512 -DA:274,6511 -DA:275,1 -DA:276,1 -DA:279,6510 -DA:280,1581 -DA:284,6537 -DA:286,1 -DA:302,6512 -DA:303,6512 -DA:304,6512 -DA:305,6508 -DA:306,1 -DA:308,2 -DA:313,248 -DA:314,158 -DA:319,6448 -DA:321,6448 -DA:322,820 -DA:323,6393 -DA:327,6393 -DA:328,6393 -DA:331,6448 -DA:332,6448 -DA:334,6448 -DA:335,6336 -DA:336,11830 -DA:337,156 -DA:340,112 -DA:341,199 -DA:342,53 -DA:347,265 -DA:348,214 -DA:349,265 -DA:355,47 -DA:356,47 -DA:364,84 -DA:365,84 -DA:369,37 -DA:374,87 -DA:375,87 -DA:377,87 -DA:378,38 -DA:379,48 -DA:384,48 -DA:385,48 -DA:388,87 -DA:389,31 -DA:390,39 -DA:393,56 -DA:394,106 -DA:399,5 -DA:401,5 -LF:222 -LH:222 -BRDA:14,0,0,6566 -BRDA:14,0,1,1 -BRDA:61,1,0,122 -BRDA:61,1,1,5 -BRDA:63,2,0,122 -BRDA:63,2,1,22 -BRDA:68,3,0,122 -BRDA:68,3,1,115 -BRDA:69,4,0,122 -BRDA:69,4,1,121 -BRDA:70,5,0,122 -BRDA:70,5,1,121 -BRDA:71,6,0,122 -BRDA:71,6,1,121 -BRDA:73,7,0,3 -BRDA:73,7,1,119 -BRDA:77,8,0,5 -BRDA:77,8,1,117 -BRDA:78,9,0,4 -BRDA:78,9,1,1 -BRDA:94,10,0,41 -BRDA:94,10,1,81 -BRDA:98,11,0,122 -BRDA:98,11,1,122 -BRDA:113,12,0,21 -BRDA:113,12,1,79 -BRDA:121,13,0,1 -BRDA:121,13,1,127 -BRDA:124,14,0,27 -BRDA:124,14,1,100 -BRDA:133,15,0,1 -BRDA:133,15,1,26 -BRDA:137,16,0,2 -BRDA:137,16,1,25 -BRDA:152,17,0,34 -BRDA:152,17,1,6507 -BRDA:162,18,0,1 -BRDA:162,18,1,6452 -BRDA:166,19,0,1 -BRDA:166,19,1,6452 -BRDA:178,20,0,24 -BRDA:178,20,1,6514 -BRDA:190,21,0,1 -BRDA:190,21,1,820 -BRDA:203,22,0,9093 -BRDA:203,22,1,11503 -BRDA:208,23,0,50238 -BRDA:208,23,1,49694 -BRDA:211,24,0,25 -BRDA:211,24,1,38710 -BRDA:220,25,0,96 -BRDA:220,25,1,11403 -BRDA:220,26,0,11499 -BRDA:220,26,1,11363 -BRDA:220,26,2,97 -BRDA:221,27,0,4 -BRDA:221,27,1,92 -BRDA:231,28,0,25863 -BRDA:231,28,1,25863 -BRDA:231,28,2,25792 -BRDA:241,29,0,6156 -BRDA:241,29,1,32583 -BRDA:244,30,0,18770 -BRDA:244,30,1,13813 -BRDA:245,31,0,4954 -BRDA:245,31,1,13816 -BRDA:245,32,0,18770 -BRDA:245,32,1,9951 -BRDA:250,33,0,6541 -BRDA:250,33,1,7272 -BRDA:251,34,0,4 -BRDA:251,34,1,6537 -BRDA:256,35,0,6453 -BRDA:256,35,1,7358 -BRDA:260,36,0,24 -BRDA:260,36,1,7334 -BRDA:263,37,0,860 -BRDA:263,37,1,6474 -BRDA:263,38,0,7334 -BRDA:263,38,1,7332 -BRDA:263,38,2,1680 -BRDA:264,39,0,2 -BRDA:264,39,1,858 -BRDA:268,40,0,821 -BRDA:268,40,1,38 -BRDA:274,41,0,1 -BRDA:274,41,1,6510 -BRDA:279,42,0,1581 -BRDA:279,42,1,4929 -BRDA:279,43,0,6510 -BRDA:279,43,1,1581 -BRDA:313,44,0,158 -BRDA:313,44,1,90 -BRDA:313,45,0,248 -BRDA:313,45,1,177 -BRDA:321,46,0,820 -BRDA:321,46,1,5628 -BRDA:323,47,0,14 -BRDA:323,47,1,6379 -BRDA:324,48,0,14 -BRDA:324,48,1,4 -BRDA:327,49,0,18 -BRDA:327,49,1,6375 -BRDA:334,50,0,6336 -BRDA:334,50,1,112 -BRDA:336,51,0,156 -BRDA:336,51,1,11674 -BRDA:341,52,0,53 -BRDA:341,52,1,146 -BRDA:347,53,0,214 -BRDA:347,53,1,51 -BRDA:364,54,0,1 -BRDA:364,54,1,83 -BRDA:377,55,0,38 -BRDA:377,55,1,49 -BRDA:379,56,0,14 -BRDA:379,56,1,34 -BRDA:380,57,0,14 -BRDA:380,57,1,4 -BRDA:384,58,0,4 -BRDA:384,58,1,44 -BRDA:388,59,0,31 -BRDA:388,59,1,56 -BRF:123 -BRH:123 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/parse.js -FN:61,(anonymous_0) -FN:64,(anonymous_1) -FN:71,(anonymous_2) -FN:103,(anonymous_3) -FN:128,(anonymous_4) -FN:157,(anonymous_5) -FN:169,(anonymous_6) -FN:177,(anonymous_7) -FN:194,(anonymous_8) -FN:198,(anonymous_9) -FN:216,(anonymous_10) -FN:227,(anonymous_11) -FN:234,(anonymous_12) -FN:262,(anonymous_13) -FN:268,(anonymous_14) -FN:290,(anonymous_15) -FN:291,(anonymous_16) -FN:293,(anonymous_17) -FN:316,(anonymous_18) -FN:321,(anonymous_19) -FN:326,(anonymous_20) -FN:342,(anonymous_21) -FN:370,(anonymous_22) -FN:405,(anonymous_23) -FNF:24 -FNH:24 -FNDA:2032,(anonymous_0) -FNDA:742,(anonymous_1) -FNDA:589,(anonymous_2) -FNDA:6101,(anonymous_3) -FNDA:475,(anonymous_4) -FNDA:4299,(anonymous_5) -FNDA:1272,(anonymous_6) -FNDA:2947,(anonymous_7) -FNDA:9,(anonymous_8) -FNDA:2194,(anonymous_9) -FNDA:475,(anonymous_10) -FNDA:4328,(anonymous_11) -FNDA:455,(anonymous_12) -FNDA:2,(anonymous_13) -FNDA:669590,(anonymous_14) -FNDA:20164,(anonymous_15) -FNDA:2,(anonymous_16) -FNDA:226,(anonymous_17) -FNDA:6,(anonymous_18) -FNDA:652869,(anonymous_19) -FNDA:3449,(anonymous_20) -FNDA:655942,(anonymous_21) -FNDA:655553,(anonymous_22) -FNDA:718,(anonymous_23) -DA:23,9 -DA:24,9 -DA:25,9 -DA:26,9 -DA:27,9 -DA:28,9 -DA:29,9 -DA:30,9 -DA:31,9 -DA:33,9 -DA:34,9 -DA:35,9 -DA:36,9 -DA:37,9 -DA:38,9 -DA:39,9 -DA:40,9 -DA:41,9 -DA:42,9 -DA:43,9 -DA:44,9 -DA:45,9 -DA:46,9 -DA:47,9 -DA:48,9 -DA:49,9 -DA:50,9 -DA:51,9 -DA:52,9 -DA:53,9 -DA:54,9 -DA:55,9 -DA:56,9 -DA:57,9 -DA:58,9 -DA:59,9 -DA:61,2032 -DA:63,9 -DA:65,742 -DA:66,742 -DA:68,742 -DA:69,134 -DA:71,608 -DA:72,589 -DA:73,589 -DA:74,589 -DA:75,589 -DA:78,742 -DA:79,742 -DA:80,742 -DA:83,742 -DA:84,742 -DA:86,742 -DA:87,742 -DA:88,742 -DA:89,742 -DA:90,742 -DA:91,742 -DA:92,742 -DA:93,742 -DA:94,742 -DA:95,742 -DA:96,742 -DA:97,742 -DA:98,36 -DA:99,742 -DA:100,34 -DA:104,6101 -DA:106,6101 -DA:107,1834 -DA:108,4267 -DA:109,160 -DA:110,4107 -DA:111,40 -DA:113,4067 -DA:114,4067 -DA:115,40 -DA:116,4027 -DA:117,40 -DA:119,3987 -DA:121,3987 -DA:122,759 -DA:123,260 -DA:124,260 -DA:125,260 -DA:126,499 -DA:127,455 -DA:128,475 -DA:129,455 -DA:133,3228 -DA:134,3228 -DA:135,3228 -DA:136,1070 -DA:137,1070 -DA:139,2158 -DA:140,1028 -DA:142,1130 -DA:143,1130 -DA:146,2158 -DA:147,1675 -DA:148,1675 -DA:150,483 -DA:158,4299 -DA:160,4299 -DA:161,1653 -DA:162,1653 -DA:163,2646 -DA:164,490 -DA:166,2156 -DA:167,2156 -DA:168,2150 -DA:169,1288 -DA:170,1288 -DA:174,4293 -DA:178,2947 -DA:180,2941 -DA:188,2478 -DA:189,2478 -DA:190,2478 -DA:191,2468 -DA:192,516 -DA:194,10 -DA:200,2194 -DA:201,2194 -DA:202,2194 -DA:205,2194 -DA:207,2194 -DA:208,2121 -DA:209,2121 -DA:210,2121 -DA:213,2194 -DA:217,475 -DA:218,475 -DA:221,475 -DA:222,455 -DA:224,475 -DA:228,4328 -DA:229,3815 -DA:231,513 -DA:235,455 -DA:236,455 -DA:239,351 -DA:240,351 -DA:243,44 -DA:244,44 -DA:248,40 -DA:249,40 -DA:250,40 -DA:253,20 -DA:254,20 -DA:255,20 -DA:263,2 -DA:264,2 -DA:265,2 -DA:269,669590 -DA:270,1 -DA:273,669589 -DA:274,944 -DA:275,224 -DA:276,224 -DA:278,944 -DA:279,224 -DA:280,224 -DA:282,720 -DA:283,947 -DA:284,493 -DA:286,720 -DA:287,227 -DA:288,227 -DA:289,227 -DA:290,20164 -DA:291,227 -DA:292,2 -DA:293,227 -DA:294,226 -DA:295,226 -DA:297,227 -DA:301,669138 -DA:302,669138 -DA:303,33586 -DA:305,635552 -DA:306,669132 -DA:310,669132 -DA:315,669132 -DA:316,63 -DA:318,669132 -DA:322,652869 -DA:323,652866 -DA:327,3449 -DA:328,709 -DA:329,709 -DA:330,709 -DA:331,2 -DA:332,2 -DA:334,2 -DA:335,1 -DA:336,2 -DA:338,709 -DA:343,655942 -DA:344,10 -DA:345,655932 -DA:346,381 -DA:348,655551 -DA:349,655551 -DA:350,652859 -DA:351,652859 -DA:352,652859 -DA:353,652859 -DA:355,2692 -DA:358,655545 -DA:359,2 -DA:360,2 -DA:361,2 -DA:363,655545 -DA:366,655936 -DA:367,3068 -DA:373,655553 -DA:374,655553 -DA:375,655553 -DA:376,8295 -DA:378,6101 -DA:379,6095 -DA:380,6095 -DA:384,1719 -DA:385,1719 -DA:388,475 -DA:389,475 -DA:397,655547 -DA:398,652863 -DA:399,1 -DA:401,652862 -DA:406,718 -DA:407,717 -DA:408,113 -DA:410,604 -DA:411,604 -LF:236 -LH:236 -BRDA:65,0,0,742 -BRDA:65,0,1,22 -BRDA:68,1,0,134 -BRDA:68,1,1,608 -BRDA:79,2,0,742 -BRDA:79,2,1,462 -BRDA:80,3,0,290 -BRDA:80,3,1,452 -BRDA:97,4,0,36 -BRDA:97,4,1,706 -BRDA:99,5,0,34 -BRDA:99,5,1,708 -BRDA:106,6,0,1834 -BRDA:106,6,1,4267 -BRDA:108,7,0,160 -BRDA:108,7,1,4107 -BRDA:110,8,0,40 -BRDA:110,8,1,4067 -BRDA:114,9,0,40 -BRDA:114,9,1,4027 -BRDA:114,10,0,4067 -BRDA:114,10,1,248 -BRDA:116,11,0,40 -BRDA:116,11,1,3987 -BRDA:116,12,0,4027 -BRDA:116,12,1,3819 -BRDA:121,13,0,759 -BRDA:121,13,1,3228 -BRDA:122,14,0,260 -BRDA:122,14,1,499 -BRDA:126,15,0,455 -BRDA:126,15,1,44 -BRDA:134,16,0,3228 -BRDA:134,16,1,3226 -BRDA:135,17,0,1070 -BRDA:135,17,1,2158 -BRDA:137,18,0,382 -BRDA:137,18,1,688 -BRDA:139,19,0,1028 -BRDA:139,19,1,1130 -BRDA:146,20,0,1675 -BRDA:146,20,1,483 -BRDA:160,21,0,1653 -BRDA:160,21,1,2646 -BRDA:163,22,0,490 -BRDA:163,22,1,2156 -BRDA:168,23,0,1288 -BRDA:168,23,1,862 -BRDA:180,24,0,2478 -BRDA:180,24,1,463 -BRDA:189,25,0,2478 -BRDA:189,25,1,825 -BRDA:189,25,2,167 -BRDA:190,26,0,2468 -BRDA:190,26,1,10 -BRDA:191,27,0,516 -BRDA:191,27,1,1952 -BRDA:202,28,0,583 -BRDA:202,28,1,1611 -BRDA:202,29,0,2194 -BRDA:202,29,1,593 -BRDA:207,30,0,2121 -BRDA:207,30,1,73 -BRDA:221,31,0,455 -BRDA:221,31,1,20 -BRDA:228,32,0,3815 -BRDA:228,32,1,513 -BRDA:228,33,0,4328 -BRDA:228,33,1,3916 -BRDA:236,34,0,351 -BRDA:236,34,1,351 -BRDA:236,34,2,44 -BRDA:236,34,3,40 -BRDA:236,34,4,40 -BRDA:236,34,5,20 -BRDA:248,35,0,40 -BRDA:248,35,1,40 -BRDA:253,36,0,20 -BRDA:253,36,1,20 -BRDA:269,37,0,1 -BRDA:269,37,1,669589 -BRDA:273,38,0,944 -BRDA:273,38,1,668645 -BRDA:273,39,0,669589 -BRDA:273,39,1,944 -BRDA:274,40,0,224 -BRDA:274,40,1,720 -BRDA:278,41,0,224 -BRDA:278,41,1,720 -BRDA:282,42,0,1667 -BRDA:282,42,1,1174 -BRDA:283,43,0,493 -BRDA:283,43,1,454 -BRDA:286,44,0,227 -BRDA:286,44,1,493 -BRDA:297,45,0,113 -BRDA:297,45,1,114 -BRDA:302,46,0,33586 -BRDA:302,46,1,635552 -BRDA:310,47,0,190 -BRDA:310,47,1,668942 -BRDA:311,48,0,61606 -BRDA:311,48,1,607336 -BRDA:315,49,0,63 -BRDA:315,49,1,669069 -BRDA:315,50,0,669132 -BRDA:315,50,1,253 -BRDA:322,51,0,652866 -BRDA:322,51,1,3 -BRDA:322,52,0,652869 -BRDA:322,52,1,652866 -BRDA:323,53,0,652864 -BRDA:323,53,1,2 -BRDA:327,54,0,709 -BRDA:327,54,1,2740 -BRDA:327,55,0,3449 -BRDA:327,55,1,1094 -BRDA:327,55,2,710 -BRDA:330,56,0,2 -BRDA:330,56,1,707 -BRDA:330,57,0,709 -BRDA:330,57,1,255 -BRDA:331,58,0,1 -BRDA:331,58,1,1 -BRDA:334,59,0,1 -BRDA:334,59,1,1 -BRDA:343,60,0,10 -BRDA:343,60,1,655932 -BRDA:345,61,0,381 -BRDA:345,61,1,655551 -BRDA:345,62,0,655932 -BRDA:345,62,1,382 -BRDA:349,63,0,652859 -BRDA:349,63,1,2692 -BRDA:358,64,0,655547 -BRDA:358,64,1,652864 -BRDA:358,64,2,2 -BRDA:366,65,0,3068 -BRDA:366,65,1,652868 -BRDA:366,66,0,655936 -BRDA:366,66,1,652872 -BRDA:375,67,0,663842 -BRDA:375,67,1,8295 -BRDA:376,68,0,6101 -BRDA:376,68,1,670 -BRDA:376,68,2,1719 -BRDA:376,68,3,475 -BRDA:397,69,0,652863 -BRDA:397,69,1,2684 -BRDA:398,70,0,1 -BRDA:398,70,1,652862 -BRDA:406,71,0,717 -BRDA:406,71,1,1 -BRDA:407,72,0,113 -BRDA:407,72,1,604 -BRF:155 -BRH:155 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/pax.js -FN:6,(anonymous_0) -FN:25,(anonymous_1) -FN:71,(anonymous_2) -FN:91,(anonymous_3) -FN:112,(anonymous_4) -FN:114,(anonymous_5) -FN:115,(anonymous_6) -FN:117,(anonymous_7) -FN:123,(anonymous_8) -FNF:9 -FNH:9 -FNDA:435,(anonymous_0) -FNDA:34,(anonymous_1) -FNDA:34,(anonymous_2) -FNDA:510,(anonymous_3) -FNDA:401,(anonymous_4) -FNDA:401,(anonymous_5) -FNDA:1,(anonymous_6) -FNDA:401,(anonymous_7) -FNDA:2259,(anonymous_8) -DA:2,11 -DA:3,11 -DA:7,435 -DA:8,435 -DA:9,435 -DA:10,435 -DA:11,435 -DA:12,435 -DA:13,435 -DA:14,435 -DA:15,435 -DA:16,435 -DA:17,435 -DA:18,435 -DA:19,435 -DA:20,435 -DA:21,435 -DA:22,435 -DA:26,34 -DA:27,34 -DA:28,1 -DA:30,33 -DA:33,33 -DA:34,33 -DA:37,33 -DA:38,16896 -DA:41,33 -DA:61,33 -DA:64,33 -DA:65,8949 -DA:68,33 -DA:72,34 -DA:92,510 -DA:93,204 -DA:94,306 -DA:96,306 -DA:100,306 -DA:104,306 -DA:105,306 -DA:106,30 -DA:107,306 -DA:108,306 -DA:112,401 -DA:114,11 -DA:115,401 -DA:117,11 -DA:118,401 -DA:123,11 -DA:124,2259 -DA:128,2259 -DA:129,5 -DA:131,2254 -DA:132,2254 -DA:133,2254 -DA:134,2254 -DA:135,1 -DA:137,2253 -DA:138,2253 -DA:142,2253 -DA:145,11 -LF:60 -LH:60 -BRDA:7,0,0,435 -BRDA:7,0,1,85 -BRDA:8,1,0,435 -BRDA:8,1,1,435 -BRDA:9,2,0,435 -BRDA:9,2,1,411 -BRDA:10,3,0,435 -BRDA:10,3,1,85 -BRDA:11,4,0,435 -BRDA:11,4,1,369 -BRDA:12,5,0,435 -BRDA:12,5,1,410 -BRDA:13,6,0,435 -BRDA:13,6,1,435 -BRDA:14,7,0,435 -BRDA:14,7,1,368 -BRDA:15,8,0,435 -BRDA:15,8,1,2 -BRDA:16,9,0,435 -BRDA:16,9,1,363 -BRDA:17,10,0,435 -BRDA:17,10,1,371 -BRDA:18,11,0,435 -BRDA:18,11,1,373 -BRDA:19,12,0,435 -BRDA:19,12,1,86 -BRDA:20,13,0,435 -BRDA:20,13,1,86 -BRDA:21,14,0,435 -BRDA:21,14,1,86 -BRDA:22,15,0,435 -BRDA:22,15,1,389 -BRDA:27,16,0,1 -BRDA:27,16,1,33 -BRDA:46,17,0,33 -BRDA:46,17,1,33 -BRDA:47,18,0,33 -BRDA:47,18,1,6 -BRDA:48,19,0,33 -BRDA:48,19,1,6 -BRDA:50,20,0,33 -BRDA:50,20,1,5 -BRDA:51,21,0,1 -BRDA:51,21,1,32 -BRDA:53,22,0,33 -BRDA:53,22,1,7 -BRDA:54,23,0,33 -BRDA:54,23,1,32 -BRDA:57,24,0,33 -BRDA:57,24,1,6 -BRDA:58,25,0,33 -BRDA:58,25,1,6 -BRDA:92,26,0,204 -BRDA:92,26,1,306 -BRDA:92,27,0,510 -BRDA:92,27,1,306 -BRDA:94,28,0,82 -BRDA:94,28,1,224 -BRDA:97,29,0,78 -BRDA:97,29,1,228 -BRDA:97,30,0,306 -BRDA:97,30,1,280 -BRDA:97,30,2,254 -BRDA:105,31,0,30 -BRDA:105,31,1,276 -BRDA:115,32,0,1 -BRDA:115,32,1,400 -BRDA:128,33,0,5 -BRDA:128,33,1,2254 -BRDA:134,34,0,1 -BRDA:134,34,1,2253 -BRDA:138,35,0,685 -BRDA:138,35,1,1568 -BRDA:140,36,0,1084 -BRDA:140,36,1,484 -BRF:75 -BRH:75 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/read-entry.js -FN:7,(anonymous_0) -FN:66,(anonymous_1) -FN:85,(anonymous_2) -FNF:3 -FNH:3 -FNDA:4004,(anonymous_0) -FNDA:2222,(anonymous_1) -FNDA:457,(anonymous_2) -DA:2,11 -DA:3,11 -DA:5,11 -DA:6,11 -DA:8,4004 -DA:9,4004 -DA:10,4004 -DA:11,4004 -DA:12,4004 -DA:13,4004 -DA:14,4004 -DA:15,4004 -DA:16,4004 -DA:17,4004 -DA:18,4004 -DA:29,3241 -DA:37,760 -DA:38,760 -DA:43,3 -DA:46,4004 -DA:47,4004 -DA:48,4004 -DA:49,3720 -DA:50,4004 -DA:51,4004 -DA:52,4004 -DA:53,4004 -DA:54,4004 -DA:55,4004 -DA:56,4004 -DA:57,4004 -DA:58,4004 -DA:59,4004 -DA:60,4004 -DA:62,4004 -DA:63,4004 -DA:67,2222 -DA:68,2222 -DA:69,2 -DA:71,2220 -DA:72,2220 -DA:73,2220 -DA:74,2220 -DA:75,2220 -DA:76,673 -DA:78,1547 -DA:79,132 -DA:82,1415 -DA:86,457 -DA:89,6384 -DA:91,2657 -LF:51 -LH:51 -BRDA:18,0,0,1502 -BRDA:18,0,1,1502 -BRDA:18,0,2,1565 -BRDA:18,0,3,1710 -BRDA:18,0,4,1712 -BRDA:18,0,5,1714 -BRDA:18,0,6,3239 -BRDA:18,0,7,3241 -BRDA:18,0,8,3241 -BRDA:18,0,9,3241 -BRDA:18,0,10,41 -BRDA:18,0,11,121 -BRDA:18,0,12,121 -BRDA:18,0,13,165 -BRDA:18,0,14,760 -BRDA:18,0,15,760 -BRDA:18,0,16,3 -BRDA:48,1,0,3720 -BRDA:48,1,1,284 -BRDA:62,2,0,412 -BRDA:62,2,1,3592 -BRDA:63,3,0,45 -BRDA:63,3,1,3959 -BRDA:68,4,0,2 -BRDA:68,4,1,2220 -BRDA:75,5,0,673 -BRDA:75,5,1,1547 -BRDA:78,6,0,132 -BRDA:78,6,1,1415 -BRDA:89,7,0,2657 -BRDA:89,7,1,3727 -BRDA:89,8,0,6384 -BRDA:89,8,1,2702 -BRDA:89,8,2,2701 -BRDA:90,9,0,2701 -BRDA:90,9,1,89 -BRF:36 -BRH:36 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/replace.js -FN:20,(anonymous_0) -FN:38,(anonymous_1) -FN:92,(anonymous_2) -FN:101,(anonymous_3) -FN:105,(anonymous_4) -FN:106,(anonymous_5) -FN:108,(anonymous_6) -FN:119,(anonymous_7) -FN:156,(anonymous_8) -FN:159,(anonymous_9) -FN:168,(anonymous_10) -FN:171,(anonymous_11) -FN:191,(anonymous_12) -FN:192,(anonymous_13) -FN:198,(anonymous_14) -FN:206,(anonymous_15) -FN:213,(anonymous_16) -FN:214,(anonymous_17) -FNF:18 -FNH:18 -FNDA:70,(anonymous_0) -FNDA:26,(anonymous_1) -FNDA:18,(anonymous_2) -FNDA:41,(anonymous_3) -FNDA:37,(anonymous_4) -FNDA:37,(anonymous_5) -FNDA:4,(anonymous_6) -FNDA:112,(anonymous_7) -FNDA:41,(anonymous_8) -FNDA:45,(anonymous_9) -FNDA:39,(anonymous_10) -FNDA:37,(anonymous_11) -FNDA:18,(anonymous_12) -FNDA:19,(anonymous_13) -FNDA:3,(anonymous_14) -FNDA:34,(anonymous_15) -FNDA:3,(anonymous_16) -FNDA:1,(anonymous_17) -DA:4,3 -DA:5,3 -DA:6,3 -DA:7,3 -DA:8,3 -DA:9,3 -DA:10,3 -DA:18,3 -DA:20,3 -DA:21,70 -DA:23,70 -DA:24,1 -DA:26,69 -DA:27,1 -DA:29,68 -DA:30,1 -DA:32,67 -DA:34,67 -DA:38,3 -DA:39,26 -DA:41,26 -DA:45,26 -DA:46,26 -DA:47,26 -DA:49,4 -DA:50,2 -DA:52,2 -DA:55,24 -DA:56,22 -DA:58,22 -DA:59,61 -DA:60,63 -DA:64,61 -DA:65,2 -DA:67,59 -DA:68,2 -DA:71,55 -DA:72,55 -DA:73,8 -DA:74,47 -DA:75,47 -DA:76,2 -DA:79,45 -DA:80,45 -DA:81,28 -DA:83,18 -DA:85,18 -DA:87,26 -DA:88,8 -DA:92,3 -DA:93,18 -DA:97,18 -DA:98,18 -DA:101,3 -DA:102,41 -DA:103,41 -DA:105,41 -DA:106,37 -DA:107,37 -DA:108,4 -DA:110,33 -DA:113,37 -DA:114,37 -DA:115,8 -DA:117,29 -DA:118,29 -DA:119,29 -DA:120,112 -DA:121,2 -DA:122,110 -DA:123,110 -DA:124,6 -DA:129,104 -DA:130,2 -DA:133,102 -DA:134,4 -DA:136,98 -DA:137,98 -DA:138,13 -DA:140,85 -DA:141,85 -DA:142,4 -DA:144,81 -DA:145,81 -DA:146,4 -DA:148,77 -DA:149,46 -DA:150,77 -DA:151,77 -DA:153,29 -DA:156,41 -DA:157,41 -DA:158,41 -DA:159,41 -DA:160,45 -DA:161,4 -DA:162,4 -DA:165,41 -DA:166,2 -DA:168,39 -DA:169,39 -DA:170,2 -DA:171,37 -DA:172,37 -DA:173,4 -DA:174,33 -DA:178,33 -DA:179,33 -DA:180,33 -DA:181,33 -DA:185,41 -DA:188,41 -DA:191,3 -DA:192,18 -DA:193,19 -DA:194,1 -DA:198,3 -DA:201,18 -DA:203,18 -DA:206,3 -DA:207,34 -DA:208,33 -DA:209,33 -DA:210,1 -DA:213,3 -DA:214,1 -DA:216,32 -DA:218,33 -LF:128 -LH:128 -BRDA:23,0,0,1 -BRDA:23,0,1,69 -BRDA:26,1,0,1 -BRDA:26,1,1,68 -BRDA:29,2,0,1 -BRDA:29,2,1,67 -BRDA:29,3,0,68 -BRDA:29,3,1,68 -BRDA:29,3,2,68 -BRDA:34,4,0,26 -BRDA:34,4,1,41 -BRDA:49,5,0,2 -BRDA:49,5,1,2 -BRDA:64,6,0,2 -BRDA:64,6,1,59 -BRDA:64,7,0,61 -BRDA:64,7,1,16 -BRDA:64,7,2,2 -BRDA:67,8,0,2 -BRDA:67,8,1,57 -BRDA:72,9,0,8 -BRDA:72,9,1,47 -BRDA:75,10,0,2 -BRDA:75,10,1,45 -BRDA:80,11,0,28 -BRDA:80,11,1,17 -BRDA:87,12,0,8 -BRDA:87,12,1,18 -BRDA:107,13,0,4 -BRDA:107,13,1,33 -BRDA:114,14,0,8 -BRDA:114,14,1,29 -BRDA:120,15,0,2 -BRDA:120,15,1,110 -BRDA:123,16,0,6 -BRDA:123,16,1,104 -BRDA:123,17,0,110 -BRDA:123,17,1,12 -BRDA:129,18,0,2 -BRDA:129,18,1,102 -BRDA:129,19,0,104 -BRDA:129,19,1,27 -BRDA:129,19,2,2 -BRDA:133,20,0,4 -BRDA:133,20,1,98 -BRDA:137,21,0,13 -BRDA:137,21,1,85 -BRDA:141,22,0,4 -BRDA:141,22,1,81 -BRDA:145,23,0,4 -BRDA:145,23,1,77 -BRDA:148,24,0,46 -BRDA:148,24,1,31 -BRDA:160,25,0,4 -BRDA:160,25,1,41 -BRDA:160,26,0,45 -BRDA:160,26,1,6 -BRDA:160,26,2,4 -BRDA:165,27,0,2 -BRDA:165,27,1,39 -BRDA:169,28,0,2 -BRDA:169,28,1,37 -BRDA:172,29,0,4 -BRDA:172,29,1,33 -BRDA:188,30,0,24 -BRDA:188,30,1,17 -BRDA:193,31,0,1 -BRDA:193,31,1,18 -BRDA:209,32,0,1 -BRDA:209,32,1,32 -BRF:70 -BRH:70 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/types.js -FN:44,(anonymous_0) -FNF:1 -FNH:1 -FNDA:294,(anonymous_0) -DA:3,14 -DA:44,294 -LF:2 -LH:2 -BRF:0 -BRH:0 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/unpack.js -FN:37,(anonymous_0) -FN:43,(anonymous_1) -FN:47,(anonymous_2) -FN:117,(anonymous_3) -FN:120,(anonymous_4) -FN:129,(anonymous_5) -FN:168,(anonymous_6) -FN:194,(anonymous_7) -FN:207,(anonymous_8) -FN:222,(anonymous_9) -FN:233,(anonymous_10) -FN:237,(anonymous_11) -FN:241,(anonymous_12) -FN:247,(anonymous_13) -FN:250,(anonymous_14) -FN:257,(anonymous_15) -FN:260,(anonymous_16) -FN:277,(anonymous_17) -FN:279,(anonymous_18) -FN:284,(anonymous_19) -FN:305,(anonymous_20) -FN:310,(anonymous_21) -FN:314,(anonymous_22) -FN:318,(anonymous_23) -FN:322,(anonymous_24) -FN:327,(anonymous_25) -FN:333,(anonymous_26) -FN:335,(anonymous_27) -FN:338,(anonymous_28) -FN:348,(anonymous_29) -FN:350,(anonymous_30) -FN:352,(anonymous_31) -FN:357,(anonymous_32) -FN:379,(anonymous_33) -FN:381,(anonymous_34) -FN:391,(anonymous_35) -FN:395,(anonymous_36) -FN:425,(anonymous_37) -FN:428,(anonymous_38) -FN:441,(anonymous_39) -FN:449,(anonymous_40) -FN:465,(anonymous_41) -FN:483,(anonymous_42) -FN:502,(anonymous_43) -FNF:44 -FNH:44 -FNDA:60,(anonymous_0) -FNDA:134,(anonymous_1) -FNDA:109,(anonymous_2) -FNDA:571,(anonymous_3) -FNDA:473,(anonymous_4) -FNDA:571,(anonymous_5) -FNDA:571,(anonymous_6) -FNDA:39,(anonymous_7) -FNDA:451,(anonymous_8) -FNDA:473,(anonymous_9) -FNDA:30,(anonymous_10) -FNDA:30,(anonymous_11) -FNDA:221,(anonymous_12) -FNDA:2,(anonymous_13) -FNDA:421,(anonymous_14) -FNDA:219,(anonymous_15) -FNDA:219,(anonymous_16) -FNDA:97,(anonymous_17) -FNDA:97,(anonymous_18) -FNDA:171,(anonymous_19) -FNDA:6,(anonymous_20) -FNDA:21,(anonymous_21) -FNDA:19,(anonymous_22) -FNDA:354,(anonymous_23) -FNDA:364,(anonymous_24) -FNDA:4,(anonymous_25) -FNDA:354,(anonymous_26) -FNDA:354,(anonymous_27) -FNDA:342,(anonymous_28) -FNDA:2,(anonymous_29) -FNDA:5,(anonymous_30) -FNDA:6,(anonymous_31) -FNDA:528,(anonymous_32) -FNDA:21,(anonymous_33) -FNDA:21,(anonymous_34) -FNDA:59,(anonymous_35) -FNDA:200,(anonymous_36) -FNDA:93,(anonymous_37) -FNDA:6,(anonymous_38) -FNDA:86,(anonymous_39) -FNDA:86,(anonymous_40) -FNDA:76,(anonymous_41) -FNDA:276,(anonymous_42) -FNDA:19,(anonymous_43) -DA:3,3 -DA:4,3 -DA:5,3 -DA:6,3 -DA:7,3 -DA:8,3 -DA:9,3 -DA:10,3 -DA:11,3 -DA:13,3 -DA:14,3 -DA:15,3 -DA:16,3 -DA:17,3 -DA:18,3 -DA:19,3 -DA:20,3 -DA:21,3 -DA:22,3 -DA:23,3 -DA:24,3 -DA:25,3 -DA:26,3 -DA:27,3 -DA:28,3 -DA:29,3 -DA:30,3 -DA:31,3 -DA:32,3 -DA:33,3 -DA:34,3 -DA:37,3 -DA:38,60 -DA:44,134 -DA:45,4 -DA:47,134 -DA:48,109 -DA:49,109 -DA:52,134 -DA:54,134 -DA:55,134 -DA:57,134 -DA:58,134 -DA:60,134 -DA:62,134 -DA:64,9 -DA:65,2 -DA:66,7 -DA:67,1 -DA:69,6 -DA:70,6 -DA:71,6 -DA:73,125 -DA:74,125 -DA:75,125 -DA:79,131 -DA:80,119 -DA:82,12 -DA:84,131 -DA:86,131 -DA:90,131 -DA:93,131 -DA:96,131 -DA:99,131 -DA:104,131 -DA:108,131 -DA:110,131 -DA:111,131 -DA:112,131 -DA:113,131 -DA:115,131 -DA:116,131 -DA:117,571 -DA:121,473 -DA:122,98 -DA:123,98 -DA:124,98 -DA:125,98 -DA:130,571 -DA:131,144 -DA:132,144 -DA:133,9 -DA:134,135 -DA:137,562 -DA:138,545 -DA:139,545 -DA:140,2 -DA:141,2 -DA:146,543 -DA:147,2 -DA:148,2 -DA:149,2 -DA:154,560 -DA:155,3 -DA:156,3 -DA:160,560 -DA:161,2 -DA:163,558 -DA:165,560 -DA:169,571 -DA:170,11 -DA:172,560 -DA:174,560 -DA:177,179 -DA:178,140 -DA:185,554 -DA:190,6 -DA:198,39 -DA:199,12 -DA:201,27 -DA:202,27 -DA:203,27 -DA:208,451 -DA:225,473 -DA:234,30 -DA:238,30 -DA:242,221 -DA:243,221 -DA:247,221 -DA:249,221 -DA:250,221 -DA:251,421 -DA:252,1 -DA:253,1 -DA:256,421 -DA:257,219 -DA:260,221 -DA:261,219 -DA:262,192 -DA:263,192 -DA:266,219 -DA:267,10 -DA:268,10 -DA:271,219 -DA:274,221 -DA:278,97 -DA:279,97 -DA:280,97 -DA:281,3 -DA:283,94 -DA:284,94 -DA:285,171 -DA:286,94 -DA:287,94 -DA:291,94 -DA:292,73 -DA:293,73 -DA:296,94 -DA:297,4 -DA:298,4 -DA:301,94 -DA:306,6 -DA:307,6 -DA:311,21 -DA:315,19 -DA:319,354 -DA:323,364 -DA:324,364 -DA:328,4 -DA:329,4 -DA:334,354 -DA:335,354 -DA:336,354 -DA:337,12 -DA:338,342 -DA:339,342 -DA:340,2 -DA:341,340 -DA:342,318 -DA:343,22 -DA:344,16 -DA:345,11 -DA:346,9 -DA:348,2 -DA:350,5 -DA:352,6 -DA:358,528 -DA:359,1 -DA:361,527 -DA:365,314 -DA:368,19 -DA:371,21 -DA:375,173 -DA:381,21 -DA:382,21 -DA:383,1 -DA:384,20 -DA:385,20 -DA:392,59 -DA:396,200 -DA:397,200 -DA:398,9 -DA:399,191 -DA:400,191 -DA:401,17 -DA:402,2 -DA:403,15 -DA:404,2 -DA:406,13 -DA:407,13 -DA:408,6 -DA:409,3 -DA:410,2 -DA:412,3 -DA:414,7 -DA:415,12 -DA:417,1 -DA:421,174 -DA:426,93 -DA:428,93 -DA:429,6 -DA:430,6 -DA:435,93 -DA:436,93 -DA:438,1 -DA:441,92 -DA:442,86 -DA:443,86 -DA:445,1 -DA:449,92 -DA:450,86 -DA:451,86 -DA:452,58 -DA:454,85 -DA:455,12 -DA:457,82 -DA:459,4 -DA:466,76 -DA:467,76 -DA:468,76 -DA:469,1 -DA:470,75 -DA:471,56 -DA:472,56 -DA:475,75 -DA:476,4 -DA:477,4 -DA:480,75 -DA:484,276 -DA:485,276 -DA:498,4 -DA:503,19 -DA:504,19 -DA:505,17 -DA:507,2 -DA:512,3 -DA:513,3 -LF:247 -LH:247 -BRDA:38,0,0,24 -BRDA:38,0,1,36 -BRDA:39,1,0,26 -BRDA:39,1,1,10 -BRDA:44,2,0,4 -BRDA:44,2,1,130 -BRDA:60,3,0,134 -BRDA:60,3,1,134 -BRDA:62,4,0,9 -BRDA:62,4,1,125 -BRDA:62,5,0,134 -BRDA:62,5,1,126 -BRDA:64,6,0,2 -BRDA:64,6,1,7 -BRDA:64,7,0,9 -BRDA:64,7,1,8 -BRDA:66,8,0,1 -BRDA:66,8,1,6 -BRDA:79,9,0,119 -BRDA:79,9,1,12 -BRDA:79,10,0,131 -BRDA:79,10,1,125 -BRDA:80,11,0,119 -BRDA:80,11,1,119 -BRDA:84,12,0,11 -BRDA:84,12,1,120 -BRDA:84,13,0,131 -BRDA:84,13,1,126 -BRDA:84,13,2,11 -BRDA:86,14,0,11 -BRDA:86,14,1,120 -BRDA:86,15,0,131 -BRDA:86,15,1,126 -BRDA:86,15,2,11 -BRDA:90,16,0,131 -BRDA:90,16,1,128 -BRDA:110,17,0,131 -BRDA:110,17,1,11 -BRDA:111,18,0,131 -BRDA:111,18,1,129 -BRDA:113,19,0,1 -BRDA:113,19,1,130 -BRDA:115,20,0,131 -BRDA:115,20,1,131 -BRDA:116,21,0,131 -BRDA:116,21,1,127 -BRDA:121,22,0,98 -BRDA:121,22,1,375 -BRDA:121,23,0,473 -BRDA:121,23,1,178 -BRDA:130,24,0,144 -BRDA:130,24,1,427 -BRDA:132,25,0,9 -BRDA:132,25,1,135 -BRDA:137,26,0,545 -BRDA:137,26,1,17 -BRDA:139,27,0,2 -BRDA:139,27,1,543 -BRDA:146,28,0,2 -BRDA:146,28,1,541 -BRDA:154,29,0,3 -BRDA:154,29,1,557 -BRDA:156,30,0,2 -BRDA:156,30,1,1 -BRDA:160,31,0,2 -BRDA:160,31,1,558 -BRDA:169,32,0,11 -BRDA:169,32,1,560 -BRDA:174,33,0,179 -BRDA:174,33,1,179 -BRDA:174,33,2,514 -BRDA:174,33,3,514 -BRDA:174,33,4,514 -BRDA:174,33,5,533 -BRDA:174,33,6,554 -BRDA:174,33,7,2 -BRDA:174,33,8,4 -BRDA:174,33,9,6 -BRDA:177,34,0,140 -BRDA:177,34,1,39 -BRDA:198,35,0,12 -BRDA:198,35,1,27 -BRDA:225,36,0,473 -BRDA:225,36,1,34 -BRDA:225,36,2,31 -BRDA:225,36,3,23 -BRDA:225,36,4,15 -BRDA:225,36,5,455 -BRDA:225,36,6,12 -BRDA:225,36,7,447 -BRDA:225,36,8,4 -BRDA:242,37,0,221 -BRDA:242,37,1,30 -BRDA:251,38,0,1 -BRDA:251,38,1,420 -BRDA:256,39,0,219 -BRDA:256,39,1,202 -BRDA:261,40,0,192 -BRDA:261,40,1,27 -BRDA:261,41,0,219 -BRDA:261,41,1,193 -BRDA:263,42,0,192 -BRDA:263,42,1,156 -BRDA:266,43,0,10 -BRDA:266,43,1,209 -BRDA:278,44,0,97 -BRDA:278,44,1,20 -BRDA:280,45,0,3 -BRDA:280,45,1,94 -BRDA:285,46,0,94 -BRDA:285,46,1,77 -BRDA:291,47,0,73 -BRDA:291,47,1,21 -BRDA:291,48,0,94 -BRDA:291,48,1,74 -BRDA:293,49,0,73 -BRDA:293,49,1,71 -BRDA:296,50,0,4 -BRDA:296,50,1,90 -BRDA:336,51,0,12 -BRDA:336,51,1,342 -BRDA:339,52,0,2 -BRDA:339,52,1,340 -BRDA:339,53,0,342 -BRDA:339,53,1,27 -BRDA:339,53,2,26 -BRDA:339,53,3,1 -BRDA:341,54,0,318 -BRDA:341,54,1,22 -BRDA:341,55,0,340 -BRDA:341,55,1,25 -BRDA:341,55,2,6 -BRDA:341,55,3,5 -BRDA:343,56,0,16 -BRDA:343,56,1,6 -BRDA:344,57,0,11 -BRDA:344,57,1,5 -BRDA:345,58,0,9 -BRDA:345,58,1,2 -BRDA:345,59,0,11 -BRDA:345,59,1,8 -BRDA:358,60,0,1 -BRDA:358,60,1,527 -BRDA:361,61,0,314 -BRDA:361,61,1,314 -BRDA:361,61,2,314 -BRDA:361,61,3,19 -BRDA:361,61,4,21 -BRDA:361,61,5,173 -BRDA:361,61,6,173 -BRDA:382,62,0,1 -BRDA:382,62,1,20 -BRDA:397,63,0,9 -BRDA:397,63,1,191 -BRDA:401,64,0,2 -BRDA:401,64,1,15 -BRDA:401,65,0,17 -BRDA:401,65,1,16 -BRDA:401,65,2,1 -BRDA:403,66,0,2 -BRDA:403,66,1,13 -BRDA:403,67,0,15 -BRDA:403,67,1,4 -BRDA:403,67,2,3 -BRDA:407,68,0,6 -BRDA:407,68,1,7 -BRDA:408,69,0,3 -BRDA:408,69,1,3 -BRDA:409,70,0,2 -BRDA:409,70,1,1 -BRDA:409,71,0,3 -BRDA:409,71,1,2 -BRDA:426,72,0,93 -BRDA:426,72,1,30 -BRDA:451,73,0,58 -BRDA:451,73,1,28 -BRDA:451,74,0,86 -BRDA:451,74,1,59 -BRDA:452,75,0,58 -BRDA:452,75,1,31 -BRDA:454,76,0,12 -BRDA:454,76,1,73 -BRDA:466,77,0,76 -BRDA:466,77,1,19 -BRDA:468,78,0,1 -BRDA:468,78,1,75 -BRDA:470,79,0,56 -BRDA:470,79,1,19 -BRDA:470,80,0,75 -BRDA:470,80,1,57 -BRDA:472,81,0,56 -BRDA:472,81,1,52 -BRDA:475,82,0,4 -BRDA:475,82,1,71 -BRF:194 -BRH:194 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/update.js -FN:9,(anonymous_0) -FN:27,(anonymous_1) -FN:33,(anonymous_2) -FN:35,(anonymous_3) -FNF:4 -FNH:4 -FNDA:36,(anonymous_0) -FNDA:33,(anonymous_1) -FNDA:2,(anonymous_2) -FNDA:24,(anonymous_3) -DA:5,2 -DA:6,2 -DA:9,2 -DA:10,36 -DA:12,36 -DA:13,1 -DA:15,35 -DA:16,1 -DA:18,34 -DA:19,1 -DA:21,33 -DA:23,33 -DA:24,33 -DA:27,2 -DA:28,33 -DA:30,33 -DA:31,32 -DA:33,33 -DA:34,2 -DA:35,24 -LF:20 -LH:20 -BRDA:12,0,0,1 -BRDA:12,0,1,35 -BRDA:15,1,0,1 -BRDA:15,1,1,34 -BRDA:18,2,0,1 -BRDA:18,2,1,33 -BRDA:18,3,0,34 -BRDA:18,3,1,34 -BRDA:18,3,2,34 -BRDA:30,4,0,32 -BRDA:30,4,1,1 -BRDA:33,5,0,1 -BRDA:33,5,1,32 -BRDA:34,6,0,2 -BRDA:34,6,1,1 -BRF:15 -BRH:15 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/warn-mixin.js -FN:2,(anonymous_0) -FN:3,(anonymous_1) -FNF:2 -FNH:2 -FNDA:27,(anonymous_0) -FNDA:333,(anonymous_1) -DA:2,27 -DA:4,333 -DA:5,184 -DA:6,149 -DA:7,2 -DA:9,147 -DA:10,147 -DA:11,147 -LF:8 -LH:8 -BRDA:4,0,0,184 -BRDA:4,0,1,149 -BRDA:6,1,0,2 -BRDA:6,1,1,147 -BRF:4 -BRH:4 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/winchars.js -FN:14,(anonymous_0) -FN:17,(anonymous_1) -FN:18,(anonymous_2) -FN:21,(anonymous_3) -FN:21,(anonymous_4) -FN:22,(anonymous_5) -FN:22,(anonymous_6) -FNF:7 -FNH:7 -FNDA:45,(anonymous_0) -FNDA:45,(anonymous_1) -FNDA:45,(anonymous_2) -FNDA:6,(anonymous_3) -FNDA:30,(anonymous_4) -FNDA:4,(anonymous_5) -FNDA:20,(anonymous_6) -DA:6,9 -DA:14,9 -DA:15,45 -DA:17,45 -DA:18,45 -DA:20,9 -DA:21,30 -DA:22,20 -LF:8 -LH:8 -BRF:0 -BRH:0 -end_of_record -TN: -SF:/Users/isaacs/dev/js/tar/lib/write-entry.js -FN:29,(anonymous_0) -FN:77,(anonymous_1) -FN:78,(anonymous_2) -FN:85,(anonymous_3) -FN:95,(anonymous_4) -FN:105,(anonymous_5) -FN:144,(anonymous_6) -FN:152,(anonymous_7) -FN:153,(anonymous_8) -FN:160,(anonymous_9) -FN:166,(anonymous_10) -FN:174,(anonymous_11) -FN:192,(anonymous_12) -FN:193,(anonymous_13) -FN:200,(anonymous_14) -FN:207,(anonymous_15) -FN:208,(anonymous_16) -FN:210,(anonymous_17) -FN:215,(anonymous_18) -FN:219,(anonymous_19) -FN:250,(anonymous_20) -FN:264,(anonymous_21) -FN:268,(anonymous_22) -FN:272,(anonymous_23) -FN:276,(anonymous_24) -FN:280,(anonymous_25) -FN:292,(anonymous_26) -FN:298,(anonymous_27) -FN:377,(anonymous_28) -FN:385,(anonymous_29) -FN:395,(anonymous_30) -FNF:31 -FNH:31 -FNDA:6570,(anonymous_0) -FNDA:34,(anonymous_1) -FNDA:34,(anonymous_2) -FNDA:6566,(anonymous_3) -FNDA:6566,(anonymous_4) -FNDA:6563,(anonymous_5) -FNDA:867,(anonymous_6) -FNDA:32,(anonymous_7) -FNDA:32,(anonymous_8) -FNDA:32,(anonymous_9) -FNDA:1,(anonymous_10) -FNDA:5664,(anonymous_11) -FNDA:5568,(anonymous_12) -FNDA:5568,(anonymous_13) -FNDA:5617,(anonymous_14) -FNDA:7336,(anonymous_15) -FNDA:7336,(anonymous_16) -FNDA:1,(anonymous_17) -FNDA:5566,(anonymous_18) -FNDA:7393,(anonymous_19) -FNDA:5565,(anonymous_20) -FNDA:99,(anonymous_21) -FNDA:20,(anonymous_22) -FNDA:2,(anonymous_23) -FNDA:53,(anonymous_24) -FNDA:59,(anonymous_25) -FNDA:51,(anonymous_26) -FNDA:33,(anonymous_27) -FNDA:52,(anonymous_28) -FNDA:29,(anonymous_29) -FNDA:6566,(anonymous_30) -DA:2,6 -DA:3,6 -DA:4,6 -DA:5,6 -DA:6,6 -DA:7,6 -DA:9,6 -DA:10,6 -DA:11,6 -DA:12,6 -DA:13,6 -DA:14,6 -DA:15,6 -DA:16,6 -DA:17,6 -DA:18,6 -DA:19,6 -DA:20,6 -DA:21,6 -DA:22,6 -DA:23,6 -DA:24,6 -DA:25,6 -DA:26,6 -DA:28,6 -DA:30,6570 -DA:31,6570 -DA:32,6570 -DA:33,1 -DA:34,6569 -DA:36,6569 -DA:38,6569 -DA:39,6569 -DA:40,6569 -DA:41,6569 -DA:42,6569 -DA:43,6569 -DA:44,6569 -DA:45,6569 -DA:46,6569 -DA:47,6569 -DA:49,6569 -DA:50,6515 -DA:52,6569 -DA:55,4 -DA:56,4 -DA:57,2 -DA:60,6567 -DA:61,6567 -DA:62,2 -DA:63,2 -DA:66,6567 -DA:68,6567 -DA:69,1 -DA:71,6567 -DA:72,6513 -DA:74,54 -DA:78,34 -DA:79,34 -DA:80,1 -DA:81,33 -DA:86,6566 -DA:87,6566 -DA:88,6566 -DA:89,902 -DA:90,6566 -DA:91,6566 -DA:92,6566 -DA:96,6566 -DA:97,5664 -DA:98,867 -DA:99,34 -DA:101,1 -DA:106,6563 -DA:107,4 -DA:109,6563 -DA:126,6563 -DA:127,17 -DA:141,6563 -DA:145,867 -DA:146,859 -DA:147,867 -DA:148,867 -DA:149,867 -DA:153,32 -DA:154,32 -DA:155,1 -DA:156,31 -DA:161,32 -DA:162,32 -DA:163,32 -DA:167,1 -DA:168,1 -DA:169,1 -DA:170,1 -DA:171,1 -DA:175,5664 -DA:176,7 -DA:177,7 -DA:178,2 -DA:179,2 -DA:180,1 -DA:182,6 -DA:185,5663 -DA:186,5663 -DA:187,42 -DA:189,5621 -DA:193,5568 -DA:194,5568 -DA:195,2 -DA:196,5566 -DA:201,5617 -DA:202,5617 -DA:203,5617 -DA:204,5617 -DA:208,7336 -DA:209,7336 -DA:210,1 -DA:211,7335 -DA:216,5566 -DA:220,7393 -DA:221,2 -DA:222,2 -DA:223,2 -DA:224,2 -DA:225,2 -DA:229,7392 -DA:230,5614 -DA:231,1700449 -DA:232,1700449 -DA:233,1700449 -DA:237,7392 -DA:239,7392 -DA:240,7392 -DA:241,7392 -DA:242,7392 -DA:244,7392 -DA:246,7392 -DA:247,5614 -DA:248,2 -DA:249,5614 -DA:250,5614 -DA:251,5614 -DA:254,1778 -DA:255,1754 -DA:256,1754 -DA:258,1778 -DA:259,1778 -DA:265,99 -DA:269,20 -DA:273,2 -DA:277,53 -DA:281,59 -DA:282,59 -DA:283,59 -DA:284,58 -DA:285,57 -DA:287,59 -DA:288,2 -DA:293,51 -DA:297,6 -DA:299,33 -DA:300,33 -DA:301,33 -DA:302,33 -DA:303,33 -DA:304,33 -DA:305,33 -DA:307,33 -DA:308,33 -DA:309,33 -DA:310,0 -DA:312,33 -DA:313,33 -DA:314,33 -DA:315,26 -DA:316,33 -DA:317,33 -DA:318,33 -DA:319,33 -DA:320,33 -DA:321,33 -DA:322,33 -DA:323,33 -DA:324,33 -DA:326,33 -DA:327,27 -DA:329,33 -DA:330,2 -DA:331,2 -DA:335,1 -DA:338,32 -DA:339,32 -DA:341,32 -DA:357,32 -DA:358,14 -DA:373,32 -DA:374,32 -DA:378,52 -DA:379,52 -DA:380,1 -DA:381,51 -DA:382,51 -DA:386,29 -DA:387,22 -DA:388,29 -DA:392,6 -DA:393,6 -DA:395,6 -DA:396,6566 -DA:401,6 -LF:211 -LH:210 -BRDA:30,0,0,6570 -BRDA:30,0,1,2 -BRDA:32,1,0,1 -BRDA:32,1,1,6569 -BRDA:38,2,0,6569 -BRDA:38,2,1,6569 -BRDA:39,3,0,6569 -BRDA:39,3,1,37 -BRDA:40,4,0,6569 -BRDA:40,4,1,6563 -BRDA:41,5,0,6569 -BRDA:41,5,1,53 -BRDA:42,6,0,6569 -BRDA:42,6,1,55 -BRDA:44,7,0,6569 -BRDA:44,7,1,4 -BRDA:49,8,0,6515 -BRDA:49,8,1,54 -BRDA:52,9,0,4 -BRDA:52,9,1,6565 -BRDA:52,10,0,6569 -BRDA:52,10,1,6564 -BRDA:60,11,0,6567 -BRDA:60,11,1,6565 -BRDA:61,12,0,2 -BRDA:61,12,1,6565 -BRDA:66,13,0,6567 -BRDA:66,13,1,54 -BRDA:68,14,0,1 -BRDA:68,14,1,6566 -BRDA:71,15,0,6513 -BRDA:71,15,1,54 -BRDA:79,16,0,1 -BRDA:79,16,1,33 -BRDA:88,17,0,902 -BRDA:88,17,1,5664 -BRDA:96,18,0,5664 -BRDA:96,18,1,867 -BRDA:96,18,2,34 -BRDA:96,18,3,1 -BRDA:106,19,0,4 -BRDA:106,19,1,6559 -BRDA:106,20,0,6563 -BRDA:106,20,1,867 -BRDA:115,21,0,10 -BRDA:115,21,1,6553 -BRDA:116,22,0,10 -BRDA:116,22,1,6553 -BRDA:118,23,0,6 -BRDA:118,23,1,6557 -BRDA:120,24,0,10 -BRDA:120,24,1,6553 -BRDA:121,25,0,6552 -BRDA:121,25,1,1 -BRDA:122,26,0,10 -BRDA:122,26,1,6553 -BRDA:123,27,0,10 -BRDA:123,27,1,6553 -BRDA:126,28,0,17 -BRDA:126,28,1,6546 -BRDA:126,29,0,6563 -BRDA:126,29,1,18 -BRDA:128,30,0,4 -BRDA:128,30,1,13 -BRDA:129,31,0,4 -BRDA:129,31,1,13 -BRDA:130,32,0,4 -BRDA:130,32,1,13 -BRDA:131,33,0,2 -BRDA:131,33,1,15 -BRDA:135,34,0,4 -BRDA:135,34,1,13 -BRDA:136,35,0,4 -BRDA:136,35,1,13 -BRDA:137,36,0,4 -BRDA:137,36,1,13 -BRDA:138,37,0,4 -BRDA:138,37,1,13 -BRDA:139,38,0,4 -BRDA:139,38,1,13 -BRDA:145,39,0,859 -BRDA:145,39,1,8 -BRDA:154,40,0,1 -BRDA:154,40,1,31 -BRDA:175,41,0,7 -BRDA:175,41,1,5657 -BRDA:177,42,0,2 -BRDA:177,42,1,5 -BRDA:179,43,0,1 -BRDA:179,43,1,1 -BRDA:186,44,0,42 -BRDA:186,44,1,5621 -BRDA:194,45,0,2 -BRDA:194,45,1,5566 -BRDA:209,46,0,1 -BRDA:209,46,1,7335 -BRDA:220,47,0,2 -BRDA:220,47,1,7391 -BRDA:220,48,0,7393 -BRDA:220,48,1,2 -BRDA:229,49,0,5614 -BRDA:229,49,1,1778 -BRDA:230,50,0,1706063 -BRDA:230,50,1,1700456 -BRDA:237,51,0,7338 -BRDA:237,51,1,54 -BRDA:237,52,0,7392 -BRDA:237,52,1,7369 -BRDA:246,53,0,5614 -BRDA:246,53,1,1778 -BRDA:247,54,0,2 -BRDA:247,54,1,5612 -BRDA:254,55,0,1754 -BRDA:254,55,1,24 -BRDA:287,56,0,2 -BRDA:287,56,1,57 -BRDA:299,57,0,33 -BRDA:299,57,1,4 -BRDA:309,58,0,0 -BRDA:309,58,1,33 -BRDA:309,59,0,33 -BRDA:309,59,1,2 -BRDA:314,60,0,26 -BRDA:314,60,1,7 -BRDA:316,61,0,1 -BRDA:316,61,1,32 -BRDA:317,62,0,1 -BRDA:317,62,1,32 -BRDA:318,63,0,1 -BRDA:318,63,1,32 -BRDA:319,64,0,1 -BRDA:319,64,1,32 -BRDA:321,65,0,0 -BRDA:321,65,1,33 -BRDA:322,66,0,1 -BRDA:322,66,1,32 -BRDA:323,67,0,1 -BRDA:323,67,1,32 -BRDA:326,68,0,27 -BRDA:326,68,1,6 -BRDA:329,69,0,2 -BRDA:329,69,1,31 -BRDA:329,70,0,33 -BRDA:329,70,1,3 -BRDA:347,71,0,1 -BRDA:347,71,1,31 -BRDA:348,72,0,1 -BRDA:348,72,1,31 -BRDA:350,73,0,0 -BRDA:350,73,1,32 -BRDA:352,74,0,1 -BRDA:352,74,1,31 -BRDA:353,75,0,1 -BRDA:353,75,1,31 -BRDA:354,76,0,1 -BRDA:354,76,1,31 -BRDA:357,77,0,14 -BRDA:357,77,1,18 -BRDA:357,78,0,32 -BRDA:357,78,1,14 -BRDA:359,79,0,1 -BRDA:359,79,1,13 -BRDA:360,80,0,1 -BRDA:360,80,1,13 -BRDA:361,81,0,1 -BRDA:361,81,1,13 -BRDA:362,82,0,0 -BRDA:362,82,1,14 -BRDA:366,83,0,1 -BRDA:366,83,1,13 -BRDA:367,84,0,1 -BRDA:367,84,1,13 -BRDA:368,85,0,1 -BRDA:368,85,1,13 -BRDA:369,86,0,1 -BRDA:369,86,1,13 -BRDA:370,87,0,1 -BRDA:370,87,1,13 -BRDA:379,88,0,1 -BRDA:379,88,1,51 -BRDA:386,89,0,22 -BRDA:386,89,1,7 -BRDA:396,90,0,5664 -BRDA:396,90,1,902 -BRDA:397,91,0,867 -BRDA:397,91,1,35 -BRDA:398,92,0,34 -BRDA:398,92,1,1 -BRF:188 -BRH:184 -end_of_record diff --git a/node_modules/npm-lifecycle/node_modules/tar/examples/extracter.js b/node_modules/npm-lifecycle/node_modules/tar/examples/extracter.js deleted file mode 100644 index f6253a72c5cd3..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/examples/extracter.js +++ /dev/null @@ -1,19 +0,0 @@ -var tar = require("../tar.js") - , fs = require("fs") - - -function onError(err) { - console.error('An error occurred:', err) -} - -function onEnd() { - console.log('Extracted!') -} - -var extractor = tar.Extract({path: __dirname + "/extract"}) - .on('error', onError) - .on('end', onEnd); - -fs.createReadStream(__dirname + "/../test/fixtures/c.tar") - .on('error', onError) - .pipe(extractor); diff --git a/node_modules/npm-lifecycle/node_modules/tar/examples/packer.js b/node_modules/npm-lifecycle/node_modules/tar/examples/packer.js deleted file mode 100644 index 039969ce300d1..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/examples/packer.js +++ /dev/null @@ -1,24 +0,0 @@ -var tar = require("../tar.js") - , fstream = require("fstream") - , fs = require("fs") - -var dirDest = fs.createWriteStream('dir.tar') - - -function onError(err) { - console.error('An error occurred:', err) -} - -function onEnd() { - console.log('Packed!') -} - -var packer = tar.Pack({ noProprietary: true }) - .on('error', onError) - .on('end', onEnd); - -// This must be a "directory" -fstream.Reader({ path: __dirname, type: "Directory" }) - .on('error', onError) - .pipe(packer) - .pipe(dirDest) diff --git a/node_modules/npm-lifecycle/node_modules/tar/examples/reader.js b/node_modules/npm-lifecycle/node_modules/tar/examples/reader.js deleted file mode 100644 index 39f3f0888a2cf..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/examples/reader.js +++ /dev/null @@ -1,36 +0,0 @@ -var tar = require("../tar.js") - , fs = require("fs") - -fs.createReadStream(__dirname + "/../test/fixtures/c.tar") - .pipe(tar.Parse()) - .on("extendedHeader", function (e) { - console.error("extended pax header", e.props) - e.on("end", function () { - console.error("extended pax fields:", e.fields) - }) - }) - .on("ignoredEntry", function (e) { - console.error("ignoredEntry?!?", e.props) - }) - .on("longLinkpath", function (e) { - console.error("longLinkpath entry", e.props) - e.on("end", function () { - console.error("value=%j", e.body.toString()) - }) - }) - .on("longPath", function (e) { - console.error("longPath entry", e.props) - e.on("end", function () { - console.error("value=%j", e.body.toString()) - }) - }) - .on("entry", function (e) { - console.error("entry", e.props) - e.on("data", function (c) { - console.error(" >>>" + c.toString().replace(/\n/g, "\\n")) - }) - e.on("end", function () { - console.error(" << 0 - return !this._needDrain -} - -EntryWriter.prototype.end = function (c) { - // console.error(".. ew end") - if (c) this._buffer.push(c) - this._buffer.push(EOF) - this._ended = true - this._process() - this._needDrain = this._buffer.length > 0 -} - -EntryWriter.prototype.pause = function () { - // console.error(".. ew pause") - this._paused = true - this.emit("pause") -} - -EntryWriter.prototype.resume = function () { - // console.error(".. ew resume") - this._paused = false - this.emit("resume") - this._process() -} - -EntryWriter.prototype.add = function (entry) { - // console.error(".. ew add") - if (!this.parent) return this.emit("error", new Error("no parent")) - - // make sure that the _header and such is emitted, and clear out - // the _currentEntry link on the parent. - if (!this._ended) this.end() - - return this.parent.add(entry) -} - -EntryWriter.prototype._header = function () { - // console.error(".. ew header") - if (this._didHeader) return - this._didHeader = true - - var headerBlock = TarHeader.encode(this.props) - - if (this.props.needExtended && !this._meta) { - var me = this - - ExtendedHeaderWriter = ExtendedHeaderWriter || - require("./extended-header-writer.js") - - ExtendedHeaderWriter(this.props) - .on("data", function (c) { - me.emit("data", c) - }) - .on("error", function (er) { - me.emit("error", er) - }) - .end() - } - - // console.error(".. .. ew headerBlock emitting") - this.emit("data", headerBlock) - this.emit("header") -} - -EntryWriter.prototype._process = function () { - // console.error(".. .. ew process") - if (!this._didHeader && !this._meta) { - this._header() - } - - if (this._paused || this._processing) { - // console.error(".. .. .. paused=%j, processing=%j", this._paused, this._processing) - return - } - - this._processing = true - - var buf = this._buffer - for (var i = 0; i < buf.length; i ++) { - // console.error(".. .. .. i=%d", i) - - var c = buf[i] - - if (c === EOF) this._stream.end() - else this._stream.write(c) - - if (this._paused) { - // console.error(".. .. .. paused mid-emission") - this._processing = false - if (i < buf.length) { - this._needDrain = true - this._buffer = buf.slice(i + 1) - } - return - } - } - - // console.error(".. .. .. emitted") - this._buffer.length = 0 - this._processing = false - - // console.error(".. .. .. emitting drain") - this.emit("drain") -} - -EntryWriter.prototype.destroy = function () {} diff --git a/node_modules/npm-lifecycle/node_modules/tar/lib/entry.js b/node_modules/npm-lifecycle/node_modules/tar/lib/entry.js deleted file mode 100644 index 591202bd3b9af..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/lib/entry.js +++ /dev/null @@ -1,220 +0,0 @@ -// A passthrough read/write stream that sets its properties -// based on a header, extendedHeader, and globalHeader -// -// Can be either a file system object of some sort, or -// a pax/ustar metadata entry. - -module.exports = Entry - -var TarHeader = require("./header.js") - , tar = require("../tar") - , assert = require("assert").ok - , Stream = require("stream").Stream - , inherits = require("inherits") - , fstream = require("fstream").Abstract - -function Entry (header, extended, global) { - Stream.call(this) - this.readable = true - this.writable = true - - this._needDrain = false - this._paused = false - this._reading = false - this._ending = false - this._ended = false - this._remaining = 0 - this._abort = false - this._queue = [] - this._index = 0 - this._queueLen = 0 - - this._read = this._read.bind(this) - - this.props = {} - this._header = header - this._extended = extended || {} - - // globals can change throughout the course of - // a file parse operation. Freeze it at its current state. - this._global = {} - var me = this - Object.keys(global || {}).forEach(function (g) { - me._global[g] = global[g] - }) - - this._setProps() -} - -inherits(Entry, Stream) - -Entry.prototype.write = function (c) { - if (this._ending) this.error("write() after end()", null, true) - if (this._remaining === 0) { - this.error("invalid bytes past eof") - } - - // often we'll get a bunch of \0 at the end of the last write, - // since chunks will always be 512 bytes when reading a tarball. - if (c.length > this._remaining) { - c = c.slice(0, this._remaining) - } - this._remaining -= c.length - - // put it on the stack. - var ql = this._queueLen - this._queue.push(c) - this._queueLen ++ - - this._read() - - // either paused, or buffered - if (this._paused || ql > 0) { - this._needDrain = true - return false - } - - return true -} - -Entry.prototype.end = function (c) { - if (c) this.write(c) - this._ending = true - this._read() -} - -Entry.prototype.pause = function () { - this._paused = true - this.emit("pause") -} - -Entry.prototype.resume = function () { - // console.error(" Tar Entry resume", this.path) - this.emit("resume") - this._paused = false - this._read() - return this._queueLen - this._index > 1 -} - - // This is bound to the instance -Entry.prototype._read = function () { - // console.error(" Tar Entry _read", this.path) - - if (this._paused || this._reading || this._ended) return - - // set this flag so that event handlers don't inadvertently - // get multiple _read() calls running. - this._reading = true - - // have any data to emit? - while (this._index < this._queueLen && !this._paused) { - var chunk = this._queue[this._index ++] - this.emit("data", chunk) - } - - // check if we're drained - if (this._index >= this._queueLen) { - this._queue.length = this._queueLen = this._index = 0 - if (this._needDrain) { - this._needDrain = false - this.emit("drain") - } - if (this._ending) { - this._ended = true - this.emit("end") - } - } - - // if the queue gets too big, then pluck off whatever we can. - // this should be fairly rare. - var mql = this._maxQueueLen - if (this._queueLen > mql && this._index > 0) { - mql = Math.min(this._index, mql) - this._index -= mql - this._queueLen -= mql - this._queue = this._queue.slice(mql) - } - - this._reading = false -} - -Entry.prototype._setProps = function () { - // props = extended->global->header->{} - var header = this._header - , extended = this._extended - , global = this._global - , props = this.props - - // first get the values from the normal header. - var fields = tar.fields - for (var f = 0; fields[f] !== null; f ++) { - var field = fields[f] - , val = header[field] - if (typeof val !== "undefined") props[field] = val - } - - // next, the global header for this file. - // numeric values, etc, will have already been parsed. - ;[global, extended].forEach(function (p) { - Object.keys(p).forEach(function (f) { - if (typeof p[f] !== "undefined") props[f] = p[f] - }) - }) - - // no nulls allowed in path or linkpath - ;["path", "linkpath"].forEach(function (p) { - if (props.hasOwnProperty(p)) { - props[p] = props[p].split("\0")[0] - } - }) - - - // set date fields to be a proper date - ;["mtime", "ctime", "atime"].forEach(function (p) { - if (props.hasOwnProperty(p)) { - props[p] = new Date(props[p] * 1000) - } - }) - - // set the type so that we know what kind of file to create - var type - switch (tar.types[props.type]) { - case "OldFile": - case "ContiguousFile": - type = "File" - break - - case "GNUDumpDir": - type = "Directory" - break - - case undefined: - type = "Unknown" - break - - case "Link": - case "SymbolicLink": - case "CharacterDevice": - case "BlockDevice": - case "Directory": - case "FIFO": - default: - type = tar.types[props.type] - } - - this.type = type - this.path = props.path - this.size = props.size - - // size is special, since it signals when the file needs to end. - this._remaining = props.size -} - -// the parser may not call write if _abort is true. -// useful for skipping data from some files quickly. -Entry.prototype.abort = function(){ - this._abort = true -} - -Entry.prototype.warn = fstream.warn -Entry.prototype.error = fstream.error diff --git a/node_modules/npm-lifecycle/node_modules/tar/lib/extended-header-writer.js b/node_modules/npm-lifecycle/node_modules/tar/lib/extended-header-writer.js deleted file mode 100644 index 1728c4583ae06..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/lib/extended-header-writer.js +++ /dev/null @@ -1,191 +0,0 @@ - -module.exports = ExtendedHeaderWriter - -var inherits = require("inherits") - , EntryWriter = require("./entry-writer.js") - -inherits(ExtendedHeaderWriter, EntryWriter) - -var tar = require("../tar.js") - , path = require("path") - , TarHeader = require("./header.js") - -// props is the props of the thing we need to write an -// extended header for. -// Don't be shy with it. Just encode everything. -function ExtendedHeaderWriter (props) { - // console.error(">> ehw ctor") - var me = this - - if (!(me instanceof ExtendedHeaderWriter)) { - return new ExtendedHeaderWriter(props) - } - - me.fields = props - - var p = - { path : ("PaxHeader" + path.join("/", props.path || "")) - .replace(/\\/g, "/").substr(0, 100) - , mode : props.mode || 0666 - , uid : props.uid || 0 - , gid : props.gid || 0 - , size : 0 // will be set later - , mtime : props.mtime || Date.now() / 1000 - , type : "x" - , linkpath : "" - , ustar : "ustar\0" - , ustarver : "00" - , uname : props.uname || "" - , gname : props.gname || "" - , devmaj : props.devmaj || 0 - , devmin : props.devmin || 0 - } - - - EntryWriter.call(me, p) - // console.error(">> ehw props", me.props) - me.props = p - - me._meta = true -} - -ExtendedHeaderWriter.prototype.end = function () { - // console.error(">> ehw end") - var me = this - - if (me._ended) return - me._ended = true - - me._encodeFields() - - if (me.props.size === 0) { - // nothing to write! - me._ready = true - me._stream.end() - return - } - - me._stream.write(TarHeader.encode(me.props)) - me.body.forEach(function (l) { - me._stream.write(l) - }) - me._ready = true - - // console.error(">> ehw _process calling end()", me.props) - this._stream.end() -} - -ExtendedHeaderWriter.prototype._encodeFields = function () { - // console.error(">> ehw _encodeFields") - this.body = [] - if (this.fields.prefix) { - this.fields.path = this.fields.prefix + "/" + this.fields.path - this.fields.prefix = "" - } - encodeFields(this.fields, "", this.body, this.fields.noProprietary) - var me = this - this.body.forEach(function (l) { - me.props.size += l.length - }) -} - -function encodeFields (fields, prefix, body, nop) { - // console.error(">> >> ehw encodeFields") - // "%d %s=%s\n", , , - // The length is a decimal number, and includes itself and the \n - // Numeric values are decimal strings. - - Object.keys(fields).forEach(function (k) { - var val = fields[k] - , numeric = tar.numeric[k] - - if (prefix) k = prefix + "." + k - - // already including NODETAR.type, don't need File=true also - if (k === fields.type && val === true) return - - switch (k) { - // don't include anything that's always handled just fine - // in the normal header, or only meaningful in the context - // of nodetar - case "mode": - case "cksum": - case "ustar": - case "ustarver": - case "prefix": - case "basename": - case "dirname": - case "needExtended": - case "block": - case "filter": - return - - case "rdev": - if (val === 0) return - break - - case "nlink": - case "dev": // Truly a hero among men, Creator of Star! - case "ino": // Speak his name with reverent awe! It is: - k = "SCHILY." + k - break - - default: break - } - - if (val && typeof val === "object" && - !Buffer.isBuffer(val)) encodeFields(val, k, body, nop) - else if (val === null || val === undefined) return - else body.push.apply(body, encodeField(k, val, nop)) - }) - - return body -} - -function encodeField (k, v, nop) { - // lowercase keys must be valid, otherwise prefix with - // "NODETAR." - if (k.charAt(0) === k.charAt(0).toLowerCase()) { - var m = k.split(".")[0] - if (!tar.knownExtended[m]) k = "NODETAR." + k - } - - // no proprietary - if (nop && k.charAt(0) !== k.charAt(0).toLowerCase()) { - return [] - } - - if (typeof val === "number") val = val.toString(10) - - var s = new Buffer(" " + k + "=" + v + "\n") - , digits = Math.floor(Math.log(s.length) / Math.log(10)) + 1 - - // console.error("1 s=%j digits=%j s.length=%d", s.toString(), digits, s.length) - - // if adding that many digits will make it go over that length, - // then add one to it. For example, if the string is: - // " foo=bar\n" - // then that's 9 characters. With the "9", that bumps the length - // up to 10. However, this is invalid: - // "10 foo=bar\n" - // but, since that's actually 11 characters, since 10 adds another - // character to the length, and the length includes the number - // itself. In that case, just bump it up again. - if (s.length + digits >= Math.pow(10, digits)) digits += 1 - // console.error("2 s=%j digits=%j s.length=%d", s.toString(), digits, s.length) - - var len = digits + s.length - // console.error("3 s=%j digits=%j s.length=%d len=%d", s.toString(), digits, s.length, len) - var lenBuf = new Buffer("" + len) - if (lenBuf.length + s.length !== len) { - throw new Error("Bad length calculation\n"+ - "len="+len+"\n"+ - "lenBuf="+JSON.stringify(lenBuf.toString())+"\n"+ - "lenBuf.length="+lenBuf.length+"\n"+ - "digits="+digits+"\n"+ - "s="+JSON.stringify(s.toString())+"\n"+ - "s.length="+s.length) - } - - return [lenBuf, s] -} diff --git a/node_modules/npm-lifecycle/node_modules/tar/lib/extended-header.js b/node_modules/npm-lifecycle/node_modules/tar/lib/extended-header.js deleted file mode 100644 index 74f432ceee5b2..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/lib/extended-header.js +++ /dev/null @@ -1,140 +0,0 @@ -// An Entry consisting of: -// -// "%d %s=%s\n", , , -// -// The length is a decimal number, and includes itself and the \n -// \0 does not terminate anything. Only the length terminates the string. -// Numeric values are decimal strings. - -module.exports = ExtendedHeader - -var Entry = require("./entry.js") - , inherits = require("inherits") - , tar = require("../tar.js") - , numeric = tar.numeric - , keyTrans = { "SCHILY.dev": "dev" - , "SCHILY.ino": "ino" - , "SCHILY.nlink": "nlink" } - -function ExtendedHeader () { - Entry.apply(this, arguments) - this.on("data", this._parse) - this.fields = {} - this._position = 0 - this._fieldPos = 0 - this._state = SIZE - this._sizeBuf = [] - this._keyBuf = [] - this._valBuf = [] - this._size = -1 - this._key = "" -} - -inherits(ExtendedHeader, Entry) -ExtendedHeader.prototype._parse = parse - -var s = 0 - , states = ExtendedHeader.states = {} - , SIZE = states.SIZE = s++ - , KEY = states.KEY = s++ - , VAL = states.VAL = s++ - , ERR = states.ERR = s++ - -Object.keys(states).forEach(function (s) { - states[states[s]] = states[s] -}) - -states[s] = null - -// char code values for comparison -var _0 = "0".charCodeAt(0) - , _9 = "9".charCodeAt(0) - , point = ".".charCodeAt(0) - , a = "a".charCodeAt(0) - , Z = "Z".charCodeAt(0) - , a = "a".charCodeAt(0) - , z = "z".charCodeAt(0) - , space = " ".charCodeAt(0) - , eq = "=".charCodeAt(0) - , cr = "\n".charCodeAt(0) - -function parse (c) { - if (this._state === ERR) return - - for ( var i = 0, l = c.length - ; i < l - ; this._position++, this._fieldPos++, i++) { - // console.error("top of loop, size="+this._size) - - var b = c[i] - - if (this._size >= 0 && this._fieldPos > this._size) { - error(this, "field exceeds length="+this._size) - return - } - - switch (this._state) { - case ERR: return - - case SIZE: - // console.error("parsing size, b=%d, rest=%j", b, c.slice(i).toString()) - if (b === space) { - this._state = KEY - // this._fieldPos = this._sizeBuf.length - this._size = parseInt(new Buffer(this._sizeBuf).toString(), 10) - this._sizeBuf.length = 0 - continue - } - if (b < _0 || b > _9) { - error(this, "expected [" + _0 + ".." + _9 + "], got " + b) - return - } - this._sizeBuf.push(b) - continue - - case KEY: - // can be any char except =, not > size. - if (b === eq) { - this._state = VAL - this._key = new Buffer(this._keyBuf).toString() - if (keyTrans[this._key]) this._key = keyTrans[this._key] - this._keyBuf.length = 0 - continue - } - this._keyBuf.push(b) - continue - - case VAL: - // field must end with cr - if (this._fieldPos === this._size - 1) { - // console.error("finished with "+this._key) - if (b !== cr) { - error(this, "expected \\n at end of field") - return - } - var val = new Buffer(this._valBuf).toString() - if (numeric[this._key]) { - val = parseFloat(val) - } - this.fields[this._key] = val - - this._valBuf.length = 0 - this._state = SIZE - this._size = -1 - this._fieldPos = -1 - continue - } - this._valBuf.push(b) - continue - } - } -} - -function error (me, msg) { - msg = "invalid header: " + msg - + "\nposition=" + me._position - + "\nfield position=" + me._fieldPos - - me.error(msg) - me.state = ERR -} diff --git a/node_modules/npm-lifecycle/node_modules/tar/lib/extract.js b/node_modules/npm-lifecycle/node_modules/tar/lib/extract.js deleted file mode 100644 index fe1bb976eb0ce..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/lib/extract.js +++ /dev/null @@ -1,94 +0,0 @@ -// give it a tarball and a path, and it'll dump the contents - -module.exports = Extract - -var tar = require("../tar.js") - , fstream = require("fstream") - , inherits = require("inherits") - , path = require("path") - -function Extract (opts) { - if (!(this instanceof Extract)) return new Extract(opts) - tar.Parse.apply(this) - - if (typeof opts !== "object") { - opts = { path: opts } - } - - // better to drop in cwd? seems more standard. - opts.path = opts.path || path.resolve("node-tar-extract") - opts.type = "Directory" - opts.Directory = true - - // similar to --strip or --strip-components - opts.strip = +opts.strip - if (!opts.strip || opts.strip <= 0) opts.strip = 0 - - this._fst = fstream.Writer(opts) - - this.pause() - var me = this - - // Hardlinks in tarballs are relative to the root - // of the tarball. So, they need to be resolved against - // the target directory in order to be created properly. - me.on("entry", function (entry) { - // if there's a "strip" argument, then strip off that many - // path components. - if (opts.strip) { - var p = entry.path.split("/").slice(opts.strip).join("/") - entry.path = entry.props.path = p - if (entry.linkpath) { - var lp = entry.linkpath.split("/").slice(opts.strip).join("/") - entry.linkpath = entry.props.linkpath = lp - } - } - if (entry.type === "Link") { - entry.linkpath = entry.props.linkpath = - path.join(opts.path, path.join("/", entry.props.linkpath)) - } - - if (entry.type === "SymbolicLink") { - var dn = path.dirname(entry.path) || "" - var linkpath = entry.props.linkpath - var target = path.resolve(opts.path, dn, linkpath) - if (target.indexOf(opts.path) !== 0) { - linkpath = path.join(opts.path, path.join("/", linkpath)) - } - entry.linkpath = entry.props.linkpath = linkpath - } - }) - - this._fst.on("ready", function () { - me.pipe(me._fst, { end: false }) - me.resume() - }) - - this._fst.on('error', function(err) { - me.emit('error', err) - }) - - this._fst.on('drain', function() { - me.emit('drain') - }) - - // this._fst.on("end", function () { - // console.error("\nEEEE Extract End", me._fst.path) - // }) - - this._fst.on("close", function () { - // console.error("\nEEEE Extract End", me._fst.path) - me.emit("finish") - me.emit("end") - me.emit("close") - }) -} - -inherits(Extract, tar.Parse) - -Extract.prototype._streamEnd = function () { - var me = this - if (!me._ended || me._entry) me.error("unexpected eof") - me._fst.end() - // my .end() is coming later. -} diff --git a/node_modules/npm-lifecycle/node_modules/tar/lib/global-header-writer.js b/node_modules/npm-lifecycle/node_modules/tar/lib/global-header-writer.js deleted file mode 100644 index 0bfc7b80aa7c6..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/lib/global-header-writer.js +++ /dev/null @@ -1,14 +0,0 @@ -module.exports = GlobalHeaderWriter - -var ExtendedHeaderWriter = require("./extended-header-writer.js") - , inherits = require("inherits") - -inherits(GlobalHeaderWriter, ExtendedHeaderWriter) - -function GlobalHeaderWriter (props) { - if (!(this instanceof GlobalHeaderWriter)) { - return new GlobalHeaderWriter(props) - } - ExtendedHeaderWriter.call(this, props) - this.props.type = "g" -} diff --git a/node_modules/npm-lifecycle/node_modules/tar/lib/header.js b/node_modules/npm-lifecycle/node_modules/tar/lib/header.js deleted file mode 100644 index 05b237c0c7b32..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/lib/header.js +++ /dev/null @@ -1,385 +0,0 @@ -// parse a 512-byte header block to a data object, or vice-versa -// If the data won't fit nicely in a simple header, then generate -// the appropriate extended header file, and return that. - -module.exports = TarHeader - -var tar = require("../tar.js") - , fields = tar.fields - , fieldOffs = tar.fieldOffs - , fieldEnds = tar.fieldEnds - , fieldSize = tar.fieldSize - , numeric = tar.numeric - , assert = require("assert").ok - , space = " ".charCodeAt(0) - , slash = "/".charCodeAt(0) - , bslash = process.platform === "win32" ? "\\".charCodeAt(0) : null - -function TarHeader (block) { - if (!(this instanceof TarHeader)) return new TarHeader(block) - if (block) this.decode(block) -} - -TarHeader.prototype = - { decode : decode - , encode: encode - , calcSum: calcSum - , checkSum: checkSum - } - -TarHeader.parseNumeric = parseNumeric -TarHeader.encode = encode -TarHeader.decode = decode - -// note that this will only do the normal ustar header, not any kind -// of extended posix header file. If something doesn't fit comfortably, -// then it will set obj.needExtended = true, and set the block to -// the closest approximation. -function encode (obj) { - if (!obj && !(this instanceof TarHeader)) throw new Error( - "encode must be called on a TarHeader, or supplied an object") - - obj = obj || this - var block = obj.block = new Buffer(512) - - // if the object has a "prefix", then that's actually an extension of - // the path field. - if (obj.prefix) { - // console.error("%% header encoding, got a prefix", obj.prefix) - obj.path = obj.prefix + "/" + obj.path - // console.error("%% header encoding, prefixed path", obj.path) - obj.prefix = "" - } - - obj.needExtended = false - - if (obj.mode) { - if (typeof obj.mode === "string") obj.mode = parseInt(obj.mode, 8) - obj.mode = obj.mode & 0777 - } - - for (var f = 0; fields[f] !== null; f ++) { - var field = fields[f] - , off = fieldOffs[f] - , end = fieldEnds[f] - , ret - - switch (field) { - case "cksum": - // special, done below, after all the others - break - - case "prefix": - // special, this is an extension of the "path" field. - // console.error("%% header encoding, skip prefix later") - break - - case "type": - // convert from long name to a single char. - var type = obj.type || "0" - if (type.length > 1) { - type = tar.types[obj.type] - if (!type) type = "0" - } - writeText(block, off, end, type) - break - - case "path": - // uses the "prefix" field if > 100 bytes, but <= 255 - var pathLen = Buffer.byteLength(obj.path) - , pathFSize = fieldSize[fields.path] - , prefFSize = fieldSize[fields.prefix] - - // paths between 100 and 255 should use the prefix field. - // longer than 255 - if (pathLen > pathFSize && - pathLen <= pathFSize + prefFSize) { - // need to find a slash somewhere in the middle so that - // path and prefix both fit in their respective fields - var searchStart = pathLen - 1 - pathFSize - , searchEnd = prefFSize - , found = false - , pathBuf = new Buffer(obj.path) - - for ( var s = searchStart - ; (s <= searchEnd) - ; s ++ ) { - if (pathBuf[s] === slash || pathBuf[s] === bslash) { - found = s - break - } - } - - if (found !== false) { - prefix = pathBuf.slice(0, found).toString("utf8") - path = pathBuf.slice(found + 1).toString("utf8") - - ret = writeText(block, off, end, path) - off = fieldOffs[fields.prefix] - end = fieldEnds[fields.prefix] - // console.error("%% header writing prefix", off, end, prefix) - ret = writeText(block, off, end, prefix) || ret - break - } - } - - // paths less than 100 chars don't need a prefix - // and paths longer than 255 need an extended header and will fail - // on old implementations no matter what we do here. - // Null out the prefix, and fallthrough to default. - // console.error("%% header writing no prefix") - var poff = fieldOffs[fields.prefix] - , pend = fieldEnds[fields.prefix] - writeText(block, poff, pend, "") - // fallthrough - - // all other fields are numeric or text - default: - ret = numeric[field] - ? writeNumeric(block, off, end, obj[field]) - : writeText(block, off, end, obj[field] || "") - break - } - obj.needExtended = obj.needExtended || ret - } - - var off = fieldOffs[fields.cksum] - , end = fieldEnds[fields.cksum] - - writeNumeric(block, off, end, calcSum.call(this, block)) - - return block -} - -// if it's a negative number, or greater than will fit, -// then use write256. -var MAXNUM = { 12: 077777777777 - , 11: 07777777777 - , 8 : 07777777 - , 7 : 0777777 } -function writeNumeric (block, off, end, num) { - var writeLen = end - off - , maxNum = MAXNUM[writeLen] || 0 - - num = num || 0 - // console.error(" numeric", num) - - if (num instanceof Date || - Object.prototype.toString.call(num) === "[object Date]") { - num = num.getTime() / 1000 - } - - if (num > maxNum || num < 0) { - write256(block, off, end, num) - // need an extended header if negative or too big. - return true - } - - // god, tar is so annoying - // if the string is small enough, you should put a space - // between the octal string and the \0, but if it doesn't - // fit, then don't. - var numStr = Math.floor(num).toString(8) - if (num < MAXNUM[writeLen - 1]) numStr += " " - - // pad with "0" chars - if (numStr.length < writeLen) { - numStr = (new Array(writeLen - numStr.length).join("0")) + numStr - } - - if (numStr.length !== writeLen - 1) { - throw new Error("invalid length: " + JSON.stringify(numStr) + "\n" + - "expected: "+writeLen) - } - block.write(numStr, off, writeLen, "utf8") - block[end - 1] = 0 -} - -function write256 (block, off, end, num) { - var buf = block.slice(off, end) - var positive = num >= 0 - buf[0] = positive ? 0x80 : 0xFF - - // get the number as a base-256 tuple - if (!positive) num *= -1 - var tuple = [] - do { - var n = num % 256 - tuple.push(n) - num = (num - n) / 256 - } while (num) - - var bytes = tuple.length - - var fill = buf.length - bytes - for (var i = 1; i < fill; i ++) { - buf[i] = positive ? 0 : 0xFF - } - - // tuple is a base256 number, with [0] as the *least* significant byte - // if it's negative, then we need to flip all the bits once we hit the - // first non-zero bit. The 2's-complement is (0x100 - n), and the 1's- - // complement is (0xFF - n). - var zero = true - for (i = bytes; i > 0; i --) { - var byte = tuple[bytes - i] - if (positive) buf[fill + i] = byte - else if (zero && byte === 0) buf[fill + i] = 0 - else if (zero) { - zero = false - buf[fill + i] = 0x100 - byte - } else buf[fill + i] = 0xFF - byte - } -} - -function writeText (block, off, end, str) { - // strings are written as utf8, then padded with \0 - var strLen = Buffer.byteLength(str) - , writeLen = Math.min(strLen, end - off) - // non-ascii fields need extended headers - // long fields get truncated - , needExtended = strLen !== str.length || strLen > writeLen - - // write the string, and null-pad - if (writeLen > 0) block.write(str, off, writeLen, "utf8") - for (var i = off + writeLen; i < end; i ++) block[i] = 0 - - return needExtended -} - -function calcSum (block) { - block = block || this.block - assert(Buffer.isBuffer(block) && block.length === 512) - - if (!block) throw new Error("Need block to checksum") - - // now figure out what it would be if the cksum was " " - var sum = 0 - , start = fieldOffs[fields.cksum] - , end = fieldEnds[fields.cksum] - - for (var i = 0; i < fieldOffs[fields.cksum]; i ++) { - sum += block[i] - } - - for (var i = start; i < end; i ++) { - sum += space - } - - for (var i = end; i < 512; i ++) { - sum += block[i] - } - - return sum -} - - -function checkSum (block) { - var sum = calcSum.call(this, block) - block = block || this.block - - var cksum = block.slice(fieldOffs[fields.cksum], fieldEnds[fields.cksum]) - cksum = parseNumeric(cksum) - - return cksum === sum -} - -function decode (block) { - block = block || this.block - assert(Buffer.isBuffer(block) && block.length === 512) - - this.block = block - this.cksumValid = this.checkSum() - - var prefix = null - - // slice off each field. - for (var f = 0; fields[f] !== null; f ++) { - var field = fields[f] - , val = block.slice(fieldOffs[f], fieldEnds[f]) - - switch (field) { - case "ustar": - // if not ustar, then everything after that is just padding. - if (val.toString() !== "ustar\0") { - this.ustar = false - return - } else { - // console.error("ustar:", val, val.toString()) - this.ustar = val.toString() - } - break - - // prefix is special, since it might signal the xstar header - case "prefix": - var atime = parseNumeric(val.slice(131, 131 + 12)) - , ctime = parseNumeric(val.slice(131 + 12, 131 + 12 + 12)) - if ((val[130] === 0 || val[130] === space) && - typeof atime === "number" && - typeof ctime === "number" && - val[131 + 12] === space && - val[131 + 12 + 12] === space) { - this.atime = atime - this.ctime = ctime - val = val.slice(0, 130) - } - prefix = val.toString("utf8").replace(/\0+$/, "") - // console.error("%% header reading prefix", prefix) - break - - // all other fields are null-padding text - // or a number. - default: - if (numeric[field]) { - this[field] = parseNumeric(val) - } else { - this[field] = val.toString("utf8").replace(/\0+$/, "") - } - break - } - } - - // if we got a prefix, then prepend it to the path. - if (prefix) { - this.path = prefix + "/" + this.path - // console.error("%% header got a prefix", this.path) - } -} - -function parse256 (buf) { - // first byte MUST be either 80 or FF - // 80 for positive, FF for 2's comp - var positive - if (buf[0] === 0x80) positive = true - else if (buf[0] === 0xFF) positive = false - else return null - - // build up a base-256 tuple from the least sig to the highest - var zero = false - , tuple = [] - for (var i = buf.length - 1; i > 0; i --) { - var byte = buf[i] - if (positive) tuple.push(byte) - else if (zero && byte === 0) tuple.push(0) - else if (zero) { - zero = false - tuple.push(0x100 - byte) - } else tuple.push(0xFF - byte) - } - - for (var sum = 0, i = 0, l = tuple.length; i < l; i ++) { - sum += tuple[i] * Math.pow(256, i) - } - - return positive ? sum : -1 * sum -} - -function parseNumeric (f) { - if (f[0] & 0x80) return parse256(f) - - var str = f.toString("utf8").split("\0")[0].trim() - , res = parseInt(str, 8) - - return isNaN(res) ? null : res -} - diff --git a/node_modules/npm-lifecycle/node_modules/tar/lib/pack.js b/node_modules/npm-lifecycle/node_modules/tar/lib/pack.js deleted file mode 100644 index 5a3bb95a121bd..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/lib/pack.js +++ /dev/null @@ -1,236 +0,0 @@ -// pipe in an fstream, and it'll make a tarball. -// key-value pair argument is global extended header props. - -module.exports = Pack - -var EntryWriter = require("./entry-writer.js") - , Stream = require("stream").Stream - , path = require("path") - , inherits = require("inherits") - , GlobalHeaderWriter = require("./global-header-writer.js") - , collect = require("fstream").collect - , eof = new Buffer(512) - -for (var i = 0; i < 512; i ++) eof[i] = 0 - -inherits(Pack, Stream) - -function Pack (props) { - // console.error("-- p ctor") - var me = this - if (!(me instanceof Pack)) return new Pack(props) - - if (props) me._noProprietary = props.noProprietary - else me._noProprietary = false - - me._global = props - - me.readable = true - me.writable = true - me._buffer = [] - // console.error("-- -- set current to null in ctor") - me._currentEntry = null - me._processing = false - - me._pipeRoot = null - me.on("pipe", function (src) { - if (src.root === me._pipeRoot) return - me._pipeRoot = src - src.on("end", function () { - me._pipeRoot = null - }) - me.add(src) - }) -} - -Pack.prototype.addGlobal = function (props) { - // console.error("-- p addGlobal") - if (this._didGlobal) return - this._didGlobal = true - - var me = this - GlobalHeaderWriter(props) - .on("data", function (c) { - me.emit("data", c) - }) - .end() -} - -Pack.prototype.add = function (stream) { - if (this._global && !this._didGlobal) this.addGlobal(this._global) - - if (this._ended) return this.emit("error", new Error("add after end")) - - collect(stream) - this._buffer.push(stream) - this._process() - this._needDrain = this._buffer.length > 0 - return !this._needDrain -} - -Pack.prototype.pause = function () { - this._paused = true - if (this._currentEntry) this._currentEntry.pause() - this.emit("pause") -} - -Pack.prototype.resume = function () { - this._paused = false - if (this._currentEntry) this._currentEntry.resume() - this.emit("resume") - this._process() -} - -Pack.prototype.end = function () { - this._ended = true - this._buffer.push(eof) - this._process() -} - -Pack.prototype._process = function () { - var me = this - if (me._paused || me._processing) { - return - } - - var entry = me._buffer.shift() - - if (!entry) { - if (me._needDrain) { - me.emit("drain") - } - return - } - - if (entry.ready === false) { - // console.error("-- entry is not ready", entry) - me._buffer.unshift(entry) - entry.on("ready", function () { - // console.error("-- -- ready!", entry) - me._process() - }) - return - } - - me._processing = true - - if (entry === eof) { - // need 2 ending null blocks. - me.emit("data", eof) - me.emit("data", eof) - me.emit("end") - me.emit("close") - return - } - - // Change the path to be relative to the root dir that was - // added to the tarball. - // - // XXX This should be more like how -C works, so you can - // explicitly set a root dir, and also explicitly set a pathname - // in the tarball to use. That way we can skip a lot of extra - // work when resolving symlinks for bundled dependencies in npm. - - var root = path.dirname((entry.root || entry).path); - if (me._global && me._global.fromBase && entry.root && entry.root.path) { - // user set 'fromBase: true' indicating tar root should be directory itself - root = entry.root.path; - } - - var wprops = {} - - Object.keys(entry.props || {}).forEach(function (k) { - wprops[k] = entry.props[k] - }) - - if (me._noProprietary) wprops.noProprietary = true - - wprops.path = path.relative(root, entry.path || '') - - // actually not a matter of opinion or taste. - if (process.platform === "win32") { - wprops.path = wprops.path.replace(/\\/g, "/") - } - - if (!wprops.type) - wprops.type = 'Directory' - - switch (wprops.type) { - // sockets not supported - case "Socket": - return - - case "Directory": - wprops.path += "/" - wprops.size = 0 - break - - case "Link": - var lp = path.resolve(path.dirname(entry.path), entry.linkpath) - wprops.linkpath = path.relative(root, lp) || "." - wprops.size = 0 - break - - case "SymbolicLink": - var lp = path.resolve(path.dirname(entry.path), entry.linkpath) - wprops.linkpath = path.relative(path.dirname(entry.path), lp) || "." - wprops.size = 0 - break - } - - // console.error("-- new writer", wprops) - // if (!wprops.type) { - // // console.error("-- no type?", entry.constructor.name, entry) - // } - - // console.error("-- -- set current to new writer", wprops.path) - var writer = me._currentEntry = EntryWriter(wprops) - - writer.parent = me - - // writer.on("end", function () { - // // console.error("-- -- writer end", writer.path) - // }) - - writer.on("data", function (c) { - me.emit("data", c) - }) - - writer.on("header", function () { - Buffer.prototype.toJSON = function () { - return this.toString().split(/\0/).join(".") - } - // console.error("-- -- writer header %j", writer.props) - if (writer.props.size === 0) nextEntry() - }) - writer.on("close", nextEntry) - - var ended = false - function nextEntry () { - if (ended) return - ended = true - - // console.error("-- -- writer close", writer.path) - // console.error("-- -- set current to null", wprops.path) - me._currentEntry = null - me._processing = false - me._process() - } - - writer.on("error", function (er) { - // console.error("-- -- writer error", writer.path) - me.emit("error", er) - }) - - // if it's the root, then there's no need to add its entries, - // or data, since they'll be added directly. - if (entry === me._pipeRoot) { - // console.error("-- is the root, don't auto-add") - writer.add = null - } - - entry.pipe(writer) -} - -Pack.prototype.destroy = function () {} -Pack.prototype.write = function () {} diff --git a/node_modules/npm-lifecycle/node_modules/tar/lib/parse.js b/node_modules/npm-lifecycle/node_modules/tar/lib/parse.js deleted file mode 100644 index 1c66ebdaf0c15..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/lib/parse.js +++ /dev/null @@ -1,281 +0,0 @@ - -// A writable stream. -// It emits "entry" events, which provide a readable stream that has -// header info attached. - -module.exports = Parse.create = Parse - -var stream = require("stream") - , Stream = stream.Stream - , BlockStream = require("block-stream") - , tar = require("../tar.js") - , TarHeader = require("./header.js") - , Entry = require("./entry.js") - , BufferEntry = require("./buffer-entry.js") - , ExtendedHeader = require("./extended-header.js") - , assert = require("assert").ok - , inherits = require("inherits") - , fstream = require("fstream") - -// reading a tar is a lot like reading a directory -// However, we're actually not going to run the ctor, -// since it does a stat and various other stuff. -// This inheritance gives us the pause/resume/pipe -// behavior that is desired. -inherits(Parse, fstream.Reader) - -function Parse () { - var me = this - if (!(me instanceof Parse)) return new Parse() - - // doesn't apply fstream.Reader ctor? - // no, becasue we don't want to stat/etc, we just - // want to get the entry/add logic from .pipe() - Stream.apply(me) - - me.writable = true - me.readable = true - me._stream = new BlockStream(512) - me.position = 0 - me._ended = false - me._hardLinks = {} - - me._stream.on("error", function (e) { - me.emit("error", e) - }) - - me._stream.on("data", function (c) { - me._process(c) - }) - - me._stream.on("end", function () { - me._streamEnd() - }) - - me._stream.on("drain", function () { - me.emit("drain") - }) -} - -// overridden in Extract class, since it needs to -// wait for its DirWriter part to finish before -// emitting "end" -Parse.prototype._streamEnd = function () { - var me = this - if (!me._ended || me._entry) me.error("unexpected eof") - me.emit("end") -} - -// a tar reader is actually a filter, not just a readable stream. -// So, you should pipe a tarball stream into it, and it needs these -// write/end methods to do that. -Parse.prototype.write = function (c) { - if (this._ended) { - // gnutar puts a LOT of nulls at the end. - // you can keep writing these things forever. - // Just ignore them. - for (var i = 0, l = c.length; i > l; i ++) { - if (c[i] !== 0) return this.error("write() after end()") - } - return - } - return this._stream.write(c) -} - -Parse.prototype.end = function (c) { - this._ended = true - return this._stream.end(c) -} - -// don't need to do anything, since we're just -// proxying the data up from the _stream. -// Just need to override the parent's "Not Implemented" -// error-thrower. -Parse.prototype._read = function () {} - -Parse.prototype._process = function (c) { - assert(c && c.length === 512, "block size should be 512") - - // one of three cases. - // 1. A new header - // 2. A part of a file/extended header - // 3. One of two or more EOF null blocks - - if (this._entry) { - var entry = this._entry - if(!entry._abort) entry.write(c) - else { - entry._remaining -= c.length - if(entry._remaining < 0) entry._remaining = 0 - } - if (entry._remaining === 0) { - entry.end() - this._entry = null - } - } else { - // either zeroes or a header - var zero = true - for (var i = 0; i < 512 && zero; i ++) { - zero = c[i] === 0 - } - - // eof is *at least* 2 blocks of nulls, and then the end of the - // file. you can put blocks of nulls between entries anywhere, - // so appending one tarball to another is technically valid. - // ending without the eof null blocks is not allowed, however. - if (zero) { - if (this._eofStarted) - this._ended = true - this._eofStarted = true - } else { - this._eofStarted = false - this._startEntry(c) - } - } - - this.position += 512 -} - -// take a header chunk, start the right kind of entry. -Parse.prototype._startEntry = function (c) { - var header = new TarHeader(c) - , self = this - , entry - , ev - , EntryType - , onend - , meta = false - - if (null === header.size || !header.cksumValid) { - var e = new Error("invalid tar file") - e.header = header - e.tar_file_offset = this.position - e.tar_block = this.position / 512 - return this.emit("error", e) - } - - switch (tar.types[header.type]) { - case "File": - case "OldFile": - case "Link": - case "SymbolicLink": - case "CharacterDevice": - case "BlockDevice": - case "Directory": - case "FIFO": - case "ContiguousFile": - case "GNUDumpDir": - // start a file. - // pass in any extended headers - // These ones consumers are typically most interested in. - EntryType = Entry - ev = "entry" - break - - case "GlobalExtendedHeader": - // extended headers that apply to the rest of the tarball - EntryType = ExtendedHeader - onend = function () { - self._global = self._global || {} - Object.keys(entry.fields).forEach(function (k) { - self._global[k] = entry.fields[k] - }) - } - ev = "globalExtendedHeader" - meta = true - break - - case "ExtendedHeader": - case "OldExtendedHeader": - // extended headers that apply to the next entry - EntryType = ExtendedHeader - onend = function () { - self._extended = entry.fields - } - ev = "extendedHeader" - meta = true - break - - case "NextFileHasLongLinkpath": - // set linkpath= in extended header - EntryType = BufferEntry - onend = function () { - self._extended = self._extended || {} - self._extended.linkpath = entry.body - } - ev = "longLinkpath" - meta = true - break - - case "NextFileHasLongPath": - case "OldGnuLongPath": - // set path= in file-extended header - EntryType = BufferEntry - onend = function () { - self._extended = self._extended || {} - self._extended.path = entry.body - } - ev = "longPath" - meta = true - break - - default: - // all the rest we skip, but still set the _entry - // member, so that we can skip over their data appropriately. - // emit an event to say that this is an ignored entry type? - EntryType = Entry - ev = "ignoredEntry" - break - } - - var global, extended - if (meta) { - global = extended = null - } else { - var global = this._global - var extended = this._extended - - // extendedHeader only applies to one entry, so once we start - // an entry, it's over. - this._extended = null - } - entry = new EntryType(header, extended, global) - entry.meta = meta - - // only proxy data events of normal files. - if (!meta) { - entry.on("data", function (c) { - me.emit("data", c) - }) - } - - if (onend) entry.on("end", onend) - - this._entry = entry - - if (entry.type === "Link") { - this._hardLinks[entry.path] = entry - } - - var me = this - - entry.on("pause", function () { - me.pause() - }) - - entry.on("resume", function () { - me.resume() - }) - - if (this.listeners("*").length) { - this.emit("*", ev, entry) - } - - this.emit(ev, entry) - - // Zero-byte entry. End immediately. - if (entry.props.size === 0) { - entry.end() - this._entry = null - } -} diff --git a/node_modules/npm-lifecycle/node_modules/tar/package.json b/node_modules/npm-lifecycle/node_modules/tar/package.json deleted file mode 100644 index 4a4dacaba5a5d..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/package.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "_from": "tar@^2.0.0", - "_id": "tar@2.2.2", - "_inBundle": false, - "_integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "_location": "/npm-lifecycle/tar", - "_phantomChildren": {}, - "_requested": { - "type": "range", - "registry": true, - "raw": "tar@^2.0.0", - "name": "tar", - "escapedName": "tar", - "rawSpec": "^2.0.0", - "saveSpec": null, - "fetchSpec": "^2.0.0" - }, - "_requiredBy": [ - "/npm-lifecycle/node-gyp" - ], - "_resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "_shasum": "0ca8848562c7299b8b446ff6a4d60cdbb23edc40", - "_spec": "tar@^2.0.0", - "_where": "/home/hugh/Development/github.com/npm/cli/node_modules/npm-lifecycle/node_modules/node-gyp", - "author": { - "name": "Isaac Z. Schlueter", - "email": "i@izs.me", - "url": "http://blog.izs.me/" - }, - "bugs": { - "url": "https://github.com/isaacs/node-tar/issues" - }, - "bundleDependencies": false, - "dependencies": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - }, - "deprecated": false, - "description": "tar for node", - "devDependencies": { - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "rimraf": "1.x", - "tap": "0.x" - }, - "homepage": "https://github.com/isaacs/node-tar#readme", - "license": "ISC", - "main": "tar.js", - "name": "tar", - "repository": { - "type": "git", - "url": "git://github.com/isaacs/node-tar.git" - }, - "scripts": { - "test": "tap test/*.js" - }, - "version": "2.2.2" -} diff --git a/node_modules/npm-lifecycle/node_modules/tar/tar.js b/node_modules/npm-lifecycle/node_modules/tar/tar.js deleted file mode 100644 index a81298b9a0b12..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/tar.js +++ /dev/null @@ -1,173 +0,0 @@ -// field paths that every tar file must have. -// header is padded to 512 bytes. -var f = 0 - , fields = {} - , path = fields.path = f++ - , mode = fields.mode = f++ - , uid = fields.uid = f++ - , gid = fields.gid = f++ - , size = fields.size = f++ - , mtime = fields.mtime = f++ - , cksum = fields.cksum = f++ - , type = fields.type = f++ - , linkpath = fields.linkpath = f++ - , headerSize = 512 - , blockSize = 512 - , fieldSize = [] - -fieldSize[path] = 100 -fieldSize[mode] = 8 -fieldSize[uid] = 8 -fieldSize[gid] = 8 -fieldSize[size] = 12 -fieldSize[mtime] = 12 -fieldSize[cksum] = 8 -fieldSize[type] = 1 -fieldSize[linkpath] = 100 - -// "ustar\0" may introduce another bunch of headers. -// these are optional, and will be nulled out if not present. - -var ustar = fields.ustar = f++ - , ustarver = fields.ustarver = f++ - , uname = fields.uname = f++ - , gname = fields.gname = f++ - , devmaj = fields.devmaj = f++ - , devmin = fields.devmin = f++ - , prefix = fields.prefix = f++ - , fill = fields.fill = f++ - -// terminate fields. -fields[f] = null - -fieldSize[ustar] = 6 -fieldSize[ustarver] = 2 -fieldSize[uname] = 32 -fieldSize[gname] = 32 -fieldSize[devmaj] = 8 -fieldSize[devmin] = 8 -fieldSize[prefix] = 155 -fieldSize[fill] = 12 - -// nb: prefix field may in fact be 130 bytes of prefix, -// a null char, 12 bytes for atime, 12 bytes for ctime. -// -// To recognize this format: -// 1. prefix[130] === ' ' or '\0' -// 2. atime and ctime are octal numeric values -// 3. atime and ctime have ' ' in their last byte - -var fieldEnds = {} - , fieldOffs = {} - , fe = 0 -for (var i = 0; i < f; i ++) { - fieldOffs[i] = fe - fieldEnds[i] = (fe += fieldSize[i]) -} - -// build a translation table of field paths. -Object.keys(fields).forEach(function (f) { - if (fields[f] !== null) fields[fields[f]] = f -}) - -// different values of the 'type' field -// paths match the values of Stats.isX() functions, where appropriate -var types = - { 0: "File" - , "\0": "OldFile" // like 0 - , "": "OldFile" - , 1: "Link" - , 2: "SymbolicLink" - , 3: "CharacterDevice" - , 4: "BlockDevice" - , 5: "Directory" - , 6: "FIFO" - , 7: "ContiguousFile" // like 0 - // posix headers - , g: "GlobalExtendedHeader" // k=v for the rest of the archive - , x: "ExtendedHeader" // k=v for the next file - // vendor-specific stuff - , A: "SolarisACL" // skip - , D: "GNUDumpDir" // like 5, but with data, which should be skipped - , I: "Inode" // metadata only, skip - , K: "NextFileHasLongLinkpath" // data = link path of next file - , L: "NextFileHasLongPath" // data = path of next file - , M: "ContinuationFile" // skip - , N: "OldGnuLongPath" // like L - , S: "SparseFile" // skip - , V: "TapeVolumeHeader" // skip - , X: "OldExtendedHeader" // like x - } - -Object.keys(types).forEach(function (t) { - types[types[t]] = types[types[t]] || t -}) - -// values for the mode field -var modes = - { suid: 04000 // set uid on extraction - , sgid: 02000 // set gid on extraction - , svtx: 01000 // set restricted deletion flag on dirs on extraction - , uread: 0400 - , uwrite: 0200 - , uexec: 0100 - , gread: 040 - , gwrite: 020 - , gexec: 010 - , oread: 4 - , owrite: 2 - , oexec: 1 - , all: 07777 - } - -var numeric = - { mode: true - , uid: true - , gid: true - , size: true - , mtime: true - , devmaj: true - , devmin: true - , cksum: true - , atime: true - , ctime: true - , dev: true - , ino: true - , nlink: true - } - -Object.keys(modes).forEach(function (t) { - modes[modes[t]] = modes[modes[t]] || t -}) - -var knownExtended = - { atime: true - , charset: true - , comment: true - , ctime: true - , gid: true - , gname: true - , linkpath: true - , mtime: true - , path: true - , realtime: true - , security: true - , size: true - , uid: true - , uname: true } - - -exports.fields = fields -exports.fieldSize = fieldSize -exports.fieldOffs = fieldOffs -exports.fieldEnds = fieldEnds -exports.types = types -exports.modes = modes -exports.numeric = numeric -exports.headerSize = headerSize -exports.blockSize = blockSize -exports.knownExtended = knownExtended - -exports.Pack = require("./lib/pack.js") -exports.Parse = require("./lib/parse.js") -exports.Extract = require("./lib/extract.js") diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/00-setup-fixtures.js b/node_modules/npm-lifecycle/node_modules/tar/test/00-setup-fixtures.js deleted file mode 100644 index 1524ff7af0570..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/00-setup-fixtures.js +++ /dev/null @@ -1,53 +0,0 @@ -// the fixtures have some weird stuff that is painful -// to include directly in the repo for various reasons. -// -// So, unpack the fixtures with the system tar first. -// -// This means, of course, that it'll only work if you -// already have a tar implementation, and some of them -// will not properly unpack the fixtures anyway. -// -// But, since usually those tests will fail on Windows -// and other systems with less capable filesystems anyway, -// at least this way we don't cause inconveniences by -// merely cloning the repo or installing the package. - -var tap = require("tap") -, child_process = require("child_process") -, rimraf = require("rimraf") -, test = tap.test -, path = require("path") - -test("clean fixtures", function (t) { - rimraf(path.resolve(__dirname, "fixtures"), function (er) { - t.ifError(er, "rimraf ./fixtures/") - t.end() - }) -}) - -test("clean tmp", function (t) { - rimraf(path.resolve(__dirname, "tmp"), function (er) { - t.ifError(er, "rimraf ./tmp/") - t.end() - }) -}) - -test("extract fixtures", function (t) { - var c = child_process.spawn("tar" - ,["xzvf", "fixtures.tgz"] - ,{ cwd: __dirname }) - - c.stdout.on("data", errwrite) - c.stderr.on("data", errwrite) - function errwrite (chunk) { - process.stderr.write(chunk) - } - - c.on("exit", function (code) { - t.equal(code, 0, "extract fixtures should exit with 0") - if (code) { - t.comment("Note, all tests from here on out will fail because of this.") - } - t.end() - }) -}) diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/cb-never-called-1.0.1.tgz b/node_modules/npm-lifecycle/node_modules/tar/test/cb-never-called-1.0.1.tgz deleted file mode 100644 index 9e7014d85abe48a54cb6b4e1ec032df9a2073034..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4096 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 diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/dir-normalization.js b/node_modules/npm-lifecycle/node_modules/tar/test/dir-normalization.js deleted file mode 100644 index 9719c42f35400..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/dir-normalization.js +++ /dev/null @@ -1,177 +0,0 @@ -// Set the umask, so that it works the same everywhere. -process.umask(parseInt('22', 8)) - -var fs = require('fs') -var path = require('path') - -var fstream = require('fstream') -var test = require('tap').test - -var tar = require('../tar.js') -var file = path.resolve(__dirname, 'dir-normalization.tar') -var target = path.resolve(__dirname, 'tmp/dir-normalization-test') -var ee = 0 - -var expectEntries = [ - { path: 'fixtures/', - mode: '755', - type: '5', - linkpath: '' - }, - { path: 'fixtures/a/', - mode: '755', - type: '5', - linkpath: '' - }, - { path: 'fixtures/the-chumbler', - mode: '755', - type: '2', - linkpath: path.resolve(target, 'a/b/c/d/the-chumbler'), - }, - { path: 'fixtures/a/b/', - mode: '755', - type: '5', - linkpath: '' - }, - { path: 'fixtures/a/x', - mode: '644', - type: '0', - linkpath: '' - }, - { path: 'fixtures/a/b/c/', - mode: '755', - type: '5', - linkpath: '' - }, - { path: 'fixtures/a/b/c/y', - mode: '755', - type: '2', - linkpath: '../../x', - } -] - -var ef = 0 -var expectFiles = [ - { path: '', - mode: '40755', - type: 'Directory', - depth: 0, - linkpath: undefined - }, - { path: '/fixtures', - mode: '40755', - type: 'Directory', - depth: 1, - linkpath: undefined - }, - { path: '/fixtures/a', - mode: '40755', - type: 'Directory', - depth: 2, - linkpath: undefined - }, - { path: '/fixtures/a/b', - mode: '40755', - type: 'Directory', - depth: 3, - linkpath: undefined - }, - { path: '/fixtures/a/b/c', - mode: '40755', - type: 'Directory', - depth: 4, - linkpath: undefined - }, - { path: '/fixtures/a/b/c/y', - mode: '120755', - type: 'SymbolicLink', - depth: 5, - linkpath: '../../x' - }, - { path: '/fixtures/a/x', - mode: '100644', - type: 'File', - depth: 3, - linkpath: undefined - }, - { path: '/fixtures/the-chumbler', - mode: '120755', - type: 'SymbolicLink', - depth: 2, - linkpath: path.resolve(target, 'a/b/c/d/the-chumbler') - } -] - -test('preclean', function (t) { - require('rimraf').sync(path.join(__dirname, '/tmp/dir-normalization-test')) - t.pass('cleaned!') - t.end() -}) - -test('extract test', function (t) { - var extract = tar.Extract(target) - var inp = fs.createReadStream(file) - - inp.pipe(extract) - - extract.on('end', function () { - t.equal(ee, expectEntries.length, 'should see ' + expectEntries.length + ' entries') - - // should get no more entries after end - extract.removeAllListeners('entry') - extract.on('entry', function (e) { - t.fail('Should not get entries after end!') - }) - - next() - }) - - extract.on('entry', function (entry) { - var mode = entry.props.mode & (~parseInt('22', 8)) - var found = { - path: entry.path, - mode: mode.toString(8), - type: entry.props.type, - linkpath: entry.props.linkpath, - } - - var wanted = expectEntries[ee++] - t.equivalent(found, wanted, 'tar entry ' + ee + ' ' + (wanted && wanted.path)) - }) - - function next () { - var r = fstream.Reader({ - path: target, - type: 'Directory', - sort: 'alpha' - }) - - r.on('ready', function () { - foundEntry(r) - }) - - r.on('end', finish) - - function foundEntry (entry) { - var p = entry.path.substr(target.length) - var mode = entry.props.mode & (~parseInt('22', 8)) - var found = { - path: p, - mode: mode.toString(8), - type: entry.props.type, - depth: entry.props.depth, - linkpath: entry.props.linkpath - } - - var wanted = expectFiles[ef++] - t.equivalent(found, wanted, 'unpacked file ' + ef + ' ' + (wanted && wanted.path)) - - entry.on('entry', foundEntry) - } - - function finish () { - t.equal(ef, expectFiles.length, 'should have ' + ef + ' items') - t.end() - } - } -}) diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/dir-normalization.tar b/node_modules/npm-lifecycle/node_modules/tar/test/dir-normalization.tar deleted file mode 100644 index 3c4845356cecb20939b415830a5fa9717fb91341..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 4608 zcmeHJS&qUm4DC^J0f_Cy&3Qtn6-dKR7m2w&PN6j7t4Me>Xkt~0n?~MVp55+r8K=G- zY^5gv5SUE`972tqikXFmnFvea&It?*4!@B>h$+50` z-pt$IGqpQZU1J+8}SF0 zCIB7{5IUmDkd5|W8~bGygDd>M_5W1rH{-sT+lc?%|G~}t525gXDWB^4;D59iEk}ZX z?bE#9F#qrUKRCf3v;xZQ7XGjNZ*)4qOZ=A~MLp$ne2HwSHsX(c~XH?({YrM8z diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/error-on-broken.js b/node_modules/npm-lifecycle/node_modules/tar/test/error-on-broken.js deleted file mode 100644 index e484920fd9625..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/error-on-broken.js +++ /dev/null @@ -1,33 +0,0 @@ -var fs = require('fs') -var path = require('path') -var zlib = require('zlib') - -var tap = require('tap') - -var tar = require('../tar.js') - -var file = path.join(__dirname, 'cb-never-called-1.0.1.tgz') -var target = path.join(__dirname, 'tmp/extract-test') - -tap.test('preclean', function (t) { - require('rimraf').sync(__dirname + '/tmp/extract-test') - t.pass('cleaned!') - t.end() -}) - -tap.test('extract test', function (t) { - var extract = tar.Extract(target) - var inp = fs.createReadStream(file) - - inp.pipe(zlib.createGunzip()).pipe(extract) - - extract.on('error', function (er) { - t.equal(er.message, 'unexpected eof', 'error noticed') - t.end() - }) - - extract.on('end', function () { - t.fail('shouldn\'t reach this point due to errors') - t.end() - }) -}) diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/extract-move.js b/node_modules/npm-lifecycle/node_modules/tar/test/extract-move.js deleted file mode 100644 index 45400cd9bb818..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/extract-move.js +++ /dev/null @@ -1,132 +0,0 @@ -// Set the umask, so that it works the same everywhere. -process.umask(parseInt('22', 8)) - -var tap = require("tap") - , tar = require("../tar.js") - , fs = require("fs") - , gfs = require("graceful-fs") - , path = require("path") - , file = path.resolve(__dirname, "fixtures/dir.tar") - , target = path.resolve(__dirname, "tmp/extract-test") - , index = 0 - , fstream = require("fstream") - , rimraf = require("rimraf") - , mkdirp = require("mkdirp") - - , ee = 0 - , expectEntries = [ - { - "path" : "dir/", - "mode" : "750", - "type" : "5", - "depth" : undefined, - "size" : 0, - "linkpath" : "", - "nlink" : undefined, - "dev" : undefined, - "ino" : undefined - }, - { - "path" : "dir/sub/", - "mode" : "750", - "type" : "5", - "depth" : undefined, - "size" : 0, - "linkpath" : "", - "nlink" : undefined, - "dev" : undefined, - "ino" : undefined - } ] - -function slow (fs, method, t1, t2) { - var orig = fs[method] - if (!orig) return null - fs[method] = function () { - var args = [].slice.call(arguments) - console.error("slow", method, args[0]) - var cb = args.pop() - - setTimeout(function () { - orig.apply(fs, args.concat(function(er, data) { - setTimeout(function() { - cb(er, data) - }, t2) - })) - }, t1) - } -} - -// Make sure we get the graceful-fs that fstream is using. -var gfs2 -try { - gfs2 = require("fstream/node_modules/graceful-fs") -} catch (er) {} - -var slowMethods = ["chown", "chmod", "utimes", "lutimes"] -slowMethods.forEach(function (method) { - var t1 = 500 - var t2 = 0 - slow(fs, method, t1, t2) - slow(gfs, method, t1, t2) - if (gfs2) { - slow(gfs2, method, t1, t2) - } -}) - - - -// The extract class basically just pipes the input -// to a Reader, and then to a fstream.DirWriter - -// So, this is as much a test of fstream.Reader and fstream.Writer -// as it is of tar.Extract, but it sort of makes sense. - -tap.test("preclean", function (t) { - rimraf.sync(target) - /mkdirp.sync(target) - t.pass("cleaned!") - t.end() -}) - -tap.test("extract test", function (t) { - var extract = tar.Extract(target) - var inp = fs.createReadStream(file) - - // give it a weird buffer size to try to break in odd places - inp.bufferSize = 1234 - - inp.pipe(extract) - - extract.on("end", function () { - rimraf.sync(target) - - t.equal(ee, expectEntries.length, "should see "+ee+" entries") - - // should get no more entries after end - extract.removeAllListeners("entry") - extract.on("entry", function (e) { - t.fail("Should not get entries after end!") - }) - - t.end() - }) - - - extract.on("entry", function (entry) { - var found = - { path: entry.path - , mode: entry.props.mode.toString(8) - , type: entry.props.type - , depth: entry.props.depth - , size: entry.props.size - , linkpath: entry.props.linkpath - , nlink: entry.props.nlink - , dev: entry.props.dev - , ino: entry.props.ino - } - - var wanted = expectEntries[ee ++] - - t.equivalent(found, wanted, "tar entry " + ee + " " + wanted.path) - }) -}) diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/extract.js b/node_modules/npm-lifecycle/node_modules/tar/test/extract.js deleted file mode 100644 index eca4e7cc962db..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/extract.js +++ /dev/null @@ -1,367 +0,0 @@ -// Set the umask, so that it works the same everywhere. -process.umask(parseInt('22', 8)) - -var tap = require("tap") - , tar = require("../tar.js") - , fs = require("fs") - , path = require("path") - , file = path.resolve(__dirname, "fixtures/c.tar") - , target = path.resolve(__dirname, "tmp/extract-test") - , index = 0 - , fstream = require("fstream") - - , ee = 0 - , expectEntries = -[ { path: 'c.txt', - mode: '644', - type: '0', - depth: undefined, - size: 513, - linkpath: '', - nlink: undefined, - dev: undefined, - ino: undefined }, - { path: 'cc.txt', - mode: '644', - type: '0', - depth: undefined, - size: 513, - linkpath: '', - nlink: undefined, - dev: undefined, - ino: undefined }, - { path: 'r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: '644', - type: '0', - depth: undefined, - size: 100, - linkpath: '', - nlink: undefined, - dev: undefined, - ino: undefined }, - { path: 'Ω.txt', - mode: '644', - type: '0', - depth: undefined, - size: 2, - linkpath: '', - nlink: undefined, - dev: undefined, - ino: undefined }, - { path: 'Ω.txt', - mode: '644', - type: '0', - depth: undefined, - size: 2, - linkpath: '', - nlink: 1, - dev: 234881026, - ino: 51693379 }, - { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: '644', - type: '0', - depth: undefined, - size: 200, - linkpath: '', - nlink: 1, - dev: 234881026, - ino: 51681874 }, - { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: '644', - type: '0', - depth: undefined, - size: 201, - linkpath: '', - nlink: undefined, - dev: undefined, - ino: undefined }, - { path: '200LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL', - mode: '777', - type: '2', - depth: undefined, - size: 0, - linkpath: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - nlink: undefined, - dev: undefined, - ino: undefined }, - { path: '200-hard', - mode: '644', - type: '0', - depth: undefined, - size: 200, - linkpath: '', - nlink: 2, - dev: 234881026, - ino: 51681874 }, - { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: '644', - type: '1', - depth: undefined, - size: 0, - linkpath: path.resolve(target, '200-hard'), - nlink: 2, - dev: 234881026, - ino: 51681874 } ] - - , ef = 0 - , expectFiles = -[ { path: '', - mode: '40755', - type: 'Directory', - depth: 0, - linkpath: undefined }, - { path: '/200-hard', - mode: '100644', - type: 'File', - depth: 1, - size: 200, - linkpath: undefined, - nlink: 2 }, - { path: '/200LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL', - mode: '120777', - type: 'SymbolicLink', - depth: 1, - size: 200, - linkpath: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - nlink: 1 }, - { path: '/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: '100644', - type: 'Link', - depth: 1, - size: 200, - linkpath: path.join(target, '200-hard'), - nlink: 2 }, - { path: '/c.txt', - mode: '100644', - type: 'File', - depth: 1, - size: 513, - linkpath: undefined, - nlink: 1 }, - { path: '/cc.txt', - mode: '100644', - type: 'File', - depth: 1, - size: 513, - linkpath: undefined, - nlink: 1 }, - { path: '/r', - mode: '40755', - type: 'Directory', - depth: 1, - linkpath: undefined }, - { path: '/r/e', - mode: '40755', - type: 'Directory', - depth: 2, - linkpath: undefined }, - { path: '/r/e/a', - mode: '40755', - type: 'Directory', - depth: 3, - linkpath: undefined }, - { path: '/r/e/a/l', - mode: '40755', - type: 'Directory', - depth: 4, - linkpath: undefined }, - { path: '/r/e/a/l/l', - mode: '40755', - type: 'Directory', - depth: 5, - linkpath: undefined }, - { path: '/r/e/a/l/l/y', - mode: '40755', - type: 'Directory', - depth: 6, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-', - mode: '40755', - type: 'Directory', - depth: 7, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d', - mode: '40755', - type: 'Directory', - depth: 8, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e', - mode: '40755', - type: 'Directory', - depth: 9, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e', - mode: '40755', - type: 'Directory', - depth: 10, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p', - mode: '40755', - type: 'Directory', - depth: 11, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-', - mode: '40755', - type: 'Directory', - depth: 12, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f', - mode: '40755', - type: 'Directory', - depth: 13, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o', - mode: '40755', - type: 'Directory', - depth: 14, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l', - mode: '40755', - type: 'Directory', - depth: 15, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d', - mode: '40755', - type: 'Directory', - depth: 16, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e', - mode: '40755', - type: 'Directory', - depth: 17, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r', - mode: '40755', - type: 'Directory', - depth: 18, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-', - mode: '40755', - type: 'Directory', - depth: 19, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p', - mode: '40755', - type: 'Directory', - depth: 20, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a', - mode: '40755', - type: 'Directory', - depth: 21, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t', - mode: '40755', - type: 'Directory', - depth: 22, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h', - mode: '40755', - type: 'Directory', - depth: 23, - linkpath: undefined }, - { path: '/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: '100644', - type: 'File', - depth: 24, - size: 100, - linkpath: undefined, - nlink: 1 }, - { path: '/Ω.txt', - mode: '100644', - type: 'File', - depth: 1, - size: 2, - linkpath: undefined, - nlink: 1 } ] - - - -// The extract class basically just pipes the input -// to a Reader, and then to a fstream.DirWriter - -// So, this is as much a test of fstream.Reader and fstream.Writer -// as it is of tar.Extract, but it sort of makes sense. - -tap.test("preclean", function (t) { - require("rimraf").sync(__dirname + "/tmp/extract-test") - t.pass("cleaned!") - t.end() -}) - -tap.test("extract test", function (t) { - var extract = tar.Extract(target) - var inp = fs.createReadStream(file) - - // give it a weird buffer size to try to break in odd places - inp.bufferSize = 1234 - - inp.pipe(extract) - - extract.on("end", function () { - t.equal(ee, expectEntries.length, "should see "+ee+" entries") - - // should get no more entries after end - extract.removeAllListeners("entry") - extract.on("entry", function (e) { - t.fail("Should not get entries after end!") - }) - - next() - }) - - extract.on("entry", function (entry) { - var found = - { path: entry.path - , mode: entry.props.mode.toString(8) - , type: entry.props.type - , depth: entry.props.depth - , size: entry.props.size - , linkpath: entry.props.linkpath - , nlink: entry.props.nlink - , dev: entry.props.dev - , ino: entry.props.ino - } - - var wanted = expectEntries[ee ++] - - t.equivalent(found, wanted, "tar entry " + ee + " " + wanted.path) - }) - - function next () { - var r = fstream.Reader({ path: target - , type: "Directory" - // this is just to encourage consistency - , sort: "alpha" }) - - r.on("ready", function () { - foundEntry(r) - }) - - r.on("end", finish) - - function foundEntry (entry) { - var p = entry.path.substr(target.length) - var found = - { path: p - , mode: entry.props.mode.toString(8) - , type: entry.props.type - , depth: entry.props.depth - , size: entry.props.size - , linkpath: entry.props.linkpath - , nlink: entry.props.nlink - } - - var wanted = expectFiles[ef ++] - - t.has(found, wanted, "unpacked file " + ef + " " + wanted.path) - - entry.on("entry", foundEntry) - } - - function finish () { - t.equal(ef, expectFiles.length, "should have "+ef+" items") - t.end() - } - } -}) diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/fixtures.tgz b/node_modules/npm-lifecycle/node_modules/tar/test/fixtures.tgz deleted file mode 100644 index f1676023afa2bba2aa18b5508c92f03e1d0816c6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 19352 zcmdS9Wm8?>6E%oKa0>)?hoHgXLLj)iOK^9Wixb@4-2;JO!GpWILvVM$XZZb}7gIGe zUtnIH+O<#h+1^?)mpt7>+4-uRLlz3qxI~Dff#Gk#6 z`g-rTn_<`NkGgSqh`9%iyIO+RJMIEk@Q^cjEPzS$QFJLbkvahQFp1Gi?M1xtX z_d_3jPIjl>+%+o^H;key?OVfX3E8v2FgIk&q5@J)^5h?H8?w4%1l*k;@LW8A*KOPe z2m})_YIt^yV27?Sb9o}&8YLHw}wmBaI#s5;w$~1gL}Yl8$kSfR+T&Wf?T=;vdl4$nrcnE0Smw^kG$rI+igCu zLr{XYa&G{kKrnW&uV)Zm056SzBh^q4DFok3neK>2dnOF*v9)P(VIXSxruX3R_(6<} zOZDyM+Urp`x)%;WHfqw~UlV|((9x}_0fV6Gd7)s-8b8Iyj6dV=FE|k7SbKGn(HT^^ z)#XFd>jGa=?AGFLS4E*@QNW1Z$Q|ykv(g=BFX*Wsx?zg(0`LaBgj=IE_Wi($#wNW= zsOzqY_94)b9n`KM(7@!i*G@qTGS7a5nPO`&8Hxx?HJ_Gs!6KRIcU9CIXw9oVS zaHGn2ODfpk4(T4xmN)?#5wf70ksW$_I+pa)A=&N+ErhZ;zaOTE3v1zIS}$30$99_@ zb#iRJNa!r%r72#Uo2unZQ3}G@roGZvMz_6UPggT$oZ&9C#MNJTEnx0o>7^3(ga*-0 z&|(RQ5v%!l@f?}!_P4aUe|2XDn?Mi3*r3P46Qlh9V>}CRA zNt_D6UCg|6b#Tv={{aM$OtzmQ$i&Yf7iIx&i#I_l@h5^OhV5nYfI{AjKXEfz1ce5@z7!Ei78)mBhq_n%2+n=ux$t?fCf*hcr8^+}NV~}t0I|P;l~Dfy z!P1AX08Kyxu($y+Y>8+@)w&bh(9{}u_Nj(4Ujc>yYM_@la&?%B6_turyY$u2@C7Ki z>{{J++UgDrJ_)=BW)`g6JJY#8KLD>o53tw3D;snh2o7LH?m=^eY+@U^sAij6@eoCg zkH_?3)Vt4Z*h_A7gvEms*^r9@fY@H{SLyQhOQ~PLr_8c^m+W6 zlrdDj_DAr1kbw4f7X2lu)tdOTJ+eBX@l1;u?E88w$R9$A)^86lIoi1RR&Q1rArGd{eH6$HSpvF zphwMqYsS@TeAefy_J-C#%>?2!(}CsK(bvhQe_#uM6`q@?pN%Z91eOzx%h4)7d56K} z)Y>XP9eIg+MkFab6~VjxnM+BoY1%4Zx=r3HKSCDP%_@HsDh**J8G*6><~JvS-j5}W zzN>y}rrh9r%-$m-a*1~eCCjaY{4WI0Chrb*X9B!|^Ez45U3nMx9@%|hqVgKF`s-r!h3v08+ywa|;0oDPc?XrN()H-=WDK=y zYaai@>}TjqOax|hLM@tiXH#C5pD3I`W*?@g?R}KHX+&_+UXGkWX;7aZlAJxXSl*cx zS*GW$`UZnO^uK)BKz6l^dSx}sl1Qpa^#+1uSF~LmnY(|A(wN?|1xcWw5zz3P!XGbX!q*-V*b{#S=Ws@+bDjMqk5mR zjb|;MQs=`KY3kmnTUYzAgWsv)(G8PGVimd8_qS2d+csIGooYB7qs$E z8qKum8fe9z76`L9-#PvjK?QY-b|}l)`zd|C4?)Yy-$!6Y;d`A+A@xA{o}Vktxsgwy zoqqc4KkmMe6m5e2jhguA|+(eH*iS?hzyIMn+ z*2>F;9VRY<+KhECR6w;$kdWCzOCC^eK?4a7Uxwsj*i2qfYtIB9Ji+y%+tD{y;QP1e z`|!*1-wv?f5AXS?iz0#SV`herWGe_@YUeXDa_PUs2~Rq~;?TQPYo3Kf3i zz<-779Bf06Qb8L<@Y$qZ9>^Q%l>Ue4G>6=*i}+H@LkU9n%wtq2r4 z&#xwgbmf|^$iYsa7@p&r=mtL$WkG}?rn(krh*giCv#S|G{h4&`XCJoOfL<32oY8zO zQlQ29&yX7?JdBB2^7R5-gfm$|)W%Ck|I|qwjDe&U21RC{5t3J}t$P|NmVocL+8ZvX z@9;*5@cyf>rQ9^-5z1!?ZOk|`D=IEEySb!I_CoH@KUfDyXp$Gk+r;Rra`-! zj0UZ?_`V$-(;BbcvphCA{EylZO-QQovUdy|4w*%v^%Nm=LAB>D*I!)3##;t#V zcQ1#fZS3oy&zBIV+ORF3FXyeVT?^mfJ%lTndN~%rZbdF^7%edU-&fNIfy*>DMkS=5 zB2JS}KyEh((s@kEt3{)RqWQTnruDh&O#P7zMN=62AnH)=<3cv@ruC`+=v~dLMa^zo z%Sa1g^ap9J&UN(pNxev6GfRK3Kx;9=fZr_ixV z(x3w`A`sma*0_xyvpxGm3S4%GwwrjDz(NP{m-A>O{M5bxY7Pzaiyj2SuXY45KD`E| z!eE4+X$r+XeEdHucqp6>k^Cp#T$t&NHUI;>gt0=sE1&ED2uMo_%uEi!-|vGfHc@{01*RPWf;3OmcKDu@q4D`r~G_ z(cEfdB8)Dxe8|Rcw$&nDOk;}!Y+gW~kii^451AKm=;+x4SMvd&f3I;Fc=G>fCJHGY zv93XawV43cpe67!%BJw191>o~x=y17u+AJ`0N-_20YniO;WGecsI%O=*cuEYTNie# z)1u!4c5u7z{(%;Nh{C2QfCXNI1x);os8>UWsq3y)G6$A&v^7Xv2j5j5l!KIP5H-cq zh2#bm)_D|wCx&uy_%g7I zhQO3;_N&K#5-&8U3GnvX;2+0JbarZeLmcoY-vt@N#Pv-;bSZ7^BaMZHWf6}{AIHbh zrg}Px@lB<@8%BSEaa-=tE+27*iMCAsoaCGXVZdb&_Ul5p2ej^zzZOq-5!>U1tbIo( z%H{qV6h^G^=)*3(+=_v~wQl;y|9YjlvvG?FVRnAF zx-snu-~?f$))jXqriYcbVp;Lai=f z7LWwI%QDBh-25|8bwe;s6!)8egGnwV?GC_ZjizE1c_TyYYy+$qE|o_7|EJmKo7;AG|CH~k3w3D?x9E0F z3KI8Ac*p&BPG3Zxxbzx&kO7^nM^H6MWAo~CbWI!?x_!>;g-Ky^%Ijv>rl8D&<}ko+ ze8>LO)zPs7y@`dSoEow>+JpZ~@!z;KL@Q%HAB? z?p;$|4`WPDlLU^H;3-~PzR?twcq6r^GPayPVaXZ$5P@VzCtq7SNSZ`Cc~VsD;f+V> zOHgm8(cKe^_Z*r}tA1;a;}YuSPG$y=-cZ0R3-J1qy@k-WBn9{O5N}cx2lw^#^7FRy z#udOhocCr;-VyfG&bsQU~7jK=$3BDXX#V z5|YBb^8=U__EqasEAjr`GGkhAyP)o#v)+}CZOW)}8{VqNcL-u&zmwmGn@2K8;KI=-m!&T{tS+)ga26y*a5X?0&iWY?>yGgvkxeHcLrci?Y$}zH1+|a zNVc1$H+j;h=U^S=z2`+mk-33|yeD9{a zci$n8{f>Xx%33GVpxAqN1`_N&_y=%wFN06eKoby*W$>@GzII^u7Em#|hhS7f?qi!( zzaXv%i2AC#bSt`l_3X)j1u?(!zJO?faD&x(us$;H+eLREEaJ%reu#jKfFYeW`|_U` zZb3m@vdLQD5HaCG(iC`+zLo0p*i7NCZiOtKfDF3-%C_u04?^$z(SBF~N07DM86q6s z85)rr<-U=5sskV^#Ls{W1JsEKq^mSohn)PnsmRm9Vvq+GTC|-+Li)D}@9QU|fKZ#> z89U7#DC4<%_a>puerSK*^6HnbD=nP>S)=~j=3c-JutPA}tNxfe~;2BRqT5#}dMsM5r|8?n=XVw51`#Q*3`Pl-PV5$y+?;#JpXb66s zuK`r@o!+m~ssC*o6aRTX^OzQJuCMZ+sexC+W=K?c#tArlW9x1abQRQH18{65-gR*z zxAZ(CChP(w-6bcWKScj62Xj{eUF0!sK;RdgLmedIoy-yUe}XUWaUI|89DE{@0NFsM zYOufVe=mmz{>Sw{e?yw1KWrGi^+3CxbfLb7ZBRI>lvChz(hz%ElDPlU_Lv*j78+RLYcK15!Fyrw!z6z$$w`>R-O&B|%F{bhq5hog z04W$UeDp7_!8Q?HhwhEE{c7|;=n()KS{df@p@eSH46p|Amudq35H+=@vU2kn+SwAj zE4&0p(S<%bw>)UKKizKko)0#Me;01|d^_&{=?QpU9Hhlz#JPiHKYPC-1D=E=fVxNa642WUvph;I>V8~GfQLR^emR^tS?_)0nWH#e zJ-4_!dFfbh_IYNtk-Ah)aEl-7bK)NA8l8w#)jG2sTS8oJwpBXvTDCcDn!kX8iyN8< zocN=i#-6Qm7hJgE=a1vl_^>*?G1%b*{vPnxuUjB^`K^`kijzO)i$u0(*`|!G0Pr z{1+;^@g$>2+9CXSyFa;Ob&5DCe!xXimh+*Su=-fIX0p^2T8maoCPJMOt`v_g?lvNz zdE!}22fk4I@Gm*2=bRHkYhb*+xx$-?RT=!b?_t*eVD9+spO5`5ruV?7SXSD#TlU|a zotQvYjLQztfs3i+QOAQn1lqNQD}`p|xTS4840q&&uczdt4VrVdh8i8X*z1)GSOSfH zL>smDyHHd(LSwi}`6&V?=ND}22{YM!ka0|6(mhdt5P(oh#Xf9YI8hob4Th7yvGmFp z;kkYNxfAaE%MlG_{$sJ_90OJMqqKjbC}`j@OR0!f8I==;5s_5%3#~+AeII0jE+MYo zDH0CFMOu}CEEK`;w2QEFX$5SCMk;aXx0cu4;zb(3_}rT$YHo$)OKAhI5;J9}2wNjD z!fpH{j28Gwfw};#;lq&Asq+w|Pz!O8frkgAm^?7L~UGScl-?lo9__q4Y(A47B zpAJ_zT}^kjueFbwSv}rwwo@e;sb53I(QX?yttxn$9@D@(=5-kD!pK~Esfqyuf@=WA zTgZjiJe~j36VFKm??(BTo9)@v;EuTCgtL_g!+TZ$vYvfW06Xw-r%dd}`|S7x>j3e! zY*ZSodqMw~A2et>DqMPpc`KmUC?!Svac8qHsmn_-vy>Qp-uCw4DIsfvNS;<}|UqE1v1L5t(E0Zf+zv7>t?j)BRv`v89t0CVGmO=E&Mli>C zS!nCy<+GeO)r;yZQAR9$MdLo*bp7{^TDt{SskIRzs3OJU;9)CaA-<1q5$^O*7N9Z~lZ(I&w`Y4jg4DnaUm_ zn$q-85%$sxEyk6;y0f3Ta4gU~!;=$JVK8(VV_4*$$V(OYj}?suJhqS6XL1IL zI-f8ImvB!n<;~Vj4~mjA=`OIxavM+~8uu*N$Ct&YzWxY!l-5bOsMRn?*TeTXzf)AM zY6qRo|Xx!Lp#{p33m01t-HZw~2f7we9*ssbILy%RT$N?Devedw-hN zmAF0M#h=c}jS+7K;h|0aK$0?lIFzDXY4G`7He~MslRI*Sn;P6FO+^`bTwZX-S@>qW z0lywtK(O^U8SgmbQ$1A`Nq~eaVxDlPz!D&Zx19vy{1Z2&?SIGBuTA!^4o^!39e%GG znvxQ=39~R*7E_v<)8e={Ex72-5Ht-V{A7f*vYqS|j2Sd6B#HrJs(#f7`np(%MdU8M zjIAil(WHpzV1<<+_lqa=F)e90Z))bt+NgwWc-N`FaI((UFog+~_c=bXFHs;(`tW0q zS#ZdemGSLAO^FcF-i2mgsN61Wkr%pNVm|N>)M%34D;}y>mB?ngt}jE}-%J#hsb8PJ zg<|G?sjO8~m=j+}LWSX>tG`SXl&)KrP!T*F1>uvKuiFF7Hbn{{G}$M&ynuObi4&+1GJ>z4JkX_I5AxKSjk1d= z(9~6Oh;a}{YBrnqPLL5*j#xioG7m9lhMTNhtk8cNY+BuzVoB0 zhir`hasHztJ!ptjHv30W6qZg~lh}H+SOyJE3}$Q-ugoAF!8f7l+8Qep8)3HCn>N(h zsQ@TRDBh9u$+cfnZqIGVe;p-*sBybSI{0JlgNMKF{7M+GB8~$@Ai#3h@yBtcmX!(i8g_ke4V56?ZEzGLR8k1ghRaTHS&5_x?g$ z#Qvk~W|MENd;nYG*JEg>(dfT86(lWQbC|7e!E_-}KRL_#zXYH@+kK9-<>>jacqVtfd~w70vFyopsz0`P^V+|8jqp^S zT~JBkxJG`-F@u&F)f0d0#(4j!y)}qltWbOP@ zAJTksj6=pJv)9d>GYnIo_QE?Ob|d%G`VzROz2|6k z6l-NpVtAXHu_O;7d6z;~o1U7?{}Q;*F^gCK1jjKpZ8aIke{q*s4N|!rkunY*8ut;Z zL$_>4yZ$tXS!(df&}J-bSkhP~nhy|V@9EyOjDKE!Dwe)pC4o!ec^10NdY)mO^OtU< zqu0*o{LU{vA+To}zM|AN+t3iT$w$%ick;^o=7a^ehFmsxM{_d0HSm?60F;IPOxMfF zIbatnUSgUuC6s#)Q3Fq@gu%TIm&6e@So(f%zXtbDXDx#Nbg1L8%rd?Zs7B7*KnN@o zm4$PQ2aP@}vJIoinIc1vt`p^uYlcmHspz3c>9ti~cImcMEoLUrwRW+LaBuz;E_2A( z+(b`>#px%qWK=)t@+`|h_8M|?dZ~)1`$|wYG2D`9OKZFZ1j%Z0V6 z$XWk~^;0mR6hd_Q;PDfHc)!_gX+`erEyKU-|>^{|+m*+&>F2P~+ubElv&U+s; zMOT;j`(EF#-|hcKD5t|pQn3(uDllY-t&_pRD*Rd&>*Wh#IPVs`(jzhK?u++PJ?nFk zsKQxNQAVBF`E9#CVppX=7?%)6hcn3Nhks<5Y|Meq-1I~_mM)aITOCfslr1Q4`k4Vn zo_FL>Mxadlp;a!UHxw!v;2cL@VG&^!Pm++mETuJhL`P_m6a3dfQ=uEg%Z{(Sa>TJ% zH%h(4b>L^vU?r-`;&R~XY?y*lUiHs7_2nWmZq&Cc+5N_o4*hcVpY?V2KUd4pInoBw z*Dv#EGKstlA9Oj1YUTM9qnq@Y`u!w)Hh=#LlF{TVN6{Z9A+jg}4up}QZsY_JKR)L(fx%d$j-tX>- zDaxr;2{IYl$t%Aj+7Yw(wb@-;A3nz*$3%E1E)?9N5FCBDUoX|yY1kr zfWQ{f>0_j8AgNcqau@?YJ<>3bmWCRbAHtBEc%7TAupMYDyhiPwj8m+t>4`~YjtlR_wW9rJw#o-CuSAhgo)2pHC-F*A&z*s{N2g~rsor5|9DN$wLrN^N`zCH{## z0!?mI(KswjWMRQjGM5e)D94iW;~(YPc$$j@sB|^F$EgsP`T4UwX-tfb#bdRV;A$iBXvzM3@=aFWUEX%|J*ygV$I^db3N@n%O(m^UGhrL383yT z`fv;-6G}Tyb0jxdo-VRPD4t6A6~20;OzN{o`~VT_EKfnk*OdTvp(I=Wfd(rJuN0O9 zO!GR!ejfTqa_mEeZsh=hh@cN17>xfY(q1`jc*iLJrU%ZwePcLUG8cuF9c85<0GuNi z3WV88IL`xuI(Lo|b{+i2=;sN%!mtpSZM3E>f84c|fLsfKIyqQKB30N*kg6!{>z%d!r1){}Y= z8j0E&5CNZpIxi^}5Sn1wbAZF_+NJ+Ai-(Ns2gvm9w}n*FUK(2NQqgolH{>4;uS z_{_9R8KALTb#FaqsieTzXtWcGq7xAt6VZ{>xUWac#oNPr_}$r68O4**_s*#OQ)6-p z(V`NGQa4{5iI@16BlsnU>F8v|N7$xtRfv?}?efaczWPd@%d10)C9D|Yc3dLyJ|uoc z9J|^xt&=e}f%E)4AG-vM{O~a=B=V)OLLL#be+<}xKazE+tEionvTi0Yfi9u3BIf^{ z6UXt~)3)y18FhrztLv<*S@cUWB;M{@Z-Wx!2~mVdsl~{bj3CKea9T#?kE(L{2g~@% zhPGsu%JKch+FVb?WNAjl=wwoqp3iJBc?8?Nz7j2El*Z4tiVbv@@b0doV?g8`+VL0u z+va-7wsHNhFK}_OV9ktOs&vX&f_gB=U)A1)3L=vlRPm2#SFPj+ldfpf-w1IBAZ#=B zfq{y4Gm$gYqfaGT0jQdKPum>mN{C4*LhdDmJx&#+ck4+3>6y% z&s8(>scOiSKIas!i}Vn4orh&_(p3a~&ukYeTH~50X}t}L=t085xv}kvOuO#Wel?03W#B+I5zE`mmtNej&8T)u4H zT6JUpm*}aKgs+2W;sM$>81aVq(M%JG6er@Gm^OroJNgB(JvQ1VxDg#hxc*HSjE2-P-IvS38)>j0J~r-4EMVr0D9wX7ONy7J7};c@0ixt4`}QXi9= z69xU^G6hn%YI%~2;0@E2TjF`Mb@c<8@p$gY|tS%CF&IzAJ z0-{;AvH`_1l4np-Nv@u-jYH&c5_fr6DIh}CN>96-f%K)l<59m@70pPTCae-$F1s;X zxgE43SW5K+s$q1Xm|kWUE2_))v5&aL`HDA6&C7Jfq{=tiJY_qJ{Y4gWCo&b>ztQ|} z$Sf6z$Q}1U%rm$kE$@<>tu&Y#76I^Ge>01rPU@%8rr&1hOEiu<16U4L)W^9hh`!-#dYW<& zrTqDTS>G_V_Eptq3WY3gi}=!V)y_isvd=Tr zDmb)dZg9`DDnfRp;TI38hX&NbsK}~V97!Cj!!nMCMAMFu5ggD>34ZkqIb&wGO8~qGk&OP&Czw7>2bj=cw?jRLV2V)~clR z(ql!59qI)^FUt@bPi0PP`7tmP(zQ*gsNS#fTwj-zt{TKtx_(41LWR$Pw#3sjCkd!b z{`2*K@gOi%o~XI-ho2DFV-=`aNYz|Moje#qi*8+rnK<01Q77dNaM>xTNim9B!(eK=HML^A)x3%H+M7O|#ks`KF@1WTf11NaDF#O3w6;G^ zT414+x~Qn&4dg_9D4lZZYTe~mPENYEU1+q$^b$O`-hZSq59z?Z$0ZyTWzsL8mVM4v z6>vIGO-yRshj=1Qi6{g&Lk@9sBeYEksGV+B~^hc#-$OB(9oM6oU=_4G&{z;S#+Flj4tNFw%yhtD;xMtB;UiY z(O^1E$l>b^)S0U*jCPl7u4CrmMz^g_@O+kAb+8;LmMq?jh|W|XM%!txx0;*AGBV=Y zvndnZ%T|-SGJeHnjI7Z5iHol>8~*5M=;Hvbd2MoL`kYF8g^ZP%c`!&F2A>vgnjp-! z?`|<*(sieWAeKpOre}>;NjhBKKkCe;0$Za=nVu724r(}L2M!e$>%=_MZ{%cq4qc-z z9eapX^OQJ>KlvMfL*qU-qb^noJeT%K(f1l-Z92>^2oXZxIMTH$h9r_dxb5|LhG_4| zPPcPkm5CADQ~et+oIc$t*!M3ASwwvh%?SI*XM-Xbz2o;<*fBaY7EY^1wD+uv;0@N2 zQ&Lp=>!XUQ;z6wmlVYj$y#d>-xSDg^=5tEKQNEP}rHiC2PGY37DuduZ)cGFYcJ$jQ2T$qFN1R~j)R z*iow<%zeGs<^w?{7lp(@+zMtvT%#(pt3@^284;4y?pKWPxxW8gJ9OckTf7!WBFpG) zL`EtPu1!Tv(G+7RR%Y_uj!jnP922WVWxg}$U$5JzVbidm`wR!&6!6A}x6JCvpy;nF zBEXAMh?j;Zx*V>N25d0w^a~-lT{p&S^TARz|Ds6eQ-5)&|3OWX9he%|pitR-HxkNa zCh6B?X~fT79b7n$i`->hV5GjsG$Ibd7sxyC(b7l&w@fYLZr3b6R=^M*Z)2ydA;{(}^Sj*9>93*Q8ZbBv;x=vvVu& zA8wL+z#>vR&1B@;G`rtwWey2z$`Pm03V9%zMT=OKXO>S;BkttPc4$ktYPg1!P9E!T z-Pz%dkfem`VJta|_72Y94Ywr8VvLwfu=?}kuFMTKljaTKru`u-hE|31{MC8ftK%<> zYVm15tMl`J{%QH!f?MqFg7PtUfg1HO!}D`acJp42-~h94K|S<^S8`X?c9*a7wK$$< zptP4Hkqx7vkK*9O)5QZnIE(#y)=d1oCN^fw`s7wxTW%j2ZLH5%r}vcITqNk1NGK-D z->TSsmeub1zfYhiO{>}hJ~k4ErNU~H$&!JpG#52If>jcHGub?UjV_rWWjj5rRf@f4 z!^rctY(p ze*P>EP=@pF709C>gwG1JKCWI~xm>XZ59hH_#eRoff@U7B0;Tf&n-eZO`*v3$Zoh%? z{h5_v;G#hRK;<1>6X0YOGe+fTR$2~C%2tqbjzu6i!1f`iN>^i(GUH*W7mdU4&M`NG zgGDLtVV$3)7$9dr>6OwL^h3}lj6|nPSP%Q$<>xl#=}Uaa6BT54}ucX2MhdqzujElZsA9FIEh=8R(FK2=V%N(UAJk}LCzOY?5d?N_riEKjCCJM@nPrcJ z2$eXoJ0&9$vo*1P(A8)NU?|*;NxxbN)bv`@)KE72_Bhfn6XSLi!?Ls@ugdb$(lSz* zV6kRZQzH=0CYS$MAo#OWR-JW%ZlFYKU-nYL2WPUk^jq2H;1R_6_GbTHv4nt@Wl_hQ z<>PTdBgM@b#v8G|AE!_%U0~lZFUj}hDo|@(P3XYe*Q3268(z6^FWA_63s-qrZmUBg z(%)<(t$xL-L@)!RLg^(bZY40ClRB zFUny;U6kwYsS3@ma9Dh#Z7zk3bJET!p*3EVHy6jmRgs43O$Req!^w)u56iqtFe3QU zygRPEDe!vnWrh*DnSN4kv27o5HE2*mJY@!#(NHTV0{FhV7u&c@qGhaU*Qftu;~$v7 z|By({5usl35jMvC-Y3}xC7T4HKsuq7!0EGWxak2sEQ)D~e{5U_x)8n;&rmfb|)$&Jai0u(|?f#W{ zgJe{6m2JP`p0}no=bLWhAMCV^9;;C8FTGZpWpG9z&9_+uvw1Lwjd<#GRw| z3=;4DXsmH~l?y74_kP!vA8vpE*D-EphDMoXT&+AOQFqTZFJFI=w^rWGYJdAis7)~- zvxVQEhRvJEIf6|sbBNSXEnSsaVRS25VPWPr8(R@Mv*VoXhdDSK(c#B2flysH@`-8h za8H29Np(PTzO)nfP6aJ*`O|vT~?fQr_ zCnil$`PU9^*_=C~>PJ_ziAI zgjUL`!Y`O9>U{J8(hNBiR&{IjIYy_f(;FX^4R5v^ZrdK)YGy_U+Us*e>^tS+OA00f(%Zcd*t*9co@s+l$UqLf} z{ru;)QBWS&03mET>Q@}r98Z0HL$j8}+4NSau8EM-*xB6kw(sP462tHcjc)>vO?v#aFEqkcDk=pTb%S3V~!g#GMlXtQ_M`r}yarJjf8 zt4O0e{1NVXu#t%;@wF*oGs(S8!;W{qU9T+qp`q|@Oh@apt!OwtTx5STa!wt#MWrh9 z&&2Oc=9{*$K9$zTDXSJ@TEvl5cT4KO(Pxx=aeA|^@uUS+1Mv>7cmZTqKp}<1l>0cT zO9%_lK0~%ANlCFD^*iHmIpigC&C@nM)Y&w|hJU-AeSCRxc}DZ(e6wozg5X4R-NO*C zx?J(VeuJILgoHQ<9T?Ji2?q>IR)eqv4A3UEb$s`JDrG`{UlZIc|8XWmQRrH3Sy?QW zD;0PQ=KZC(r2I|y4^B)!NlEghlgj5d36CEm<%}qA2kwp%8h!+hb)Pb9T@oEqV|wW& zsD4(<9;h+^8!}ZgT_tbO_VB{^e}0cE>BPI5XgRHr4GTM`PJ2XuQg7!}@-bwoXw*%2 zZ!R?<(Mg4qFEe#A<$66DI@L-_KTrFppw@ZcCrn1A%e6<^_|`7>E9n5Eg;PuOcQC4F zc1212(Lr-laGEz+j(3IHE^p&e^)cpNv@&JOpVjYN6Y{;#4Kyej=3?j}%TQ**&cyL} z(D3>VRddzHOx4s~6*^y^MW#`uEuspvA(^&&_V7Qgn$~y%nO^+quorP#Rjlm^Rc_iP zkk;+*YZ72Cb>J{_LY+YLFKvuX)?0_N9D^>Br4c#?vg6WjzWb5AR`vQOn^o8VTffc` z*aFRuhX-%0-XRfPPPd-R+%+?gwDM=ga8_AzjYf3c=d3;UlH?uh}ewaGIN>366b9ET0w?`)3c#{le=nU5?~9w@2$&l0T$YQA?}G zmXM}qPYYN5L^tdU7E{ZL7-uqZxRgV&i=tAW;xM)nyQ3GjiR8H>wXTb@{a*U1u`<)Z zLA$JZ)-)?*?NN>)TFOX@A@~V-N-Bn0M)>xs~vpA7LY5wvp&AT>RzCjOU zMLRxIA_d|eSHUM4-_Y>y;o_cx&Kpv98$5B}>}%>Qp7$UrQf%^JDpK5TNtvb_)XDU< zz0n^$+=Yy?C$3B8EwFS|uDY0zFpVx^94J*#L&3r(2KhO+%M=q<6fYnoR>;KalL{!9 zD;fm|*g4F-ggKq>C?b9Fb?%KEz_xh z!`sU9S7ah=9S z0XRmaZ_Tr^rrxSgq&nJq1D477zF%N8g-rRzoQL#~7?L`fl4u16g~U-Kjh^igaVq|} zCZ*A!R~E%*oG0BDxAXj@@cmX+H`4yFt7le^bEu4qH?Dl-R@ow^$#a-*l7Pk`3>mJL zLG(iQ`#hK2;T+ua&$%j>A>44J{r-7?Y;bn(n;maLso>x`g1(xD*;kJjA(z~}H+|FU zw?+Fey}zAPlj00Upl(YyBbPD9mT#Ji;Eq!asmY(YomCVjKO^Ml3dNOxXm>(irQn|kxMx4Yi*B&k(r zCPQe}@~1Ej%`WMOle=x*^C?jcms-bF3EW=L&?*jvlZxy9% z7J;oor9fV#d%tVBOrLd*^1Z26SEmSjy?%`k9jxxujk`xWP*QkCWyr6o=pzJBTr1XmtA9*a zdwav9s^QQ7468(C)Y>`F?4C+9Ph*TMtt=eYZiNXe^mQ8jQ@76@z6-z9 z)xFahF*Y|Mb&t^uk4s=^$+NiP95sEPS^y%YFB@)jkHg2W*)guIBYaVGRgeIC5yL-C zKX|C^ir)B`I+?1`%V)EjZGq;FxNMX#Fly9kwKT`HSfbWef~za?u`PP(?4ONz&+dQS zbMTDm%4ThX4yjdtnZ2q++ z;e>r0Daoz8m7<|GpDto%bIOQ)OvM-@?EDDlo)VEcL0i)9md$;1iefcmwQl$0e&J(z zxLWyKez6GC@h>i;eMF`4A}U7H)?2jJ?N`ff%AioOk`e23dV1DE1siZrHquS$ip<+j zGHb@aTh^)x58mTtELR!VvVJMHajK!8nb6J2D{((htC}uWSK}cyFhN%P|4v0b8VNh3 zHL56TcUqLHxDGKVe7mU_BTdz&0%B@2zX+&281y62xjXArEZ_AiH+ylE%Rj&TZU zl3(f)(TsMv4O4Tr-um?_SCLrny!6zxiO*5oJNW&4SaH27^3y5D)+tPl#*wZ^+x2X3 zr|KK?t0viD&Jp+&S+nZ=a+o5BUEEUOZ4;(r^;$F0xkrCLTKB7FIWty>06XqPUU@ER z=VmZbe+sR<{9t9Ze)#v3u2({~;5uaY7ZFkd!FJGbX;6Z<1wG_1_Wu>?2^IEHc0u=< ztyE(Lc*9(SQX|-{-amIyl2y(618p^9d%%oWlh~%1qD)t>n$$>MKwR3cH)M1(?%72m zDZ%ryK4XbyYG{|MHS;-#r%eT)pGo~S%QdYOsg`qpj>lK@(M0Pw4Xb*v2%W^{a z;tq=M@`__Bg`FC&j_c}9;$&H|PcAB3-e^sUoBgxC9qQqtz@nV{7iGO6Rq7VdtAUm0 z!SR5X>6*}evqD``Q;m|-Cw#^Wt*VRX%vCdV$qWLMGpMpe$JrTHT|+|crQbNc#w6Iu zc#1XCVaYkwrP?D7it2OiYK$g%fPQH{KltR`6T0N*iU$ep=&rd;cC9<(+$0W?ZqT4p zMQY91b$D{}L>45&(_1so5*7{T2SK0DP)H3CY^DfZb&6xj#?JWdO~B>f7^H@&_mj#) zB+b*r*Djx$Ws3+nMo&bf0`vYz#actah^P<&s;t;hmZ)>?2L`+;d0;YOl(>U%*X z|9EDK{TY)e>Iahf&dc&L*P-D;L6fo}UD1`V;HX`N%g=Dq9Xm@zKa9k*!u@?Nht_J(i}@4PiS z8+=!rxhG*u$u!}E%`Q0h*KD?1MQqjy5I6?L%9y3CLQGe{+v5}?k} zR_^QlVW%lm%Z_M zDIy&PVCs?A&v5<1DPBQf23ROC!UtH3VLE~(25KCqWy(W7tZc2r({^6>+00etbnKfg ztR;r*X*3Ij$c%5|pYrk?b68xC{Aar=0$!Vnm!NjdN7YSrGL1>1Hd-?+d0E<@AG$Q_ zgUKZww5T|8HW=}h>SdX8IznYfih37Xb(Xu=%E%bJ@4W zRLBRTAmH!aIRR14E;GAN-h?J=pw6b}DGJ1I+2GE5L|6?UygYJ;d4=%6TSUc=F)J5m zU^~?IgXEn6m`Geq%4@R9(|TS@;^G#)8G0WJJaD!jNe}xa-+a{c0i|>$X4I8$Q%(#9 zVpDg{;z_i;14BgHci6FyC}6TYMJ(l%c#U%)g2ncMx}ZiY+c#6)bXg&F)*@}Vema#2 z-Q9BPC~k3)PslmB z(i-+FSLqt5jr2XIK^daixLVsdCRAB8vaeBR1Lg8DXkeDC`jYkN2-saF7t9>BpFD4JkrKp$KA zAL@2H+T7=td2fHniTr5BwPpvVCMvwr99iMeii$Xu81{Q=%fuK83Ql;>8VHJl^6Di6 zgXC9gTW)iu(+NC1;Zq!F;2}a;0!js>P0lSt(?5I^=bFJVp1g$yBn^6zPK{Q8ij1;J zE&M7U)lFBkhp=D%55F2SV`}D>*@rI&NBiQ}PX}KDL z@n)2OSK9)#-C5m?+XI9Lho1~2=GPxT9qk>?`0n+WceB3Q{c`jktEiS=-cmaRo`L@} z{BQT|+s}K4hp#q1q{FBFGrU%DG$rTo8<%^cE#eocI0d8O<>S-IWc1V4*7xtyvZ}3r{Jk|fpWMC;&-0Qf5|6yN z-A;Ugf8)j~{Y$_5zVQ7d@j@>S!ccgD7l+X!aen)z=L6kR4PEIMY1%1fKL?NXdY9ng zp$Pr&Jpq_*ys6-2oep^QHv&)4eIhUY$lH$Mot+&YKTG+uFo?IqD2aA9f>4#s>t^3x z`boRp4*YH7CgH?j&|89T0Re*`KfHr_1+Oc;T|9ip@!giD-L6RiE|4};x{*M>X oml~`&|2uHtz<~n?4jede;J|?c2M!!Kc-Zj&1MZ2imH?Oo0D?ENMF0Q* diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/header.js b/node_modules/npm-lifecycle/node_modules/tar/test/header.js deleted file mode 100644 index 8ea6f79500de7..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/header.js +++ /dev/null @@ -1,183 +0,0 @@ -var tap = require("tap") -var TarHeader = require("../lib/header.js") -var tar = require("../tar.js") -var fs = require("fs") - - -var headers = - { "a.txt file header": - [ "612e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030303430312031313635313336303333332030313234353100203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - , { cksumValid: true - , path: 'a.txt' - , mode: 420 - , uid: 24561 - , gid: 20 - , size: 257 - , mtime: 1319493851 - , cksum: 5417 - , type: '0' - , linkpath: '' - , ustar: 'ustar\0' - , ustarver: '00' - , uname: 'isaacs' - , gname: 'staff' - , devmaj: 0 - , devmin: 0 - , fill: '' } - ] - - , "omega pax": // the extended header from omega tar. - [ "5061784865616465722fcea92e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030303137302031313534333731303631312030313530353100207800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - , { cksumValid: true - , path: 'PaxHeader/Ω.txt' - , mode: 420 - , uid: 24561 - , gid: 20 - , size: 120 - , mtime: 1301254537 - , cksum: 6697 - , type: 'x' - , linkpath: '' - , ustar: 'ustar\0' - , ustarver: '00' - , uname: 'isaacs' - , gname: 'staff' - , devmaj: 0 - , devmin: 0 - , fill: '' } ] - - , "omega file header": - [ "cea92e7478740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030303030322031313534333731303631312030313330373200203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - , { cksumValid: true - , path: 'Ω.txt' - , mode: 420 - , uid: 24561 - , gid: 20 - , size: 2 - , mtime: 1301254537 - , cksum: 5690 - , type: '0' - , linkpath: '' - , ustar: 'ustar\0' - , ustarver: '00' - , uname: 'isaacs' - , gname: 'staff' - , devmaj: 0 - , devmin: 0 - , fill: '' } ] - - , "foo.js file header": - [ "666f6f2e6a730000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030303030342031313534333637303734312030313236313700203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - , { cksumValid: true - , path: 'foo.js' - , mode: 420 - , uid: 24561 - , gid: 20 - , size: 4 - , mtime: 1301246433 - , cksum: 5519 - , type: '0' - , linkpath: '' - , ustar: 'ustar\0' - , ustarver: '00' - , uname: 'isaacs' - , gname: 'staff' - , devmaj: 0 - , devmin: 0 - , fill: '' } - ] - - , "b.txt file header": - [ "622e747874000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000030303036343420003035373736312000303030303234200030303030303030313030302031313635313336303637372030313234363100203000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - , { cksumValid: true - , path: 'b.txt' - , mode: 420 - , uid: 24561 - , gid: 20 - , size: 512 - , mtime: 1319494079 - , cksum: 5425 - , type: '0' - , linkpath: '' - , ustar: 'ustar\0' - , ustarver: '00' - , uname: 'isaacs' - , gname: 'staff' - , devmaj: 0 - , devmin: 0 - , fill: '' } - ] - - , "deep nested file": - [ "636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363636363633030303634342000303537373631200030303030323420003030303030303030313434203131363532313531353333203034333331340020300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000075737461720030306973616163730000000000000000000000000000000000000000000000000000737461666600000000000000000000000000000000000000000000000000000030303030303020003030303030302000722f652f612f6c2f6c2f792f2d2f642f652f652f702f2d2f662f6f2f6c2f642f652f722f2d2f702f612f742f680000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" - , { cksumValid: true, - path: 'r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' - , mode: 420 - , uid: 24561 - , gid: 20 - , size: 100 - , mtime: 1319687003 - , cksum: 18124 - , type: '0' - , linkpath: '' - , ustar: 'ustar\0' - , ustarver: '00' - , uname: 'isaacs' - , gname: 'staff' - , devmaj: 0 - , devmin: 0 - , fill: '' } - ] - } - -tap.test("parsing", function (t) { - Object.keys(headers).forEach(function (name) { - var h = headers[name] - , header = new Buffer(h[0], "hex") - , expect = h[1] - , parsed = new TarHeader(header) - - // console.error(parsed) - t.has(parsed, expect, "parse " + name) - }) - t.end() -}) - -tap.test("encoding", function (t) { - Object.keys(headers).forEach(function (name) { - var h = headers[name] - , expect = new Buffer(h[0], "hex") - , encoded = TarHeader.encode(h[1]) - - // might have slightly different bytes, since the standard - // isn't very strict, but should have the same semantics - // checkSum will be different, but cksumValid will be true - - var th = new TarHeader(encoded) - delete h[1].block - delete h[1].needExtended - delete h[1].cksum - t.has(th, h[1], "fields "+name) - }) - t.end() -}) - -// test these manually. they're a bit rare to find in the wild -tap.test("parseNumeric tests", function (t) { - var parseNumeric = TarHeader.parseNumeric - , numbers = - { "303737373737373700": 2097151 - , "30373737373737373737373700": 8589934591 - , "303030303036343400": 420 - , "800000ffffffffffff": 281474976710655 - , "ffffff000000000001": -281474976710654 - , "ffffff000000000000": -281474976710655 - , "800000000000200000": 2097152 - , "8000000000001544c5": 1393861 - , "ffffffffffff1544c5": -15383354 } - Object.keys(numbers).forEach(function (n) { - var b = new Buffer(n, "hex") - t.equal(parseNumeric(b), numbers[n], n + " === " + numbers[n]) - }) - t.end() -}) diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision.js b/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision.js deleted file mode 100644 index cb3e2d5e4edf8..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision.js +++ /dev/null @@ -1,39 +0,0 @@ -// Set the umask, so that it works the same everywhere. -process.umask(parseInt('22', 8)) - -var tap = require("tap") - , tar = require("../tar.js") - , fs = require("fs") - , path = require("path") - , file = path.resolve(__dirname, "link-file-entry-collision/bad-link.tar") - , target = path.resolve(__dirname, "tmp/link-file-entry-collision") - , index = 0 - , fstream = require("fstream") - , mkdirp = require("mkdirp") - , rimraf = require("rimraf") - -tap.test("preclean", function (t) { - rimraf.sync(target) - t.pass("cleaned!") - t.end() -}) - -tap.test("extract test", function (t) { - var extract = tar.Extract(target) - var inp = fs.createReadStream(file) - inp.pipe(extract) - - extract.on("end", function () { - t.equal(fs.readFileSync(target + "/bad-link-target", "utf8"), - "this should remain the same\n") - t.equal(fs.readFileSync(target + "/a.txt", "utf8"), - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - t.end() - }) -}) - -tap.test("cleanup", function (t) { - rimraf.sync(target) - t.pass("cleaned!") - t.end() -}) diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.hex b/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.hex deleted file mode 100644 index 99f5db0db0248..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.hex +++ /dev/null @@ -1,25 +0,0 @@ --- header for the link target -- -6261642d6c696e6b2d74617267657400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030303037363520003030303032342000303030303030303030333420313334363636353530353620303134333731002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # bad-link-target.....................................................................................000644..000765..000024..00000000034.13466655056.014371..0................................................................................................... -00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... - --- link target file contents (should not be overwritten) -- -746869732073686f756c642072656d61696e207468652073616d650a000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # this.should.remain.the.same..................................................................................................................................................................................................................................... -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # ................................................................................................................................................................................................................................................................ - --- header for the link named a.txt -- -612e74787400000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003030303634342000303030373635200030303030323420003030303030303030303030203133343636363535303536203031353334320020316261642d6c696e6b2d746172676574000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # a.txt...............................................................................................000644..000765..000024..00000000000.13466655056.015342..1bad-link-target.................................................................................... -00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... - --- header for file entry which attempts to overwrite the link -- -612e7478740000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000303030363434200030353737363120003030303032342000303030303030303034303120313136353133363033333320303132343531002030000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # a.txt...............................................................................................000644..057761..000024..00000000401.11651360333.012451..0................................................................................................... -00757374617200303069736161637300000000000000000000000000000000000000000000000000007374616666000000000000000000000000000000000000000000000000000000303030303030200030303030303020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # .ustar.00isaacs..........................staff...........................000000..000000......................................................................................................................................................................... - --- contents that threaten to overwrite the link target -- -61616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161 # aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa -61000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # a............................................................................................................................................................................................................................................................... - --- tar eof -- -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # ................................................................................................................................................................................................................................................................ -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # ................................................................................................................................................................................................................................................................ -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # ................................................................................................................................................................................................................................................................ -00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 # ................................................................................................................................................................................................................................................................ diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.tar b/node_modules/npm-lifecycle/node_modules/tar/test/link-file-entry-collision/bad-link.tar deleted file mode 100644 index be0b0d2f73a2cdca26771554090aca269bfcfc69..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 3584 zcmeHH+X{m)4E1?mksoj*wvFFYr%stVuod?C3-dvyu%}f7o0r^5I638{uw~k{!z1-} zyjMO6VTj0DLn1zB^YNI?xs=3|22z@tjX}eJq*YD{UmvH zFX<+lH<_11giZgT1>dv|T=Sf|62_{x?Et>1z}ddK929bd^+yKm)xW~1egP@c_^p4@ z%eVfG(pdsj>~Ne;uK!*C-{d*d_Wo-mAYwy`Q7I+&Khq}O|3yFnBYSoW$ZZ@Q8Hfx- I29C_Y8xFy>h5!Hn diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/pack-no-proprietary.js b/node_modules/npm-lifecycle/node_modules/tar/test/pack-no-proprietary.js deleted file mode 100644 index d4b03a1fe936b..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/pack-no-proprietary.js +++ /dev/null @@ -1,886 +0,0 @@ -// This is exactly like test/pack.js, except that it's excluding -// any proprietary headers. -// -// This loses some information about the filesystem, but creates -// tarballs that are supported by more versions of tar, especially -// old non-spec-compliant copies of gnutar. - -// the symlink file is excluded from git, because it makes -// windows freak the hell out. -var fs = require("fs") - , path = require("path") - , symlink = path.resolve(__dirname, "fixtures/symlink") -try { fs.unlinkSync(symlink) } catch (e) {} -fs.symlinkSync("./hardlink-1", symlink) -process.on("exit", function () { - fs.unlinkSync(symlink) -}) - -var tap = require("tap") - , tar = require("../tar.js") - , pkg = require("../package.json") - , Pack = tar.Pack - , fstream = require("fstream") - , Reader = fstream.Reader - , Writer = fstream.Writer - , input = path.resolve(__dirname, "fixtures/") - , target = path.resolve(__dirname, "tmp/pack.tar") - , uid = process.getuid ? process.getuid() : 0 - , gid = process.getgid ? process.getgid() : 0 - - , entries = - - // the global header and root fixtures/ dir are going to get - // a different date each time, so omit that bit. - // Also, dev/ino values differ across machines, so that's not - // included. - [ [ 'entry', - { path: 'fixtures/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'extendedHeader', - { path: 'PaxHeader/fixtures/200cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: 420, - uid: uid, - gid: gid, - type: 'x', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' }, - { path: 'fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - uid: uid, - gid: gid, - size: 200 } ] - - , [ 'entry', - { path: 'fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: 420, - uid: uid, - gid: gid, - size: 200, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/a.txt', - mode: 420, - uid: uid, - gid: gid, - size: 257, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/b.txt', - mode: 420, - uid: uid, - gid: gid, - size: 512, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/c.txt', - mode: 420, - uid: uid, - gid: gid, - size: 513, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/cc.txt', - mode: 420, - uid: uid, - gid: gid, - size: 513, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/dir/', - mode: 488, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/dir/sub/', - mode: 488, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/foo.js', - mode: 420, - uid: uid, - gid: gid, - size: 4, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/hardlink-1', - mode: 420, - uid: uid, - gid: gid, - size: 200, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/hardlink-2', - mode: 420, - uid: uid, - gid: gid, - size: 0, - type: '1', - linkpath: 'fixtures/hardlink-1', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/omega.txt', - mode: 420, - uid: uid, - gid: gid, - size: 2, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/packtest/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/packtest/omega.txt', - mode: 420, - uid: uid, - gid: gid, - size: 2, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/packtest/star.4.html', - mode: 420, - uid: uid, - gid: gid, - size: 54081, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'extendedHeader', - { path: 'PaxHeader/fixtures/packtest/Ω.txt', - mode: 420, - uid: uid, - gid: gid, - type: 'x', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' }, - { path: 'fixtures/packtest/Ω.txt', - uid: uid, - gid: gid, - size: 2 } ] - - , [ 'entry', - { path: 'fixtures/packtest/Ω.txt', - mode: 420, - uid: uid, - gid: gid, - size: 2, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: 420, - uid: uid, - gid: gid, - size: 100, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/symlink', - uid: uid, - gid: gid, - size: 0, - type: '2', - linkpath: 'hardlink-1', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'extendedHeader', - { path: 'PaxHeader/fixtures/Ω.txt', - mode: 420, - uid: uid, - gid: gid, - type: 'x', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' }, - { path: "fixtures/Ω.txt" - , uid: uid - , gid: gid - , size: 2 } ] - - , [ 'entry', - { path: 'fixtures/Ω.txt', - mode: 420, - uid: uid, - gid: gid, - size: 2, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - ] - - -// first, make sure that the hardlinks are actually hardlinks, or this -// won't work. Git has a way of replacing them with a copy. -var hard1 = path.resolve(__dirname, "fixtures/hardlink-1") - , hard2 = path.resolve(__dirname, "fixtures/hardlink-2") - , fs = require("fs") - -try { fs.unlinkSync(hard2) } catch (e) {} -fs.linkSync(hard1, hard2) - -tap.test("with global header", { timeout: 10000 }, function (t) { - runTest(t, true) -}) - -tap.test("without global header", { timeout: 10000 }, function (t) { - runTest(t, false) -}) - -function alphasort (a, b) { - return a === b ? 0 - : a.toLowerCase() > b.toLowerCase() ? 1 - : a.toLowerCase() < b.toLowerCase() ? -1 - : a > b ? 1 - : -1 -} - - -function runTest (t, doGH) { - var reader = Reader({ path: input - , filter: function () { - return !this.path.match(/\.(tar|hex)$/) - } - , sort: alphasort - }) - - var props = doGH ? pkg : {} - props.noProprietary = true - var pack = Pack(props) - var writer = Writer(target) - - // global header should be skipped regardless, since it has no content. - var entry = 0 - - t.ok(reader, "reader ok") - t.ok(pack, "pack ok") - t.ok(writer, "writer ok") - - pack.pipe(writer) - - var parse = tar.Parse() - t.ok(parse, "parser should be ok") - - pack.on("data", function (c) { - // console.error("PACK DATA") - if (c.length !== 512) { - // this one is too noisy, only assert if it'll be relevant - t.equal(c.length, 512, "parser should emit data in 512byte blocks") - } - parse.write(c) - }) - - pack.on("end", function () { - // console.error("PACK END") - t.pass("parser ends") - parse.end() - }) - - pack.on("error", function (er) { - t.fail("pack error", er) - }) - - parse.on("error", function (er) { - t.fail("parse error", er) - }) - - writer.on("error", function (er) { - t.fail("writer error", er) - }) - - reader.on("error", function (er) { - t.fail("reader error", er) - }) - - parse.on("*", function (ev, e) { - var wanted = entries[entry++] - if (!wanted) { - t.fail("unexpected event: "+ev) - return - } - t.equal(ev, wanted[0], "event type should be "+wanted[0]) - - if (ev !== wanted[0] || e.path !== wanted[1].path) { - console.error("wanted", wanted) - console.error([ev, e.props]) - e.on("end", function () { - console.error(e.fields) - throw "break" - }) - } - - t.has(e.props, wanted[1], "properties "+wanted[1].path) - if (wanted[2]) { - e.on("end", function () { - if (!e.fields) { - t.ok(e.fields, "should get fields") - } else { - t.has(e.fields, wanted[2], "should get expected fields") - } - }) - } - }) - - reader.pipe(pack) - - writer.on("close", function () { - t.equal(entry, entries.length, "should get all expected entries") - t.pass("it finished") - t.end() - }) - -} diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/pack.js b/node_modules/npm-lifecycle/node_modules/tar/test/pack.js deleted file mode 100644 index 0f16c07bb0162..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/pack.js +++ /dev/null @@ -1,952 +0,0 @@ - -// the symlink file is excluded from git, because it makes -// windows freak the hell out. -var fs = require("fs") - , path = require("path") - , symlink = path.resolve(__dirname, "fixtures/symlink") -try { fs.unlinkSync(symlink) } catch (e) {} -fs.symlinkSync("./hardlink-1", symlink) -process.on("exit", function () { - fs.unlinkSync(symlink) -}) - - -var tap = require("tap") - , tar = require("../tar.js") - , pkg = require("../package.json") - , Pack = tar.Pack - , fstream = require("fstream") - , Reader = fstream.Reader - , Writer = fstream.Writer - , input = path.resolve(__dirname, "fixtures/") - , target = path.resolve(__dirname, "tmp/pack.tar") - , uid = process.getuid ? process.getuid() : 0 - , gid = process.getgid ? process.getgid() : 0 - - , entries = - - // the global header and root fixtures/ dir are going to get - // a different date each time, so omit that bit. - // Also, dev/ino values differ across machines, so that's not - // included. - [ [ 'globalExtendedHeader', - { path: 'PaxHeader/', - mode: 438, - uid: 0, - gid: 0, - type: 'g', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' }, - { "NODETAR.author": pkg.author, - "NODETAR.name": pkg.name, - "NODETAR.description": pkg.description, - "NODETAR.version": pkg.version, - "NODETAR.repository.type": pkg.repository.type, - "NODETAR.repository.url": pkg.repository.url, - "NODETAR.main": pkg.main, - "NODETAR.scripts.test": pkg.scripts.test } ] - - , [ 'entry', - { path: 'fixtures/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'extendedHeader', - { path: 'PaxHeader/fixtures/200cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: 420, - uid: uid, - gid: gid, - type: 'x', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' }, - { path: 'fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - 'NODETAR.depth': '1', - 'NODETAR.type': 'File', - nlink: 1, - uid: uid, - gid: gid, - size: 200, - 'NODETAR.blksize': '4096', - 'NODETAR.blocks': '8' } ] - - , [ 'entry', - { path: 'fixtures/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: 420, - uid: uid, - gid: gid, - size: 200, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '', - 'NODETAR.depth': '1', - 'NODETAR.type': 'File', - nlink: 1, - 'NODETAR.blksize': '4096', - 'NODETAR.blocks': '8' } ] - - , [ 'entry', - { path: 'fixtures/a.txt', - mode: 420, - uid: uid, - gid: gid, - size: 257, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/b.txt', - mode: 420, - uid: uid, - gid: gid, - size: 512, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/c.txt', - mode: 420, - uid: uid, - gid: gid, - size: 513, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/cc.txt', - mode: 420, - uid: uid, - gid: gid, - size: 513, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/dir/', - mode: 488, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/dir/sub/', - mode: 488, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - - , [ 'entry', - { path: 'fixtures/foo.js', - mode: 420, - uid: uid, - gid: gid, - size: 4, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/hardlink-1', - mode: 420, - uid: uid, - gid: gid, - size: 200, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/hardlink-2', - mode: 420, - uid: uid, - gid: gid, - size: 0, - type: '1', - linkpath: 'fixtures/hardlink-1', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/omega.txt', - mode: 420, - uid: uid, - gid: gid, - size: 2, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/packtest/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/packtest/omega.txt', - mode: 420, - uid: uid, - gid: gid, - size: 2, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/packtest/star.4.html', - mode: 420, - uid: uid, - gid: gid, - size: 54081, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'extendedHeader', - { path: 'PaxHeader/fixtures/packtest/Ω.txt', - mode: 420, - uid: uid, - gid: gid, - type: 'x', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' }, - { path: 'fixtures/packtest/Ω.txt', - 'NODETAR.depth': '2', - 'NODETAR.type': 'File', - nlink: 1, - uid: uid, - gid: gid, - size: 2, - 'NODETAR.blksize': '4096', - 'NODETAR.blocks': '8' } ] - - , [ 'entry', - { path: 'fixtures/packtest/Ω.txt', - mode: 420, - uid: uid, - gid: gid, - size: 2, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '', - 'NODETAR.depth': '2', - 'NODETAR.type': 'File', - nlink: 1, - 'NODETAR.blksize': '4096', - 'NODETAR.blocks': '8' } ] - - , [ 'entry', - { path: 'fixtures/r/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/', - mode: 493, - uid: uid, - gid: gid, - size: 0, - type: '5', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: 420, - uid: uid, - gid: gid, - size: 100, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'entry', - { path: 'fixtures/symlink', - uid: uid, - gid: gid, - size: 0, - type: '2', - linkpath: 'hardlink-1', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' } ] - - , [ 'extendedHeader', - { path: 'PaxHeader/fixtures/Ω.txt', - mode: 420, - uid: uid, - gid: gid, - type: 'x', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '' }, - { path: "fixtures/Ω.txt" - , "NODETAR.depth": "1" - , "NODETAR.type": "File" - , nlink: 1 - , uid: uid - , gid: gid - , size: 2 - , "NODETAR.blksize": "4096" - , "NODETAR.blocks": "8" } ] - - , [ 'entry', - { path: 'fixtures/Ω.txt', - mode: 420, - uid: uid, - gid: gid, - size: 2, - type: '0', - linkpath: '', - ustar: 'ustar\u0000', - ustarver: '00', - uname: '', - gname: '', - devmaj: 0, - devmin: 0, - fill: '', - 'NODETAR.depth': '1', - 'NODETAR.type': 'File', - nlink: 1, - 'NODETAR.blksize': '4096', - 'NODETAR.blocks': '8' } ] - ] - - -// first, make sure that the hardlinks are actually hardlinks, or this -// won't work. Git has a way of replacing them with a copy. -var hard1 = path.resolve(__dirname, "fixtures/hardlink-1") - , hard2 = path.resolve(__dirname, "fixtures/hardlink-2") - , fs = require("fs") - -try { fs.unlinkSync(hard2) } catch (e) {} -fs.linkSync(hard1, hard2) - -tap.test("with global header", { timeout: 10000 }, function (t) { - runTest(t, true) -}) - -tap.test("without global header", { timeout: 10000 }, function (t) { - runTest(t, false) -}) - -tap.test("with from base", { timeout: 10000 }, function (t) { - runTest(t, true, true) -}) - -function alphasort (a, b) { - return a === b ? 0 - : a.toLowerCase() > b.toLowerCase() ? 1 - : a.toLowerCase() < b.toLowerCase() ? -1 - : a > b ? 1 - : -1 -} - - -function runTest (t, doGH, doFromBase) { - var reader = Reader({ path: input - , filter: function () { - return !this.path.match(/\.(tar|hex)$/) - } - , sort: alphasort - }) - - var props = doGH ? pkg : {} - if(doFromBase) props.fromBase = true; - - var pack = Pack(props) - var writer = Writer(target) - - // skip the global header if we're not doing that. - var entry = doGH ? 0 : 1 - - t.ok(reader, "reader ok") - t.ok(pack, "pack ok") - t.ok(writer, "writer ok") - - pack.pipe(writer) - - var parse = tar.Parse() - t.ok(parse, "parser should be ok") - - pack.on("data", function (c) { - // console.error("PACK DATA") - if (c.length !== 512) { - // this one is too noisy, only assert if it'll be relevant - t.equal(c.length, 512, "parser should emit data in 512byte blocks") - } - parse.write(c) - }) - - pack.on("end", function () { - // console.error("PACK END") - t.pass("parser ends") - parse.end() - }) - - pack.on("error", function (er) { - t.fail("pack error", er) - }) - - parse.on("error", function (er) { - t.fail("parse error", er) - }) - - writer.on("error", function (er) { - t.fail("writer error", er) - }) - - reader.on("error", function (er) { - t.fail("reader error", er) - }) - - parse.on("*", function (ev, e) { - var wanted = entries[entry++] - if (!wanted) { - t.fail("unexpected event: "+ev) - return - } - t.equal(ev, wanted[0], "event type should be "+wanted[0]) - - if(doFromBase) { - if(wanted[1].path.indexOf('fixtures/') && wanted[1].path.length == 100) - wanted[1].path = wanted[1].path.replace('fixtures/', '') + 'ccccccccc' - - if(wanted[1]) wanted[1].path = wanted[1].path.replace('fixtures/', '').replace('//', '/') - if(wanted[1].path == '') wanted[1].path = '/' - if(wanted[2] && wanted[2].path) wanted[2].path = wanted[2].path.replace('fixtures', '').replace(/^\//, '') - - wanted[1].linkpath = wanted[1].linkpath.replace('fixtures/', '') - } - - if (ev !== wanted[0] || e.path !== wanted[1].path) { - console.error("wanted", wanted) - console.error([ev, e.props]) - e.on("end", function () { - console.error(e.fields) - throw "break" - }) - } - - - t.has(e.props, wanted[1], "properties "+wanted[1].path) - if (wanted[2]) { - e.on("end", function () { - if (!e.fields) { - t.ok(e.fields, "should get fields") - } else { - t.has(e.fields, wanted[2], "should get expected fields") - } - }) - } - }) - - reader.pipe(pack) - - writer.on("close", function () { - t.equal(entry, entries.length, "should get all expected entries") - t.pass("it finished") - t.end() - }) - -} diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/parse-discard.js b/node_modules/npm-lifecycle/node_modules/tar/test/parse-discard.js deleted file mode 100644 index da01a65ccc7d7..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/parse-discard.js +++ /dev/null @@ -1,29 +0,0 @@ -var tap = require("tap") - , tar = require("../tar.js") - , fs = require("fs") - , path = require("path") - , file = path.resolve(__dirname, "fixtures/c.tar") - -tap.test("parser test", function (t) { - var parser = tar.Parse() - var total = 0 - var dataTotal = 0 - - parser.on("end", function () { - - t.equals(total-513,dataTotal,'should have discarded only c.txt') - - t.end() - }) - - fs.createReadStream(file) - .pipe(parser) - .on('entry',function(entry){ - if(entry.path === 'c.txt') entry.abort() - - total += entry.size; - entry.on('data',function(data){ - dataTotal += data.length - }) - }) -}) diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/parse.js b/node_modules/npm-lifecycle/node_modules/tar/test/parse.js deleted file mode 100644 index f765a50129bff..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/parse.js +++ /dev/null @@ -1,359 +0,0 @@ -var tap = require("tap") - , tar = require("../tar.js") - , fs = require("fs") - , path = require("path") - , file = path.resolve(__dirname, "fixtures/c.tar") - , index = 0 - - , expect = -[ [ 'entry', - { path: 'c.txt', - mode: 420, - uid: 24561, - gid: 20, - size: 513, - mtime: new Date('Wed, 26 Oct 2011 01:10:58 GMT'), - cksum: 5422, - type: '0', - linkpath: '', - ustar: 'ustar\0', - ustarver: '00', - uname: 'isaacs', - gname: 'staff', - devmaj: 0, - devmin: 0, - fill: '' }, - undefined ], - [ 'entry', - { path: 'cc.txt', - mode: 420, - uid: 24561, - gid: 20, - size: 513, - mtime: new Date('Wed, 26 Oct 2011 01:11:02 GMT'), - cksum: 5525, - type: '0', - linkpath: '', - ustar: 'ustar\0', - ustarver: '00', - uname: 'isaacs', - gname: 'staff', - devmaj: 0, - devmin: 0, - fill: '' }, - undefined ], - [ 'entry', - { path: 'r/e/a/l/l/y/-/d/e/e/p/-/f/o/l/d/e/r/-/p/a/t/h/cccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: 420, - uid: 24561, - gid: 20, - size: 100, - mtime: new Date('Thu, 27 Oct 2011 03:43:23 GMT'), - cksum: 18124, - type: '0', - linkpath: '', - ustar: 'ustar\0', - ustarver: '00', - uname: 'isaacs', - gname: 'staff', - devmaj: 0, - devmin: 0, - fill: '' }, - undefined ], - [ 'entry', - { path: 'Ω.txt', - mode: 420, - uid: 24561, - gid: 20, - size: 2, - mtime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'), - cksum: 5695, - type: '0', - linkpath: '', - ustar: 'ustar\0', - ustarver: '00', - uname: 'isaacs', - gname: 'staff', - devmaj: 0, - devmin: 0, - fill: '' }, - undefined ], - [ 'extendedHeader', - { path: 'PaxHeader/Ω.txt', - mode: 420, - uid: 24561, - gid: 20, - size: 120, - mtime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'), - cksum: 6702, - type: 'x', - linkpath: '', - ustar: 'ustar\0', - ustarver: '00', - uname: 'isaacs', - gname: 'staff', - devmaj: 0, - devmin: 0, - fill: '' }, - { path: 'Ω.txt', - ctime: 1319737909, - atime: 1319739061, - dev: 234881026, - ino: 51693379, - nlink: 1 } ], - [ 'entry', - { path: 'Ω.txt', - mode: 420, - uid: 24561, - gid: 20, - size: 2, - mtime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'), - cksum: 5695, - type: '0', - linkpath: '', - ustar: 'ustar\0', - ustarver: '00', - uname: 'isaacs', - gname: 'staff', - devmaj: 0, - devmin: 0, - fill: '', - ctime: new Date('Thu, 27 Oct 2011 17:51:49 GMT'), - atime: new Date('Thu, 27 Oct 2011 18:11:01 GMT'), - dev: 234881026, - ino: 51693379, - nlink: 1 }, - undefined ], - [ 'extendedHeader', - { path: 'PaxHeader/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: 420, - uid: 24561, - gid: 20, - size: 353, - mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), - cksum: 14488, - type: 'x', - linkpath: '', - ustar: 'ustar\0', - ustarver: '00', - uname: 'isaacs', - gname: 'staff', - devmaj: 0, - devmin: 0, - fill: '' }, - { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - ctime: 1319686868, - atime: 1319741254, - 'LIBARCHIVE.creationtime': '1319686852', - dev: 234881026, - ino: 51681874, - nlink: 1 } ], - [ 'entry', - { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: 420, - uid: 24561, - gid: 20, - size: 200, - mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), - cksum: 14570, - type: '0', - linkpath: '', - ustar: 'ustar\0', - ustarver: '00', - uname: 'isaacs', - gname: 'staff', - devmaj: 0, - devmin: 0, - fill: '', - ctime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), - atime: new Date('Thu, 27 Oct 2011 18:47:34 GMT'), - 'LIBARCHIVE.creationtime': '1319686852', - dev: 234881026, - ino: 51681874, - nlink: 1 }, - undefined ], - [ 'longPath', - { path: '././@LongLink', - mode: 0, - uid: 0, - gid: 0, - size: 201, - mtime: new Date('Thu, 01 Jan 1970 00:00:00 GMT'), - cksum: 4976, - type: 'L', - linkpath: '', - ustar: false }, - '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' ], - [ 'entry', - { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: 420, - uid: 1000, - gid: 1000, - size: 201, - mtime: new Date('Thu, 27 Oct 2011 22:21:50 GMT'), - cksum: 14086, - type: '0', - linkpath: '', - ustar: false }, - undefined ], - [ 'longLinkpath', - { path: '././@LongLink', - mode: 0, - uid: 0, - gid: 0, - size: 201, - mtime: new Date('Thu, 01 Jan 1970 00:00:00 GMT'), - cksum: 4975, - type: 'K', - linkpath: '', - ustar: false }, - '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc' ], - [ 'longPath', - { path: '././@LongLink', - mode: 0, - uid: 0, - gid: 0, - size: 201, - mtime: new Date('Thu, 01 Jan 1970 00:00:00 GMT'), - cksum: 4976, - type: 'L', - linkpath: '', - ustar: false }, - '200LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL' ], - [ 'entry', - { path: '200LLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLLL', - mode: 511, - uid: 1000, - gid: 1000, - size: 0, - mtime: new Date('Fri, 28 Oct 2011 23:05:17 GMT'), - cksum: 21603, - type: '2', - linkpath: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - ustar: false }, - undefined ], - [ 'extendedHeader', - { path: 'PaxHeader/200-hard', - mode: 420, - uid: 24561, - gid: 20, - size: 143, - mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), - cksum: 6533, - type: 'x', - linkpath: '', - ustar: 'ustar\0', - ustarver: '00', - uname: 'isaacs', - gname: 'staff', - devmaj: 0, - devmin: 0, - fill: '' }, - { ctime: 1320617144, - atime: 1320617232, - 'LIBARCHIVE.creationtime': '1319686852', - dev: 234881026, - ino: 51681874, - nlink: 2 } ], - [ 'entry', - { path: '200-hard', - mode: 420, - uid: 24561, - gid: 20, - size: 200, - mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), - cksum: 5526, - type: '0', - linkpath: '', - ustar: 'ustar\0', - ustarver: '00', - uname: 'isaacs', - gname: 'staff', - devmaj: 0, - devmin: 0, - fill: '', - ctime: new Date('Sun, 06 Nov 2011 22:05:44 GMT'), - atime: new Date('Sun, 06 Nov 2011 22:07:12 GMT'), - 'LIBARCHIVE.creationtime': '1319686852', - dev: 234881026, - ino: 51681874, - nlink: 2 }, - undefined ], - [ 'extendedHeader', - { path: 'PaxHeader/200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: 420, - uid: 24561, - gid: 20, - size: 353, - mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), - cksum: 14488, - type: 'x', - linkpath: '', - ustar: 'ustar\0', - ustarver: '00', - uname: 'isaacs', - gname: 'staff', - devmaj: 0, - devmin: 0, - fill: '' }, - { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - ctime: 1320617144, - atime: 1320617406, - 'LIBARCHIVE.creationtime': '1319686852', - dev: 234881026, - ino: 51681874, - nlink: 2 } ], - [ 'entry', - { path: '200ccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccc', - mode: 420, - uid: 24561, - gid: 20, - size: 0, - mtime: new Date('Thu, 27 Oct 2011 03:41:08 GMT'), - cksum: 15173, - type: '1', - linkpath: '200-hard', - ustar: 'ustar\0', - ustarver: '00', - uname: 'isaacs', - gname: 'staff', - devmaj: 0, - devmin: 0, - fill: '', - ctime: new Date('Sun, 06 Nov 2011 22:05:44 GMT'), - atime: new Date('Sun, 06 Nov 2011 22:10:06 GMT'), - 'LIBARCHIVE.creationtime': '1319686852', - dev: 234881026, - ino: 51681874, - nlink: 2 }, - undefined ] ] - - -tap.test("parser test", function (t) { - var parser = tar.Parse() - - parser.on("end", function () { - t.equal(index, expect.length, "saw all expected events") - t.end() - }) - - fs.createReadStream(file) - .pipe(parser) - .on("*", function (ev, entry) { - var wanted = expect[index] - if (!wanted) { - return t.fail("Unexpected event: " + ev) - } - var result = [ev, entry.props] - entry.on("end", function () { - result.push(entry.fields || entry.body) - - t.equal(ev, wanted[0], index + " event type") - t.equivalent(entry.props, wanted[1], wanted[1].path + " entry properties") - if (wanted[2]) { - t.equivalent(result[2], wanted[2], "metadata values") - } - index ++ - }) - }) -}) diff --git a/node_modules/npm-lifecycle/node_modules/tar/test/zz-cleanup.js b/node_modules/npm-lifecycle/node_modules/tar/test/zz-cleanup.js deleted file mode 100644 index a00ff7faa0390..0000000000000 --- a/node_modules/npm-lifecycle/node_modules/tar/test/zz-cleanup.js +++ /dev/null @@ -1,20 +0,0 @@ -// clean up the fixtures - -var tap = require("tap") -, rimraf = require("rimraf") -, test = tap.test -, path = require("path") - -test("clean fixtures", function (t) { - rimraf(path.resolve(__dirname, "fixtures"), function (er) { - t.ifError(er, "rimraf ./fixtures/") - t.end() - }) -}) - -test("clean tmp", function (t) { - rimraf(path.resolve(__dirname, "tmp"), function (er) { - t.ifError(er, "rimraf ./tmp/") - t.end() - }) -}) diff --git a/node_modules/npm-lifecycle/package.json b/node_modules/npm-lifecycle/package.json index 6f63b06fd51c4..33f94a99cfecd 100644 --- a/node_modules/npm-lifecycle/package.json +++ b/node_modules/npm-lifecycle/package.json @@ -1,29 +1,30 @@ { - "_from": "npm-lifecycle@2.1.0", - "_id": "npm-lifecycle@2.1.0", + "_from": "npm-lifecycle@2.1.1", + "_id": "npm-lifecycle@2.1.1", "_inBundle": false, - "_integrity": "sha512-QbBfLlGBKsktwBZLj6AviHC6Q9Y3R/AY4a2PYSIRhSKSS0/CxRyD/PfxEX6tPeOCXQgMSNdwGeECacstgptc+g==", + "_integrity": "sha512-+Vg6I60Z75V/09pdcH5iUo/99Q/vop35PaI99elvxk56azSVVsdsSsS/sXqKDNwbRRNN1qSxkcO45ZOu0yOWew==", "_location": "/npm-lifecycle", "_phantomChildren": {}, "_requested": { "type": "version", "registry": true, - "raw": "npm-lifecycle@2.1.0", + "raw": "npm-lifecycle@2.1.1", "name": "npm-lifecycle", "escapedName": "npm-lifecycle", - "rawSpec": "2.1.0", + "rawSpec": "2.1.1", "saveSpec": null, - "fetchSpec": "2.1.0" + "fetchSpec": "2.1.1" }, "_requiredBy": [ "#USER", "/", - "/libcipm" + "/libcipm", + "/libnpm" ], - "_resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-2.1.0.tgz", - "_shasum": "1eda2eedb82db929e3a0c50341ab0aad140ed569", - "_spec": "npm-lifecycle@2.1.0", - "_where": "/Users/zkat/Documents/code/work/npm", + "_resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-2.1.1.tgz", + "_shasum": "0027c09646f0fd346c5c93377bdaba59c6748fdf", + "_spec": "npm-lifecycle@2.1.1", + "_where": "/home/hugh/Development/github.com/npm/cli", "author": { "name": "Mike Sherov" }, @@ -33,8 +34,8 @@ "bundleDependencies": false, "dependencies": { "byline": "^5.0.0", - "graceful-fs": "^4.1.11", - "node-gyp": "^3.8.0", + "graceful-fs": "^4.1.15", + "node-gyp": "^4.0.0", "resolve-from": "^4.0.0", "slide": "^1.1.6", "uid-number": "0.0.6", @@ -44,11 +45,11 @@ "deprecated": false, "description": "JavaScript package lifecycle hook runner", "devDependencies": { - "nyc": "^12.0.2", - "sinon": "^6.1.5", - "standard": "^11.0.1", + "nyc": "^14.1.0", + "sinon": "^7.2.3", + "standard": "^12.0.1", "standard-version": "^4.4.0", - "tap": "^12.0.1", + "tap": "^13.1.3", "weallbehave": "^1.2.0", "weallcontribute": "^1.0.8" }, @@ -76,9 +77,9 @@ "prerelease": "npm t", "pretest": "standard", "release": "standard-version -s", - "test": "tap -J --coverage test/*.js", + "test": "tap", "update-coc": "weallbehave -o . && git add CODE_OF_CONDUCT.md && git commit -m 'docs(coc): updated CODE_OF_CONDUCT.md'", "update-contrib": "weallcontribute -o . && git add CONTRIBUTING.md && git commit -m 'docs(contributing): updated CONTRIBUTING.md'" }, - "version": "2.1.0" + "version": "2.1.1" } diff --git a/package-lock.json b/package-lock.json index b10cf726fe9b2..47149c703b7c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -497,14 +497,6 @@ } } }, - "block-stream": { - "version": "0.0.9", - "resolved": "https://registry.npmjs.org/block-stream/-/block-stream-0.0.9.tgz", - "integrity": "sha1-E+v+d4oDIFz+A3UUgeu0szAMEmo=", - "requires": { - "inherits": "~2.0.0" - } - }, "bluebird": { "version": "3.5.3", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.3.tgz", @@ -2006,17 +1998,6 @@ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, - "fstream": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/fstream/-/fstream-1.0.12.tgz", - "integrity": "sha512-WvJ193OHa0GHPEL+AycEJgxvBEwyfRkN1vhjca23OaPVMCaLCXTd5qAu82AjTcgP1UJmytkOKb63Ypde7raDIg==", - "requires": { - "graceful-fs": "^4.1.2", - "inherits": "~2.0.0", - "mkdirp": ">=0.5 0", - "rimraf": "2" - } - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -3439,62 +3420,18 @@ "dev": true }, "npm-lifecycle": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-2.1.0.tgz", - "integrity": "sha512-QbBfLlGBKsktwBZLj6AviHC6Q9Y3R/AY4a2PYSIRhSKSS0/CxRyD/PfxEX6tPeOCXQgMSNdwGeECacstgptc+g==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/npm-lifecycle/-/npm-lifecycle-2.1.1.tgz", + "integrity": "sha512-+Vg6I60Z75V/09pdcH5iUo/99Q/vop35PaI99elvxk56azSVVsdsSsS/sXqKDNwbRRNN1qSxkcO45ZOu0yOWew==", "requires": { "byline": "^5.0.0", - "graceful-fs": "^4.1.11", - "node-gyp": "^3.8.0", + "graceful-fs": "^4.1.15", + "node-gyp": "^4.0.0", "resolve-from": "^4.0.0", "slide": "^1.1.6", "uid-number": "0.0.6", "umask": "^1.1.0", "which": "^1.3.1" - }, - "dependencies": { - "node-gyp": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-3.8.0.tgz", - "integrity": "sha512-3g8lYefrRRzvGeSowdJKAKyks8oUpLEd/DyPV4eMhVlhJ0aNaZqIrNUIPuEWWTAoPqyFkfGrM67MC69baqn6vA==", - "requires": { - "fstream": "^1.0.0", - "glob": "^7.0.3", - "graceful-fs": "^4.1.2", - "mkdirp": "^0.5.0", - "nopt": "2 || 3", - "npmlog": "0 || 1 || 2 || 3 || 4", - "osenv": "0", - "request": "^2.87.0", - "rimraf": "2", - "semver": "~5.3.0", - "tar": "^2.0.0", - "which": "1" - } - }, - "nopt": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/nopt/-/nopt-3.0.6.tgz", - "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", - "requires": { - "abbrev": "1" - } - }, - "semver": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.3.0.tgz", - "integrity": "sha1-myzl094C0XxgEq0yaqa00M9U+U8=" - }, - "tar": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/tar/-/tar-2.2.2.tgz", - "integrity": "sha512-FCEhQ/4rE1zYv9rYXJw/msRqsnmlje5jHP6huWeBZ704jUTy02c5AZyWujpMR1ax6mVw9NyJMfuK2CMDWVIfgA==", - "requires": { - "block-stream": "*", - "fstream": "^1.0.12", - "inherits": "2" - } - } } }, "npm-logical-tree": { diff --git a/package.json b/package.json index 5a097a1dae6be..80f73488b9a9c 100644 --- a/package.json +++ b/package.json @@ -94,7 +94,7 @@ "npm-audit-report": "^1.3.2", "npm-cache-filename": "~1.0.2", "npm-install-checks": "~3.0.0", - "npm-lifecycle": "^2.1.0", + "npm-lifecycle": "^2.1.1", "npm-package-arg": "^6.1.0", "npm-packlist": "^1.4.1", "npm-pick-manifest": "^2.2.3",
  • <&zGX%Xg&wY1tmYh19!l8}$B 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ξ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%0A`g-r| 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