libv8 5.7.492.65.1 → 5.9.211.38.0beta0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (297) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.travis.yml +8 -2
  4. data/CHANGELOG.md +4 -0
  5. data/README.md +4 -3
  6. data/Rakefile +27 -10
  7. data/ext/libv8/builder.rb +4 -0
  8. data/lib/libv8/version.rb +1 -1
  9. data/libv8.gemspec +1 -1
  10. data/patches/0001-Build-a-standalone-static-library.patch +5 -5
  11. data/patches/0002-Don-t-compile-unnecessary-stuff.patch +20 -24
  12. data/patches/0003-Use-the-fPIC-flag-for-the-static-library.patch +5 -5
  13. data/patches/0004-Do-not-embed-debug-symbols-in-macOS-libraries.patch +5 -5
  14. data/patches/0005-Fix-GCC-7-build-errors.patch +147 -0
  15. data/scaleway.png +0 -0
  16. data/vendor/depot_tools/.gitattributes +52 -0
  17. data/vendor/depot_tools/.gitignore +10 -0
  18. data/vendor/depot_tools/README.md +7 -3
  19. data/vendor/depot_tools/apply_issue.bat +4 -3
  20. data/vendor/depot_tools/apply_issue.py +0 -10
  21. data/vendor/depot_tools/autoninja +12 -0
  22. data/vendor/depot_tools/autoninja.bat +9 -0
  23. data/vendor/depot_tools/autoninja.py +70 -0
  24. data/vendor/depot_tools/bootstrap/win/README.md +108 -26
  25. data/vendor/depot_tools/bootstrap/win/git-bash.template.sh +3 -3
  26. data/vendor/depot_tools/bootstrap/win/git.template.bat +2 -2
  27. data/vendor/depot_tools/bootstrap/win/manifest.txt +18 -0
  28. data/vendor/depot_tools/bootstrap/win/manifest_bleeding_edge.txt +18 -0
  29. data/vendor/depot_tools/bootstrap/win/python27.new.bat +49 -0
  30. data/vendor/depot_tools/bootstrap/win/win_tools.bat +55 -59
  31. data/vendor/depot_tools/bootstrap/win/win_tools.py +335 -0
  32. data/vendor/depot_tools/cipd +16 -2
  33. data/vendor/depot_tools/cipd.bat +20 -2
  34. data/vendor/depot_tools/cipd.ps1 +36 -22
  35. data/vendor/depot_tools/cipd_bin_setup.bat +6 -0
  36. data/vendor/depot_tools/cipd_bin_setup.sh +10 -0
  37. data/vendor/depot_tools/cipd_client_version +1 -1
  38. data/vendor/depot_tools/cipd_manifest.txt +9 -0
  39. data/vendor/depot_tools/cit.bat +12 -11
  40. data/vendor/depot_tools/clang-format.bat +4 -3
  41. data/vendor/depot_tools/clang_format_merge_driver.bat +12 -11
  42. data/vendor/depot_tools/commit_queue.bat +4 -3
  43. data/vendor/depot_tools/cpplint.bat +9 -3
  44. data/vendor/depot_tools/cpplint.py +3 -3
  45. data/vendor/depot_tools/depot-tools-auth.bat +4 -3
  46. data/vendor/depot_tools/download_from_google_storage.bat +5 -3
  47. data/vendor/depot_tools/download_from_google_storage.py +6 -1
  48. data/vendor/depot_tools/fetch.bat +5 -4
  49. data/vendor/depot_tools/fetch.py +4 -5
  50. data/vendor/depot_tools/gclient-new-workdir.py +82 -46
  51. data/vendor/depot_tools/gclient.bat +5 -4
  52. data/vendor/depot_tools/gclient.py +713 -319
  53. data/vendor/depot_tools/gclient_eval.py +284 -0
  54. data/vendor/depot_tools/gclient_utils.py +70 -4
  55. data/vendor/depot_tools/gerrit_client.py +26 -1
  56. data/vendor/depot_tools/gerrit_util.py +120 -127
  57. data/vendor/depot_tools/git-crrev-parse +1 -0
  58. data/vendor/depot_tools/git-gs +1 -1
  59. data/vendor/depot_tools/git_cl.py +731 -415
  60. data/vendor/depot_tools/git_common.py +23 -3
  61. data/vendor/depot_tools/git_drover.py +10 -1
  62. data/vendor/depot_tools/git_footers.py +62 -22
  63. data/vendor/depot_tools/git_hyper_blame.py +3 -2
  64. data/vendor/depot_tools/git_map.py +30 -3
  65. data/vendor/depot_tools/git_map_branches.py +18 -4
  66. data/vendor/depot_tools/git_number.py +8 -2
  67. data/vendor/depot_tools/git_retry.py +21 -0
  68. data/vendor/depot_tools/gn.bat +4 -3
  69. data/vendor/depot_tools/infra/config/cq.cfg +1 -5
  70. data/vendor/depot_tools/infra/config/recipes.cfg +18 -16
  71. data/vendor/depot_tools/led +12 -0
  72. data/vendor/depot_tools/led.bat +7 -0
  73. data/vendor/depot_tools/man/html/git-cl.html +9 -1
  74. data/vendor/depot_tools/man/html/git-drover.html +22 -18
  75. data/vendor/depot_tools/man/man1/git-cl.1 +8 -3
  76. data/vendor/depot_tools/man/man1/git-drover.1 +22 -20
  77. data/vendor/depot_tools/man/src/git-cl.txt +3 -0
  78. data/vendor/depot_tools/man/src/git-drover.txt +8 -0
  79. data/vendor/depot_tools/my_activity.py +8 -5
  80. data/vendor/depot_tools/owners.py +103 -11
  81. data/vendor/depot_tools/owners_finder.py +14 -2
  82. data/vendor/depot_tools/presubmit_canned_checks.py +25 -67
  83. data/vendor/depot_tools/presubmit_support.py +87 -35
  84. data/vendor/depot_tools/recipes/OWNERS +2 -0
  85. data/vendor/depot_tools/recipes/README.recipes.md +842 -0
  86. data/vendor/depot_tools/recipes/recipe_modules/bot_update/__init__.py +5 -3
  87. data/vendor/depot_tools/recipes/recipe_modules/bot_update/api.py +181 -60
  88. data/vendor/depot_tools/recipes/recipe_modules/bot_update/{example.expected → examples/full.expected}/apply_gerrit_ref.json +4 -2
  89. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic.json +82 -0
  90. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic_with_branch_heads.json +149 -0
  91. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/buildbot.json +82 -0
  92. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/clobber.json +149 -0
  93. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/deprecated_got_revision_mapping.json +122 -0
  94. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/gerrit_no_rebase_patch_ref.json +149 -0
  95. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/gerrit_no_reset.json +149 -0
  96. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_shallow.json +149 -0
  97. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/reset_root_solution_revision.json +148 -0
  98. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/trychange.json +150 -0
  99. data/vendor/depot_tools/recipes/recipe_modules/bot_update/{example.expected → examples/full.expected}/trychange_oauth2.json +0 -0
  100. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/trychange_oauth2_buildbot.json +152 -0
  101. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/trychange_oauth2_json.json +150 -0
  102. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/trychange_oauth2_json_win.json +150 -0
  103. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob.json +156 -0
  104. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail.json +91 -0
  105. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch.json +118 -0
  106. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch_download.json +118 -0
  107. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_angle.json +202 -0
  108. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_angle_deprecated.json +158 -0
  109. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_feature_branch.json +196 -0
  110. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_v8.json +202 -0
  111. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_v8_feature_branch.json +202 -0
  112. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8.json +162 -0
  113. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8_head_by_default.json +162 -0
  114. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/with_tags.json +149 -0
  115. data/vendor/depot_tools/recipes/recipe_modules/bot_update/{example.py → examples/full.py} +46 -8
  116. data/vendor/depot_tools/recipes/recipe_modules/bot_update/resources/bot_update.py +139 -133
  117. data/vendor/depot_tools/recipes/recipe_modules/bot_update/test_api.py +25 -13
  118. data/vendor/depot_tools/recipes/recipe_modules/cipd/api.py +40 -9
  119. data/vendor/depot_tools/recipes/recipe_modules/cipd/{example.expected → examples/full.expected}/basic.json +0 -0
  120. data/vendor/depot_tools/recipes/recipe_modules/cipd/{example.expected → examples/full.expected}/basic_pkg.json +1 -1
  121. data/vendor/depot_tools/recipes/recipe_modules/cipd/{example.expected → examples/full.expected}/describe-failed.json +0 -0
  122. data/vendor/depot_tools/recipes/recipe_modules/cipd/{example.expected → examples/full.expected}/describe-many-instances.json +0 -0
  123. data/vendor/depot_tools/recipes/recipe_modules/cipd/{example.expected → examples/full.expected}/mac64.json +0 -0
  124. data/vendor/depot_tools/recipes/recipe_modules/cipd/{example.expected → examples/full.expected}/pkg_bad_file.json +1 -1
  125. data/vendor/depot_tools/recipes/recipe_modules/cipd/{example.expected → examples/full.expected}/pkg_bad_mode.json +0 -0
  126. data/vendor/depot_tools/recipes/recipe_modules/cipd/{example.expected → examples/full.expected}/pkg_bad_verfile.json +0 -0
  127. data/vendor/depot_tools/recipes/recipe_modules/cipd/{example.expected → examples/full.expected}/win64.json +0 -0
  128. data/vendor/depot_tools/recipes/recipe_modules/cipd/{example.py → examples/full.py} +1 -0
  129. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/junk arch.json +7 -0
  130. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/junk bits.json +7 -0
  131. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_arm_32.json +14 -0
  132. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_arm_64.json +14 -0
  133. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_intel_32.json +14 -0
  134. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_intel_64.json +14 -0
  135. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_mips_64.json +14 -0
  136. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/mac_intel_64.json +14 -0
  137. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/win_intel_32.json +14 -0
  138. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/win_intel_64.json +14 -0
  139. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.py +59 -0
  140. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/api.py +5 -0
  141. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/{example.expected → examples/full.expected}/basic.json +7 -0
  142. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/{example.expected → examples/full.expected}/win.json +7 -0
  143. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/{example.py → examples/full.py} +2 -0
  144. data/vendor/depot_tools/recipes/recipe_modules/gclient/__init__.py +1 -4
  145. data/vendor/depot_tools/recipes/recipe_modules/gclient/api.py +28 -14
  146. data/vendor/depot_tools/recipes/recipe_modules/gclient/config.py +10 -235
  147. data/vendor/depot_tools/recipes/recipe_modules/gclient/{example.expected → examples/full.expected}/basic.json +9 -9
  148. data/vendor/depot_tools/recipes/recipe_modules/gclient/{example.expected → examples/full.expected}/buildbot.json +9 -9
  149. data/vendor/depot_tools/recipes/recipe_modules/gclient/{example.expected → examples/full.expected}/revision.json +9 -9
  150. data/vendor/depot_tools/recipes/recipe_modules/gclient/{example.expected → examples/full.expected}/tryserver.json +9 -9
  151. data/vendor/depot_tools/recipes/recipe_modules/gclient/{example.py → examples/full.py} +5 -21
  152. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/patch_project.py +45 -0
  153. data/vendor/depot_tools/recipes/recipe_modules/gerrit/__init__.py +1 -0
  154. data/vendor/depot_tools/recipes/recipe_modules/gerrit/api.py +97 -2
  155. data/vendor/depot_tools/recipes/recipe_modules/gerrit/examples/full.expected/basic.json +283 -0
  156. data/vendor/depot_tools/recipes/recipe_modules/gerrit/{example.py → examples/full.py} +31 -2
  157. data/vendor/depot_tools/recipes/recipe_modules/gerrit/test_api.py +30 -1
  158. data/vendor/depot_tools/recipes/recipe_modules/git/__init__.py +1 -4
  159. data/vendor/depot_tools/recipes/recipe_modules/git/api.py +7 -35
  160. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/basic.json +3 -3
  161. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/basic_branch.json +3 -3
  162. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/basic_file_name.json +3 -3
  163. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/basic_hash.json +3 -3
  164. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/basic_ref.json +3 -3
  165. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/basic_submodule_update_force.json +3 -3
  166. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/can_fail_build.json +1 -1
  167. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/cannot_fail_build.json +3 -3
  168. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/cat-file_test.json +3 -3
  169. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/count-objects_delta.json +3 -3
  170. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/count-objects_failed.json +3 -3
  171. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/count-objects_with_bad_output.json +3 -3
  172. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/count-objects_with_bad_output_fails_build.json +1 -1
  173. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/curl_trace_file.json +3 -3
  174. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/git-cache-checkout.json +6 -6
  175. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/platform_win.json +223 -0
  176. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/rebase_failed.json +3 -3
  177. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/remote_not_origin.json +3 -3
  178. data/vendor/depot_tools/recipes/recipe_modules/git/{example.expected → examples/full.expected}/set_got_revision.json +3 -3
  179. data/vendor/depot_tools/recipes/recipe_modules/git/{example.py → examples/full.py} +2 -1
  180. data/vendor/depot_tools/recipes/recipe_modules/git/resources/git_setup.py +12 -21
  181. data/vendor/depot_tools/recipes/recipe_modules/git_cl/__init__.py +1 -4
  182. data/vendor/depot_tools/recipes/recipe_modules/git_cl/api.py +13 -11
  183. data/vendor/depot_tools/recipes/recipe_modules/git_cl/{example.expected → examples/full.expected}/basic.json +0 -0
  184. data/vendor/depot_tools/recipes/recipe_modules/git_cl/{example.py → examples/full.py} +4 -2
  185. data/vendor/depot_tools/recipes/recipe_modules/gitiles/OWNERS +3 -0
  186. data/vendor/depot_tools/recipes/recipe_modules/gitiles/__init__.py +7 -0
  187. data/vendor/depot_tools/recipes/recipe_modules/gitiles/api.py +135 -0
  188. data/vendor/depot_tools/recipes/recipe_modules/gitiles/examples/full.expected/basic.json +537 -0
  189. data/vendor/depot_tools/recipes/recipe_modules/gitiles/examples/full.py +61 -0
  190. data/vendor/depot_tools/recipes/recipe_modules/gitiles/resources/gerrit_client.py +192 -0
  191. data/vendor/depot_tools/recipes/recipe_modules/gitiles/test_api.py +95 -0
  192. data/vendor/depot_tools/recipes/recipe_modules/gsutil/{example.expected → examples/full.expected}/basic.json +0 -0
  193. data/vendor/depot_tools/recipes/recipe_modules/gsutil/{example.py → examples/full.py} +0 -0
  194. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/__init__.py +0 -3
  195. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/{example.expected → examples/full.expected}/basic.json +3 -2
  196. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/{example.expected → examples/full.expected}/paths_buildbot_linux.json +3 -2
  197. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/{example.expected → examples/full.expected}/paths_buildbot_mac.json +3 -2
  198. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/{example.expected → examples/full.expected}/paths_buildbot_win.json +3 -2
  199. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/{example.expected → examples/full.expected}/paths_generic_linux.json +3 -2
  200. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/{example.expected → examples/full.expected}/paths_generic_mac.json +3 -2
  201. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_generic_win.json +16 -0
  202. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_kitchen_linux.json +16 -0
  203. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_kitchen_mac.json +16 -0
  204. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_kitchen_win.json +16 -0
  205. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/{example.py → examples/full.py} +2 -1
  206. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/path_config.py +12 -3
  207. data/vendor/depot_tools/recipes/recipe_modules/presubmit/__init__.py +1 -0
  208. data/vendor/depot_tools/recipes/recipe_modules/presubmit/api.py +2 -2
  209. data/vendor/depot_tools/recipes/recipe_modules/presubmit/{example.expected → examples/full.expected}/basic.json +1 -1
  210. data/vendor/depot_tools/recipes/recipe_modules/presubmit/{example.py → examples/full.py} +0 -0
  211. data/vendor/depot_tools/recipes/recipe_modules/rietveld/__init__.py +0 -4
  212. data/vendor/depot_tools/recipes/recipe_modules/rietveld/{example.expected → examples/full.expected}/basic.json +0 -0
  213. data/vendor/depot_tools/recipes/recipe_modules/rietveld/{example.expected → examples/full.expected}/buildbot.json +0 -0
  214. data/vendor/depot_tools/recipes/recipe_modules/rietveld/examples/full.expected/no_auth.json +27 -0
  215. data/vendor/depot_tools/recipes/recipe_modules/rietveld/{example.py → examples/full.py} +9 -1
  216. data/vendor/depot_tools/recipes/recipe_modules/tryserver/__init__.py +3 -5
  217. data/vendor/depot_tools/recipes/recipe_modules/tryserver/api.py +21 -96
  218. data/vendor/depot_tools/recipes/recipe_modules/tryserver/{example.expected → examples/full.expected}/basic_tags.json +0 -0
  219. data/vendor/depot_tools/recipes/recipe_modules/tryserver/{example.expected → examples/full.expected}/set_failure_hash_with_no_steps.json +0 -0
  220. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_gerrit_patch.json +56 -0
  221. data/vendor/depot_tools/recipes/recipe_modules/tryserver/{example.expected/with_gerrit_patch_deprecated.json → examples/full.expected/with_git_patch.json} +2 -2
  222. data/vendor/depot_tools/recipes/recipe_modules/tryserver/{example.expected/with_gerrit_patch.json → examples/full.expected/with_git_patch_luci.json} +2 -2
  223. data/vendor/depot_tools/recipes/recipe_modules/tryserver/{example.expected → examples/full.expected}/with_rietveld_patch.json +0 -20
  224. data/vendor/depot_tools/recipes/recipe_modules/tryserver/{example.expected → examples/full.expected}/with_rietveld_patch_new.json +0 -20
  225. data/vendor/depot_tools/recipes/recipe_modules/tryserver/{example.expected → examples/full.expected}/with_wrong_patch.json +1 -13
  226. data/vendor/depot_tools/recipes/recipe_modules/tryserver/{example.expected → examples/full.expected}/with_wrong_patch_new.json +1 -13
  227. data/vendor/depot_tools/recipes/recipe_modules/tryserver/{example.py → examples/full.py} +3 -17
  228. data/vendor/depot_tools/recipes/recipes.py +141 -96
  229. data/vendor/depot_tools/rietveld.py +8 -1
  230. data/vendor/depot_tools/roll-dep-svn.bat +12 -10
  231. data/vendor/depot_tools/roll-dep.bat +5 -3
  232. data/vendor/depot_tools/scm.py +8 -1
  233. data/vendor/depot_tools/setup_color.py +0 -0
  234. data/vendor/depot_tools/split_cl.py +193 -0
  235. data/vendor/depot_tools/third_party/schema/.editorconfig +15 -0
  236. data/vendor/depot_tools/third_party/schema/.gitignore +174 -0
  237. data/vendor/depot_tools/third_party/schema/.travis.yml +37 -0
  238. data/vendor/depot_tools/third_party/schema/LICENSE-MIT +19 -0
  239. data/vendor/depot_tools/third_party/schema/MANIFEST.in +1 -0
  240. data/vendor/depot_tools/third_party/schema/README.chromium +12 -0
  241. data/vendor/depot_tools/third_party/schema/README.rst +382 -0
  242. data/vendor/depot_tools/third_party/schema/__init__.py +1 -0
  243. data/vendor/depot_tools/third_party/schema/schema.py +338 -0
  244. data/vendor/depot_tools/third_party/schema/setup.cfg +5 -0
  245. data/vendor/depot_tools/third_party/schema/setup.py +30 -0
  246. data/vendor/depot_tools/third_party/schema/test_schema.py +556 -0
  247. data/vendor/depot_tools/third_party/schema/tox.ini +33 -0
  248. data/vendor/depot_tools/third_party/upload.py +4 -0
  249. data/vendor/depot_tools/update_depot_tools +4 -16
  250. data/vendor/depot_tools/update_depot_tools.bat +4 -17
  251. data/vendor/depot_tools/update_depot_tools_toggle.py +38 -0
  252. data/vendor/depot_tools/vpython +12 -0
  253. data/vendor/depot_tools/vpython.bat +7 -0
  254. data/vendor/depot_tools/win_toolchain/get_toolchain_if_necessary.py +17 -5
  255. data/vendor/depot_tools/win_toolchain/package_from_installed.py +63 -33
  256. metadata +161 -113
  257. data/vendor/depot_tools/bootstrap/gclient.bat +0 -22
  258. data/vendor/depot_tools/bootstrap/win/get_file.js +0 -119
  259. data/vendor/depot_tools/bootstrap/win/git_bootstrap.py +0 -193
  260. data/vendor/depot_tools/bootstrap/win/git_version.txt +0 -1
  261. data/vendor/depot_tools/bootstrap/win/git_version_bleeding_edge.txt +0 -1
  262. data/vendor/depot_tools/bootstrap/win/python276.new.bat +0 -8
  263. data/vendor/depot_tools/bootstrap/win/svn.new.bat +0 -4
  264. data/vendor/depot_tools/bootstrap/win/svnversion.new.bat +0 -4
  265. data/vendor/depot_tools/bootstrap/win/unzip.js +0 -91
  266. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/basic.json +0 -53
  267. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/basic_output_manifest.json +0 -60
  268. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/basic_with_branch_heads.json +0 -54
  269. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/buildbot.json +0 -53
  270. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/clobber.json +0 -54
  271. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/gerrit_no_rebase_patch_ref.json +0 -54
  272. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/gerrit_no_reset.json +0 -54
  273. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/no_shallow.json +0 -54
  274. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/reset_root_solution_revision.json +0 -53
  275. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/trychange.json +0 -55
  276. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/trychange_oauth2_buildbot.json +0 -57
  277. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/trychange_oauth2_json.json +0 -55
  278. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/trychange_oauth2_json_win.json +0 -55
  279. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/tryjob.json +0 -59
  280. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/tryjob_fail.json +0 -62
  281. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/tryjob_fail_patch.json +0 -83
  282. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/tryjob_fail_patch_download.json +0 -84
  283. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/tryjob_gerrit_angle.json +0 -60
  284. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/tryjob_gerrit_angle_deprecated.json +0 -60
  285. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/tryjob_v8.json +0 -62
  286. data/vendor/depot_tools/recipes/recipe_modules/bot_update/example.expected/tryjob_v8_head_by_default.json +0 -62
  287. data/vendor/depot_tools/recipes/recipe_modules/gclient/bundle_extra_paths.txt +0 -4
  288. data/vendor/depot_tools/recipes/recipe_modules/gerrit/example.expected/basic.json +0 -66
  289. data/vendor/depot_tools/recipes/recipe_modules/git/bundle_extra_paths.txt +0 -28
  290. data/vendor/depot_tools/recipes/recipe_modules/git/example.expected/platform_win.json +0 -237
  291. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/example.expected/paths_generic_win.json +0 -15
  292. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/example.expected/paths_kitchen_linux.json +0 -15
  293. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/example.expected/paths_kitchen_mac.json +0 -15
  294. data/vendor/depot_tools/recipes/recipe_modules/infra_paths/example.expected/paths_kitchen_win.json +0 -15
  295. data/vendor/depot_tools/recipes/recipe_modules/presubmit/bundle_extra_paths.txt +0 -30
  296. data/vendor/depot_tools/recipes/recipe_modules/tryserver/example.expected/with_git_patch.json +0 -109
  297. data/vendor/depot_tools/recipes/recipe_modules/tryserver/example.expected/with_git_patch_luci.json +0 -8
@@ -4,11 +4,12 @@
4
4
  :: found in the LICENSE file.
5
5
  setlocal
6
6
 
7
- :: This is required with cygwin only.
8
- PATH=%~dp0;%PATH%
9
-
10
7
  :: Synchronize the root directory before deferring control back to gclient.py.
11
8
  call "%~dp0update_depot_tools.bat" %*
12
9
 
10
+ :: Ensure that "depot_tools" is somewhere in PATH so this tool can be used
11
+ :: standalone, but allow other PATH manipulations to take priority.
12
+ set PATH=%PATH%;%~dp0
13
+
13
14
  :: Defer control.
14
- "%~dp0python" "%~dp0gclient.py" %*
15
+ python "%~dp0gclient.py" %*
@@ -64,7 +64,7 @@
64
64
  # Specifying a target OS
65
65
  # An optional key named "target_os" may be added to a gclient file to specify
66
66
  # one or more additional operating systems that should be considered when
67
- # processing the deps_os dict of a DEPS file.
67
+ # processing the deps_os/hooks_os dict of a DEPS file.
68
68
  #
69
69
  # Example:
70
70
  # target_os = [ "android" ]
@@ -80,7 +80,7 @@ from __future__ import print_function
80
80
 
81
81
  __version__ = '0.7'
82
82
 
83
- import ast
83
+ import collections
84
84
  import copy
85
85
  import json
86
86
  import logging
@@ -96,6 +96,7 @@ import urllib
96
96
  import urlparse
97
97
 
98
98
  import fix_encoding
99
+ import gclient_eval
99
100
  import gclient_scm
100
101
  import gclient_utils
101
102
  import git_cache
@@ -104,75 +105,123 @@ import subcommand
104
105
  import subprocess2
105
106
  import setup_color
106
107
 
107
- CHROMIUM_SRC_URL = 'https://chromium.googlesource.com/chromium/src.git'
108
-
109
-
110
- def ast_dict_index(dnode, key):
111
- """Search an ast.Dict for the argument key, and return its index."""
112
- idx = [i for i in range(len(dnode.keys)) if (
113
- type(dnode.keys[i]) is ast.Str and dnode.keys[i].s == key)]
114
- if not idx:
115
- return -1
116
- elif len(idx) > 1:
117
- raise gclient_utils.Error('Multiple dict entries with same key in AST')
118
- return idx[-1]
119
-
120
- def ast2str(node, indent=0):
121
- """Return a pretty-printed rendition of an ast.Node."""
122
- t = type(node)
123
- if t is ast.Module:
124
- return '\n'.join([ast2str(x, indent) for x in node.body])
125
- elif t is ast.Assign:
126
- return ((' ' * indent) +
127
- ' = '.join([ast2str(x) for x in node.targets] +
128
- [ast2str(node.value, indent)]) + '\n')
129
- elif t is ast.Name:
130
- return node.id
131
- elif t is ast.List:
132
- if not node.elts:
133
- return '[]'
134
- elif len(node.elts) == 1:
135
- return '[' + ast2str(node.elts[0], indent) + ']'
136
- return ('[\n' + (' ' * (indent + 1)) +
137
- (',\n' + (' ' * (indent + 1))).join(
138
- [ast2str(x, indent + 1) for x in node.elts]) +
139
- '\n' + (' ' * indent) + ']')
140
- elif t is ast.Dict:
141
- if not node.keys:
142
- return '{}'
143
- elif len(node.keys) == 1:
144
- return '{%s: %s}' % (ast2str(node.keys[0]),
145
- ast2str(node.values[0], indent + 1))
146
- return ('{\n' + (' ' * (indent + 1)) +
147
- (',\n' + (' ' * (indent + 1))).join(
148
- ['%s: %s' % (ast2str(node.keys[i]),
149
- ast2str(node.values[i], indent + 1))
150
- for i in range(len(node.keys))]) +
151
- '\n' + (' ' * indent) + '}')
152
- elif t is ast.Str:
153
- return "'%s'" % node.s
154
- else:
155
- raise gclient_utils.Error("Unexpected AST node at line %d, column %d: %s"
156
- % (node.lineno, node.col_offset, t))
157
108
 
109
+ class GNException(Exception):
110
+ pass
158
111
 
159
- class GClientKeywords(object):
160
- class FromImpl(object):
161
- """Used to implement the From() syntax."""
162
112
 
163
- def __init__(self, module_name, sub_target_name=None):
164
- """module_name is the dep module we want to include from. It can also be
165
- the name of a subdirectory to include from.
113
+ def ToGNString(value, allow_dicts = True):
114
+ """Returns a stringified GN equivalent of the Python value.
115
+
116
+ allow_dicts indicates if this function will allow converting dictionaries
117
+ to GN scopes. This is only possible at the top level, you can't nest a
118
+ GN scope in a list, so this should be set to False for recursive calls."""
119
+ if isinstance(value, basestring):
120
+ if value.find('\n') >= 0:
121
+ raise GNException("Trying to print a string with a newline in it.")
122
+ return '"' + \
123
+ value.replace('\\', '\\\\').replace('"', '\\"').replace('$', '\\$') + \
124
+ '"'
125
+
126
+ if isinstance(value, unicode):
127
+ return ToGNString(value.encode('utf-8'))
128
+
129
+ if isinstance(value, bool):
130
+ if value:
131
+ return "true"
132
+ return "false"
133
+
134
+ # NOTE: some type handling removed compared to chromium/src copy.
135
+
136
+ raise GNException("Unsupported type when printing to GN.")
137
+
138
+
139
+ class Hook(object):
140
+ """Descriptor of command ran before/after sync or on demand."""
141
+
142
+ def __init__(self, action, pattern=None, name=None, cwd=None, condition=None,
143
+ variables=None):
144
+ """Constructor.
145
+
146
+ Arguments:
147
+ action (list of basestring): argv of the command to run
148
+ pattern (basestring regex): noop with git; deprecated
149
+ name (basestring): optional name; no effect on operation
150
+ cwd (basestring): working directory to use
151
+ condition (basestring): condition when to run the hook
152
+ variables (dict): variables for evaluating the condition
153
+ """
154
+ self._action = gclient_utils.freeze(action)
155
+ self._pattern = pattern
156
+ self._name = name
157
+ self._cwd = cwd
158
+ self._condition = condition
159
+ self._variables = variables
160
+
161
+ @staticmethod
162
+ def from_dict(d, variables=None):
163
+ """Creates a Hook instance from a dict like in the DEPS file."""
164
+ return Hook(
165
+ d['action'],
166
+ d.get('pattern'),
167
+ d.get('name'),
168
+ d.get('cwd'),
169
+ d.get('condition'),
170
+ variables=variables)
171
+
172
+ @property
173
+ def action(self):
174
+ return self._action
175
+
176
+ @property
177
+ def pattern(self):
178
+ return self._pattern
166
179
 
167
- sub_target_name is an optional parameter if the module name in the other
168
- DEPS file is different. E.g., you might want to map src/net to net."""
169
- self.module_name = module_name
170
- self.sub_target_name = sub_target_name
180
+ @property
181
+ def name(self):
182
+ return self._name
171
183
 
172
- def __str__(self):
173
- return 'From(%s, %s)' % (repr(self.module_name),
174
- repr(self.sub_target_name))
184
+ def matches(self, file_list):
185
+ """Returns true if the pattern matches any of files in the list."""
186
+ if not self._pattern:
187
+ return True
188
+ pattern = re.compile(self._pattern)
189
+ return bool([f for f in file_list if pattern.search(f)])
190
+
191
+ def run(self, root):
192
+ """Executes the hook's command (provided the condition is met)."""
193
+ if (self._condition and
194
+ not gclient_eval.EvaluateCondition(self._condition, self._variables)):
195
+ return
196
+
197
+ cmd = list(self._action)
198
+ if cmd[0] == 'python':
199
+ # If the hook specified "python" as the first item, the action is a
200
+ # Python script. Run it by starting a new copy of the same
201
+ # interpreter.
202
+ cmd[0] = sys.executable
175
203
 
204
+ cwd = root
205
+ if self._cwd:
206
+ cwd = os.path.join(cwd, self._cwd)
207
+ try:
208
+ start_time = time.time()
209
+ gclient_utils.CheckCallAndFilterAndHeader(
210
+ cmd, cwd=cwd, always=True)
211
+ except (gclient_utils.Error, subprocess2.CalledProcessError) as e:
212
+ # Use a discrete exit status code of 2 to indicate that a hook action
213
+ # failed. Users of this script may wish to treat hook action failures
214
+ # differently from VC failures.
215
+ print('Error: %s' % str(e), file=sys.stderr)
216
+ sys.exit(2)
217
+ finally:
218
+ elapsed_time = time.time() - start_time
219
+ if elapsed_time > 10:
220
+ print("Hook '%s' took %.2f secs" % (
221
+ gclient_utils.CommandToStr(cmd), elapsed_time))
222
+
223
+
224
+ class GClientKeywords(object):
176
225
  class VarImpl(object):
177
226
  def __init__(self, custom_vars, local_scope):
178
227
  self._custom_vars = custom_vars
@@ -191,13 +240,18 @@ class DependencySettings(GClientKeywords):
191
240
  """Immutable configuration settings."""
192
241
  def __init__(
193
242
  self, parent, url, managed, custom_deps, custom_vars,
194
- custom_hooks, deps_file, should_process, relative):
243
+ custom_hooks, deps_file, should_process, relative,
244
+ condition, condition_value):
195
245
  GClientKeywords.__init__(self)
196
246
 
197
247
  # These are not mutable:
198
248
  self._parent = parent
199
249
  self._deps_file = deps_file
200
250
  self._url = url
251
+ # The condition as string (or None). Useful to keep e.g. for flatten.
252
+ self._condition = condition
253
+ # Boolean value of the condition. If there's no condition, just True.
254
+ self._condition_value = condition_value
201
255
  # 'managed' determines whether or not this dependency is synced/updated by
202
256
  # gclient after gclient checks it out initially. The difference between
203
257
  # 'managed' and 'should_process' is that the user specifies 'managed' via
@@ -225,10 +279,10 @@ class DependencySettings(GClientKeywords):
225
279
  # urls are sometime incorrectly written as proto://host/path/@rev. Replace
226
280
  # it to proto://host/path@rev.
227
281
  self._url = self._url.replace('/@', '@')
228
- elif not isinstance(self._url, (self.FromImpl, None.__class__)):
282
+ elif not isinstance(self._url, (None.__class__)):
229
283
  raise gclient_utils.Error(
230
- ('dependency url must be either a string, None, '
231
- 'or From() instead of %s') % self._url.__class__.__name__)
284
+ ('dependency url must be either string or None, '
285
+ 'instead of %s') % self._url.__class__.__name__)
232
286
  # Make any deps_file path platform-appropriate.
233
287
  for sep in ['/', '\\']:
234
288
  self._deps_file = self._deps_file.replace(sep, os.sep)
@@ -274,6 +328,14 @@ class DependencySettings(GClientKeywords):
274
328
  def url(self):
275
329
  return self._url
276
330
 
331
+ @property
332
+ def condition(self):
333
+ return self._condition
334
+
335
+ @property
336
+ def condition_value(self):
337
+ return self._condition_value
338
+
277
339
  @property
278
340
  def target_os(self):
279
341
  if self.local_target_os is not None:
@@ -294,11 +356,12 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
294
356
 
295
357
  def __init__(self, parent, name, url, managed, custom_deps,
296
358
  custom_vars, custom_hooks, deps_file, should_process,
297
- relative):
359
+ relative, condition, condition_value):
298
360
  gclient_utils.WorkItem.__init__(self, name)
299
361
  DependencySettings.__init__(
300
362
  self, parent, url, managed, custom_deps, custom_vars,
301
- custom_hooks, deps_file, should_process, relative)
363
+ custom_hooks, deps_file, should_process, relative,
364
+ condition, condition_value)
302
365
 
303
366
  # This is in both .gclient and DEPS files:
304
367
  self._deps_hooks = []
@@ -308,6 +371,13 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
308
371
  # Calculates properties:
309
372
  self._parsed_url = None
310
373
  self._dependencies = []
374
+ # Keep track of original values, before post-processing (e.g. deps_os).
375
+ self._orig_dependencies = []
376
+ self._orig_deps_hooks = []
377
+ self._vars = {}
378
+ self._os_dependencies = {}
379
+ self._os_deps_hooks = {}
380
+
311
381
  # A cache of the files affected by the current operation, necessary for
312
382
  # hooks.
313
383
  self._file_list = []
@@ -316,6 +386,9 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
316
386
  # hosts will be allowed. Non-empty set means whitelist of hosts.
317
387
  # allowed_hosts var is scoped to its DEPS file, and so it isn't recursive.
318
388
  self._allowed_hosts = frozenset()
389
+ # Spec for .gni output to write (if any).
390
+ self._gn_args_file = None
391
+ self._gn_args = []
319
392
  # If it is not set to True, the dependency wasn't processed for its child
320
393
  # dependency, i.e. its DEPS wasn't read.
321
394
  self._deps_parsed = False
@@ -376,9 +449,6 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
376
449
  if self.parent and self.parent.parent and not self.parent.parent.parent:
377
450
  requirements |= set(i.name for i in self.root.dependencies if i.name)
378
451
 
379
- if isinstance(self.url, self.FromImpl):
380
- requirements.add(self.url.module_name)
381
-
382
452
  if self.name:
383
453
  requirements |= set(
384
454
  obj.name for obj in self.root.subtree(False)
@@ -448,10 +518,7 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
448
518
  return True
449
519
 
450
520
  def LateOverride(self, url):
451
- """Resolves the parsed url from url.
452
-
453
- Manages From() keyword accordingly. Do not touch self.parsed_url nor
454
- self.url because it may called with other urls due to From()."""
521
+ """Resolves the parsed url from url."""
455
522
  assert self.parsed_url == None or not self.should_process, self.parsed_url
456
523
  parsed_url = self.get_custom_deps(self.name, url)
457
524
  if parsed_url != url:
@@ -460,32 +527,6 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
460
527
  (self.name, url, parsed_url))
461
528
  return parsed_url
462
529
 
463
- if isinstance(url, self.FromImpl):
464
- # Requires tree traversal.
465
- ref = [
466
- dep for dep in self.root.subtree(True) if url.module_name == dep.name
467
- ]
468
- if not ref:
469
- raise gclient_utils.Error('Failed to find one reference to %s. %s' % (
470
- url.module_name, ref))
471
- # It may happen that len(ref) > 1 but it's no big deal.
472
- ref = ref[0]
473
- sub_target = url.sub_target_name or self.name
474
- found_deps = [d for d in ref.dependencies if d.name == sub_target]
475
- if len(found_deps) != 1:
476
- raise gclient_utils.Error(
477
- 'Couldn\'t find %s in %s, referenced by %s (parent: %s)\n%s' % (
478
- sub_target, ref.name, self.name, self.parent.name,
479
- str(self.root)))
480
-
481
- # Call LateOverride() again.
482
- found_dep = found_deps[0]
483
- parsed_url = found_dep.LateOverride(found_dep.url)
484
- logging.info(
485
- 'Dependency(%s).LateOverride(%s) -> %s (From)' %
486
- (self.name, url, parsed_url))
487
- return parsed_url
488
-
489
530
  if isinstance(url, basestring):
490
531
  parsed_url = urlparse.urlparse(url)
491
532
  if (not parsed_url[0] and
@@ -519,48 +560,111 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
519
560
  """Returns a new "deps" structure that is the deps sent in updated
520
561
  with information from deps_os (the deps_os section of the DEPS
521
562
  file) that matches the list of target os."""
522
- os_overrides = {}
523
- for the_target_os in target_os_list:
524
- the_target_os_deps = deps_os.get(the_target_os, {})
525
- for os_dep_key, os_dep_value in the_target_os_deps.iteritems():
526
- overrides = os_overrides.setdefault(os_dep_key, [])
527
- overrides.append((the_target_os, os_dep_value))
528
-
529
- # If any os didn't specify a value (we have fewer value entries
530
- # than in the os list), then it wants to use the default value.
531
- for os_dep_key, os_dep_value in os_overrides.iteritems():
532
- if len(os_dep_value) != len(target_os_list):
533
- # Record the default value too so that we don't accidentally
534
- # set it to None or miss a conflicting DEPS.
535
- if os_dep_key in deps:
536
- os_dep_value.append(('default', deps[os_dep_key]))
537
-
538
- target_os_deps = {}
539
- for os_dep_key, os_dep_value in os_overrides.iteritems():
540
- # os_dep_value is a list of (os, value) pairs.
541
- possible_values = set(x[1] for x in os_dep_value if x[1] is not None)
542
- if not possible_values:
543
- target_os_deps[os_dep_key] = None
544
- else:
545
- if len(possible_values) > 1:
546
- # It would be possible to abort here but it would be
547
- # unfortunate if we end up preventing any kind of checkout.
548
- logging.error('Conflicting dependencies for %s: %s. (target_os=%s)',
549
- os_dep_key, os_dep_value, target_os_list)
550
- # Sorting to get the same result every time in case of conflicts.
551
- target_os_deps[os_dep_key] = sorted(possible_values)[0]
552
-
553
563
  new_deps = deps.copy()
554
- new_deps.update(target_os_deps)
564
+ for dep_os, os_deps in deps_os.iteritems():
565
+ for key, value in os_deps.iteritems():
566
+ if value is None:
567
+ # Make this condition very visible, so it's not a silent failure.
568
+ # It's unclear how to support None override in deps_os.
569
+ logging.error('Ignoring %r:%r in %r deps_os', key, value, dep_os)
570
+ continue
571
+
572
+ # Normalize value to be a dict which contains |should_process| metadata.
573
+ if isinstance(value, basestring):
574
+ value = {'url': value}
575
+ assert isinstance(value, collections.Mapping), (key, value)
576
+ value['should_process'] = dep_os in target_os_list
577
+
578
+ # Handle collisions/overrides.
579
+ if key in new_deps and new_deps[key] != value:
580
+ # Normalize the existing new_deps entry.
581
+ if isinstance(new_deps[key], basestring):
582
+ new_deps[key] = {'url': new_deps[key]}
583
+ assert isinstance(new_deps[key],
584
+ collections.Mapping), (key, new_deps[key])
585
+
586
+ # It's OK if the "override" sets the key to the same value.
587
+ # This is mostly for legacy reasons to keep existing DEPS files
588
+ # working. Often mac/ios and unix/android will do this.
589
+ if value['url'] != new_deps[key]['url']:
590
+ raise gclient_utils.Error(
591
+ ('Value from deps_os (%r; %r: %r) conflicts with existing deps '
592
+ 'entry (%r).') % (dep_os, key, value, new_deps[key]))
593
+
594
+ # We'd otherwise overwrite |should_process| metadata, but a dep should
595
+ # be processed if _any_ of its references call for that.
596
+ value['should_process'] = (
597
+ value['should_process'] or
598
+ new_deps[key].get('should_process', True))
599
+
600
+ new_deps[key] = value
601
+
555
602
  return new_deps
556
603
 
604
+ def _postprocess_deps(self, deps, rel_prefix):
605
+ """Performs post-processing of deps compared to what's in the DEPS file."""
606
+ # Make sure the dict is mutable, e.g. in case it's frozen.
607
+ deps = dict(deps)
608
+
609
+ # If a line is in custom_deps, but not in the solution, we want to append
610
+ # this line to the solution.
611
+ for d in self.custom_deps:
612
+ if d not in deps:
613
+ deps[d] = self.custom_deps[d]
614
+
615
+ if rel_prefix:
616
+ logging.warning('use_relative_paths enabled.')
617
+ rel_deps = {}
618
+ for d, url in deps.items():
619
+ # normpath is required to allow DEPS to use .. in their
620
+ # dependency local path.
621
+ rel_deps[os.path.normpath(os.path.join(rel_prefix, d))] = url
622
+ logging.warning('Updating deps by prepending %s.', rel_prefix)
623
+ deps = rel_deps
624
+
625
+ return deps
626
+
627
+ def _deps_to_objects(self, deps, use_relative_paths):
628
+ """Convert a deps dict to a dict of Dependency objects."""
629
+ deps_to_add = []
630
+ for name, dep_value in deps.iteritems():
631
+ should_process = self.recursion_limit and self.should_process
632
+ deps_file = self.deps_file
633
+ if self.recursedeps is not None:
634
+ ent = self.recursedeps.get(name)
635
+ if ent is not None:
636
+ deps_file = ent['deps_file']
637
+ if dep_value is None:
638
+ continue
639
+ condition = None
640
+ condition_value = True
641
+ if isinstance(dep_value, basestring):
642
+ url = dep_value
643
+ else:
644
+ # This should be guaranteed by schema checking in gclient_eval.
645
+ assert isinstance(dep_value, collections.Mapping)
646
+ url = dep_value['url']
647
+ # Take into account should_process metadata set by MergeWithOsDeps.
648
+ should_process = (should_process and
649
+ dep_value.get('should_process', True))
650
+ condition = dep_value.get('condition')
651
+ if condition:
652
+ condition_value = gclient_eval.EvaluateCondition(
653
+ condition, self.get_vars())
654
+ should_process = should_process and condition_value
655
+ deps_to_add.append(Dependency(
656
+ self, name, url, None, None, self.custom_vars, None,
657
+ deps_file, should_process, use_relative_paths, condition,
658
+ condition_value))
659
+ deps_to_add.sort(key=lambda x: x.name)
660
+ return deps_to_add
661
+
557
662
  def ParseDepsFile(self):
558
663
  """Parses the DEPS file for this dependency."""
559
664
  assert not self.deps_parsed
560
665
  assert not self.dependencies
561
666
 
562
667
  deps_content = None
563
- use_strict = False
564
668
 
565
669
  # First try to locate the configured deps file. If it's missing, fallback
566
670
  # to DEPS.
@@ -581,66 +685,42 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
581
685
  if os.path.isfile(filepath):
582
686
  deps_content = gclient_utils.FileRead(filepath)
583
687
  logging.debug('ParseDepsFile(%s) read:\n%s', self.name, deps_content)
584
- use_strict = 'use strict' in deps_content.splitlines()[0]
585
688
 
586
689
  local_scope = {}
587
690
  if deps_content:
588
691
  # One thing is unintuitive, vars = {} must happen before Var() use.
589
692
  var = self.VarImpl(self.custom_vars, local_scope)
590
- if use_strict:
591
- logging.info(
592
- 'ParseDepsFile(%s): Strict Mode Enabled', self.name)
593
- global_scope = {
594
- '__builtins__': {'None': None},
595
- 'Var': var.Lookup,
596
- 'deps_os': {},
597
- }
598
- else:
599
- global_scope = {
600
- 'From': self.FromImpl,
601
- 'Var': var.Lookup,
602
- 'deps_os': {},
603
- }
693
+ global_scope = {
694
+ 'Var': var.Lookup,
695
+ 'deps_os': {},
696
+ }
604
697
  # Eval the content.
605
698
  try:
606
- exec(deps_content, global_scope, local_scope)
699
+ if self._get_option('validate_syntax', False):
700
+ gclient_eval.Exec(deps_content, global_scope, local_scope, filepath)
701
+ else:
702
+ exec(deps_content, global_scope, local_scope)
607
703
  except SyntaxError as e:
608
704
  gclient_utils.SyntaxErrorToError(filepath, e)
609
- if use_strict:
610
- for key, val in local_scope.iteritems():
611
- if not isinstance(val, (dict, list, tuple, str)):
612
- raise gclient_utils.Error(
613
- 'ParseDepsFile(%s): Strict mode disallows %r -> %r' %
614
- (self.name, key, val))
615
705
 
616
- deps = local_scope.get('deps', {})
617
- if 'recursion' in local_scope:
618
- self.recursion_override = local_scope.get('recursion')
619
- logging.warning(
620
- 'Setting %s recursion to %d.', self.name, self.recursion_limit)
621
- self.recursedeps = None
622
- if 'recursedeps' in local_scope:
623
- self.recursedeps = {}
624
- for ent in local_scope['recursedeps']:
625
- if isinstance(ent, basestring):
626
- self.recursedeps[ent] = {"deps_file": self.deps_file}
627
- else: # (depname, depsfilename)
628
- self.recursedeps[ent[0]] = {"deps_file": ent[1]}
629
- logging.warning('Found recursedeps %r.', repr(self.recursedeps))
630
- # If present, save 'target_os' in the local_target_os property.
631
- if 'target_os' in local_scope:
632
- self.local_target_os = local_scope['target_os']
633
- # load os specific dependencies if defined. these dependencies may
634
- # override or extend the values defined by the 'deps' member.
635
- target_os_list = self.target_os
636
- if 'deps_os' in local_scope and target_os_list:
637
- deps = self.MergeWithOsDeps(deps, local_scope['deps_os'], target_os_list)
706
+ if 'allowed_hosts' in local_scope:
707
+ try:
708
+ self._allowed_hosts = frozenset(local_scope.get('allowed_hosts'))
709
+ except TypeError: # raised if non-iterable
710
+ pass
711
+ if not self._allowed_hosts:
712
+ logging.warning("allowed_hosts is specified but empty %s",
713
+ self._allowed_hosts)
714
+ raise gclient_utils.Error(
715
+ 'ParseDepsFile(%s): allowed_hosts must be absent '
716
+ 'or a non-empty iterable' % self.name)
638
717
 
639
- # If a line is in custom_deps, but not in the solution, we want to append
640
- # this line to the solution.
641
- for d in self.custom_deps:
642
- if d not in deps:
643
- deps[d] = self.custom_deps[d]
718
+ self._gn_args_file = local_scope.get('gclient_gn_args_file')
719
+ self._gn_args = local_scope.get('gclient_gn_args', [])
720
+
721
+ # Since we heavily post-process things, freeze ones which should
722
+ # reflect original state of DEPS.
723
+ self._vars = gclient_utils.freeze(local_scope.get('vars', {}))
644
724
 
645
725
  # If use_relative_paths is set in the DEPS file, regenerate
646
726
  # the dictionary using paths relative to the directory containing
@@ -656,18 +736,24 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
656
736
  rel_prefix = self.name
657
737
  elif self._relative:
658
738
  rel_prefix = os.path.dirname(self.name)
659
- if rel_prefix:
660
- logging.warning('use_relative_paths enabled.')
661
- rel_deps = {}
662
- for d, url in deps.items():
663
- # normpath is required to allow DEPS to use .. in their
664
- # dependency local path.
665
- rel_deps[os.path.normpath(os.path.join(rel_prefix, d))] = url
666
- logging.warning('Updating deps by prepending %s.', rel_prefix)
667
- deps = rel_deps
668
739
 
669
- # Update recursedeps if it's set.
670
- if self.recursedeps is not None:
740
+ deps = local_scope.get('deps', {})
741
+ orig_deps = gclient_utils.freeze(deps)
742
+ if 'recursion' in local_scope:
743
+ self.recursion_override = local_scope.get('recursion')
744
+ logging.warning(
745
+ 'Setting %s recursion to %d.', self.name, self.recursion_limit)
746
+ self.recursedeps = None
747
+ if 'recursedeps' in local_scope:
748
+ self.recursedeps = {}
749
+ for ent in local_scope['recursedeps']:
750
+ if isinstance(ent, basestring):
751
+ self.recursedeps[ent] = {"deps_file": self.deps_file}
752
+ else: # (depname, depsfilename)
753
+ self.recursedeps[ent[0]] = {"deps_file": ent[1]}
754
+ logging.warning('Found recursedeps %r.', repr(self.recursedeps))
755
+
756
+ if rel_prefix:
671
757
  logging.warning('Updating recursedeps by prepending %s.', rel_prefix)
672
758
  rel_deps = {}
673
759
  for depname, options in self.recursedeps.iteritems():
@@ -675,32 +761,24 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
675
761
  os.path.normpath(os.path.join(rel_prefix, depname))] = options
676
762
  self.recursedeps = rel_deps
677
763
 
678
-
679
- if 'allowed_hosts' in local_scope:
680
- try:
681
- self._allowed_hosts = frozenset(local_scope.get('allowed_hosts'))
682
- except TypeError: # raised if non-iterable
683
- pass
684
- if not self._allowed_hosts:
685
- logging.warning("allowed_hosts is specified but empty %s",
686
- self._allowed_hosts)
687
- raise gclient_utils.Error(
688
- 'ParseDepsFile(%s): allowed_hosts must be absent '
689
- 'or a non-empty iterable' % self.name)
690
-
691
- # Convert the deps into real Dependency.
692
- deps_to_add = []
693
- for name, url in deps.iteritems():
694
- should_process = self.recursion_limit and self.should_process
695
- deps_file = self.deps_file
696
- if self.recursedeps is not None:
697
- ent = self.recursedeps.get(name)
698
- if ent is not None:
699
- deps_file = ent['deps_file']
700
- deps_to_add.append(Dependency(
701
- self, name, url, None, None, self.custom_vars, None,
702
- deps_file, should_process, use_relative_paths))
703
- deps_to_add.sort(key=lambda x: x.name)
764
+ # If present, save 'target_os' in the local_target_os property.
765
+ if 'target_os' in local_scope:
766
+ self.local_target_os = local_scope['target_os']
767
+ # load os specific dependencies if defined. these dependencies may
768
+ # override or extend the values defined by the 'deps' member.
769
+ target_os_list = self.target_os
770
+ if 'deps_os' in local_scope:
771
+ for dep_os, os_deps in local_scope['deps_os'].iteritems():
772
+ self._os_dependencies[dep_os] = self._deps_to_objects(
773
+ self._postprocess_deps(os_deps, rel_prefix), use_relative_paths)
774
+ if target_os_list:
775
+ deps = self.MergeWithOsDeps(
776
+ deps, local_scope['deps_os'], target_os_list)
777
+
778
+ deps_to_add = self._deps_to_objects(
779
+ self._postprocess_deps(deps, rel_prefix), use_relative_paths)
780
+ orig_deps_to_add = self._deps_to_objects(
781
+ self._postprocess_deps(orig_deps, rel_prefix), use_relative_paths)
704
782
 
705
783
  # override named sets of hooks by the custom hooks
706
784
  hooks_to_run = []
@@ -708,6 +786,20 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
708
786
  for hook in local_scope.get('hooks', []):
709
787
  if hook.get('name', '') not in hook_names_to_suppress:
710
788
  hooks_to_run.append(hook)
789
+ orig_hooks = gclient_utils.freeze(hooks_to_run)
790
+ if 'hooks_os' in local_scope and target_os_list:
791
+ hooks_os = local_scope['hooks_os']
792
+
793
+ # Keep original contents of hooks_os for flatten.
794
+ for hook_os, os_hooks in hooks_os.iteritems():
795
+ self._os_deps_hooks[hook_os] = [
796
+ Hook.from_dict(hook, variables=self.get_vars())
797
+ for hook in os_hooks]
798
+
799
+ # Specifically append these to ensure that hooks_os run after hooks.
800
+ for the_target_os in target_os_list:
801
+ the_target_os_hooks = hooks_os.get(the_target_os, [])
802
+ hooks_to_run.extend(the_target_os_hooks)
711
803
 
712
804
  # add the replacements and any additions
713
805
  for hook in self.custom_hooks:
@@ -715,18 +807,34 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
715
807
  hooks_to_run.append(hook)
716
808
 
717
809
  if self.recursion_limit:
718
- self._pre_deps_hooks = [self.GetHookAction(hook, []) for hook in
719
- local_scope.get('pre_deps_hooks', [])]
810
+ self._pre_deps_hooks = [
811
+ Hook.from_dict(hook, variables=self.get_vars()) for hook in
812
+ local_scope.get('pre_deps_hooks', [])]
720
813
 
721
- self.add_dependencies_and_close(deps_to_add, hooks_to_run)
814
+ self.add_dependencies_and_close(
815
+ deps_to_add, hooks_to_run, orig_deps_to_add=orig_deps_to_add,
816
+ orig_hooks=orig_hooks)
722
817
  logging.info('ParseDepsFile(%s) done' % self.name)
723
818
 
724
- def add_dependencies_and_close(self, deps_to_add, hooks):
819
+ def _get_option(self, attr, default):
820
+ obj = self
821
+ while not hasattr(obj, '_options'):
822
+ obj = obj.parent
823
+ return getattr(obj._options, attr, default)
824
+
825
+ def add_dependencies_and_close(
826
+ self, deps_to_add, hooks, orig_deps_to_add=None, orig_hooks=None):
725
827
  """Adds the dependencies, hooks and mark the parsing as done."""
726
828
  for dep in deps_to_add:
727
829
  if dep.verify_validity():
728
830
  self.add_dependency(dep)
729
- self._mark_as_parsed(hooks)
831
+ for dep in (orig_deps_to_add if orig_deps_to_add is not None
832
+ else deps_to_add):
833
+ self.add_orig_dependency(dep)
834
+ self._mark_as_parsed(
835
+ [Hook.from_dict(h, variables=self.get_vars()) for h in hooks],
836
+ orig_hooks=[Hook.from_dict(h, variables=self.get_vars())
837
+ for h in (orig_hooks if orig_hooks is not None else hooks)])
730
838
 
731
839
  def findDepsFromNotAllowedHosts(self):
732
840
  """Returns a list of depenecies from not allowed hosts.
@@ -757,10 +865,13 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
757
865
  # When running runhooks, there's no need to consult the SCM.
758
866
  # All known hooks are expected to run unconditionally regardless of working
759
867
  # copy state, so skip the SCM status check.
760
- run_scm = command not in ('runhooks', 'recurse', None)
868
+ run_scm = command not in (
869
+ 'flatten', 'runhooks', 'recurse', 'validate', None)
761
870
  parsed_url = self.LateOverride(self.url)
762
871
  file_list = [] if not options.nohooks else None
763
872
  revision_override = revision_overrides.pop(self.name, None)
873
+ if not revision_override and parsed_url:
874
+ revision_override = revision_overrides.get(parsed_url.split('@')[0], None)
764
875
  if run_scm and parsed_url:
765
876
  # Create a shallow copy to mutate revision.
766
877
  options = copy.copy(options)
@@ -789,6 +900,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
789
900
 
790
901
  # Always parse the DEPS file.
791
902
  self.ParseDepsFile()
903
+ if self._gn_args_file and command == 'update':
904
+ self.WriteGNArgsFile()
792
905
  self._run_is_done(file_list or [], parsed_url)
793
906
  if command in ('update', 'revert') and not options.noprehooks:
794
907
  self.RunPreDepsHooks()
@@ -796,7 +909,8 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
796
909
  if self.recursion_limit:
797
910
  # Parse the dependencies of this dependency.
798
911
  for s in self.dependencies:
799
- work_queue.enqueue(s)
912
+ if s.should_process:
913
+ work_queue.enqueue(s)
800
914
 
801
915
  if command == 'recurse':
802
916
  # Skip file only checkout.
@@ -854,6 +968,12 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
854
968
  else:
855
969
  print('Skipped missing %s' % cwd, file=sys.stderr)
856
970
 
971
+ def WriteGNArgsFile(self):
972
+ lines = ['# Generated from %r' % self.deps_file]
973
+ for arg in self._gn_args:
974
+ lines.append('%s = %s' % (arg, ToGNString(self.get_vars()[arg])))
975
+ with open(os.path.join(self.root.root_dir, self._gn_args_file), 'w') as f:
976
+ f.write('\n'.join(lines))
857
977
 
858
978
  @gclient_utils.lockedmethod
859
979
  def _run_is_done(self, file_list, parsed_url):
@@ -862,22 +982,6 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
862
982
  self._parsed_url = parsed_url
863
983
  self._processed = True
864
984
 
865
- @staticmethod
866
- def GetHookAction(hook_dict, matching_file_list):
867
- """Turns a parsed 'hook' dict into an executable command."""
868
- logging.debug(hook_dict)
869
- logging.debug(matching_file_list)
870
- command = hook_dict['action'][:]
871
- if command[0] == 'python':
872
- # If the hook specified "python" as the first item, the action is a
873
- # Python script. Run it by starting a new copy of the same
874
- # interpreter.
875
- command[0] = sys.executable
876
- if '$matching_files' in command:
877
- splice_index = command.index('$matching_files')
878
- command[splice_index:splice_index + 1] = matching_file_list
879
- return command
880
-
881
985
  def GetHooks(self, options):
882
986
  """Evaluates all hooks, and return them in a flat list.
883
987
 
@@ -896,18 +1000,11 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
896
1000
  if (options.force or
897
1001
  gclient_scm.GetScmName(self.parsed_url) in ('git', None) or
898
1002
  os.path.isdir(os.path.join(self.root.root_dir, self.name, '.git'))):
899
- for hook_dict in self.deps_hooks:
900
- result.append(self.GetHookAction(hook_dict, []))
1003
+ result.extend(self.deps_hooks)
901
1004
  else:
902
- # Run hooks on the basis of whether the files from the gclient operation
903
- # match each hook's pattern.
904
- for hook_dict in self.deps_hooks:
905
- pattern = re.compile(hook_dict['pattern'])
906
- matching_file_list = [
907
- f for f in self.file_list_and_children if pattern.search(f)
908
- ]
909
- if matching_file_list:
910
- result.append(self.GetHookAction(hook_dict, matching_file_list))
1005
+ for hook in self.deps_hooks:
1006
+ if hook.matches(self.file_list_and_children):
1007
+ result.append(hook)
911
1008
  for s in self.dependencies:
912
1009
  result.extend(s.GetHooks(options))
913
1010
  return result
@@ -916,21 +1013,7 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
916
1013
  assert self.hooks_ran == False
917
1014
  self._hooks_ran = True
918
1015
  for hook in self.GetHooks(options):
919
- try:
920
- start_time = time.time()
921
- gclient_utils.CheckCallAndFilterAndHeader(
922
- hook, cwd=self.root.root_dir, always=True)
923
- except (gclient_utils.Error, subprocess2.CalledProcessError) as e:
924
- # Use a discrete exit status code of 2 to indicate that a hook action
925
- # failed. Users of this script may wish to treat hook action failures
926
- # differently from VC failures.
927
- print('Error: %s' % str(e), file=sys.stderr)
928
- sys.exit(2)
929
- finally:
930
- elapsed_time = time.time() - start_time
931
- if elapsed_time > 10:
932
- print("Hook '%s' took %.2f secs" % (
933
- gclient_utils.CommandToStr(hook), elapsed_time))
1016
+ hook.run(self.root.root_dir)
934
1017
 
935
1018
  def RunPreDepsHooks(self):
936
1019
  assert self.processed
@@ -941,22 +1024,7 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
941
1024
  assert not s.processed
942
1025
  self._pre_deps_hooks_ran = True
943
1026
  for hook in self.pre_deps_hooks:
944
- try:
945
- start_time = time.time()
946
- gclient_utils.CheckCallAndFilterAndHeader(
947
- hook, cwd=self.root.root_dir, always=True)
948
- except (gclient_utils.Error, subprocess2.CalledProcessError) as e:
949
- # Use a discrete exit status code of 2 to indicate that a hook action
950
- # failed. Users of this script may wish to treat hook action failures
951
- # differently from VC failures.
952
- print('Error: %s' % str(e), file=sys.stderr)
953
- sys.exit(2)
954
- finally:
955
- elapsed_time = time.time() - start_time
956
- if elapsed_time > 10:
957
- print("Hook '%s' took %.2f secs" % (
958
- gclient_utils.CommandToStr(hook), elapsed_time))
959
-
1027
+ hook.run(self.root.root_dir)
960
1028
 
961
1029
  def subtree(self, include_all):
962
1030
  """Breadth first recursion excluding root node."""
@@ -968,21 +1036,18 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
968
1036
  for i in d.subtree(include_all):
969
1037
  yield i
970
1038
 
971
- def depth_first_tree(self):
972
- """Depth-first recursion including the root node."""
973
- yield self
974
- for i in self.dependencies:
975
- for j in i.depth_first_tree():
976
- if j.should_process:
977
- yield j
978
-
979
1039
  @gclient_utils.lockedmethod
980
1040
  def add_dependency(self, new_dep):
981
1041
  self._dependencies.append(new_dep)
982
1042
 
983
1043
  @gclient_utils.lockedmethod
984
- def _mark_as_parsed(self, new_hooks):
1044
+ def add_orig_dependency(self, new_dep):
1045
+ self._orig_dependencies.append(new_dep)
1046
+
1047
+ @gclient_utils.lockedmethod
1048
+ def _mark_as_parsed(self, new_hooks, orig_hooks=None):
985
1049
  self._deps_hooks.extend(new_hooks)
1050
+ self._orig_deps_hooks.extend(orig_hooks or new_hooks)
986
1051
  self._deps_parsed = True
987
1052
 
988
1053
  @property
@@ -990,11 +1055,31 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
990
1055
  def dependencies(self):
991
1056
  return tuple(self._dependencies)
992
1057
 
1058
+ @property
1059
+ @gclient_utils.lockedmethod
1060
+ def orig_dependencies(self):
1061
+ return tuple(self._orig_dependencies)
1062
+
1063
+ @property
1064
+ @gclient_utils.lockedmethod
1065
+ def os_dependencies(self):
1066
+ return dict(self._os_dependencies)
1067
+
993
1068
  @property
994
1069
  @gclient_utils.lockedmethod
995
1070
  def deps_hooks(self):
996
1071
  return tuple(self._deps_hooks)
997
1072
 
1073
+ @property
1074
+ @gclient_utils.lockedmethod
1075
+ def orig_deps_hooks(self):
1076
+ return tuple(self._orig_deps_hooks)
1077
+
1078
+ @property
1079
+ @gclient_utils.lockedmethod
1080
+ def os_deps_hooks(self):
1081
+ return dict(self._os_deps_hooks)
1082
+
998
1083
  @property
999
1084
  @gclient_utils.lockedmethod
1000
1085
  def pre_deps_hooks(self):
@@ -1075,15 +1160,26 @@ class Dependency(gclient_utils.WorkItem, DependencySettings):
1075
1160
  def __repr__(self):
1076
1161
  return '%s: %s' % (self.name, self.url)
1077
1162
 
1078
- def hierarchy(self):
1163
+ def hierarchy(self, include_url=True):
1079
1164
  """Returns a human-readable hierarchical reference to a Dependency."""
1080
- out = '%s(%s)' % (self.name, self.url)
1165
+ def format_name(d):
1166
+ if include_url:
1167
+ return '%s(%s)' % (d.name, d.url)
1168
+ return d.name
1169
+ out = format_name(self)
1081
1170
  i = self.parent
1082
1171
  while i and i.name:
1083
- out = '%s(%s) -> %s' % (i.name, i.url, out)
1172
+ out = '%s -> %s' % (format_name(i), out)
1084
1173
  i = i.parent
1085
1174
  return out
1086
1175
 
1176
+ def get_vars(self):
1177
+ """Returns a dictionary of effective variable values
1178
+ (DEPS file contents with applied custom_vars overrides)."""
1179
+ result = dict(self._vars)
1180
+ result.update(self.custom_vars or {})
1181
+ return result
1182
+
1087
1183
 
1088
1184
  class GClient(Dependency):
1089
1185
  """Object that represent a gclient checkout. A tree of Dependency(), one per
@@ -1136,7 +1232,7 @@ solutions = [
1136
1232
  # are processed.
1137
1233
  self._recursion_limit = 2
1138
1234
  Dependency.__init__(self, None, None, None, True, None, None, None,
1139
- 'unused', True, None)
1235
+ 'unused', True, None, None, True)
1140
1236
  self._options = options
1141
1237
  if options.deps_os:
1142
1238
  enforced_os = options.deps_os.split(',')
@@ -1225,7 +1321,9 @@ it or fix the checkout.
1225
1321
  s.get('custom_hooks', []),
1226
1322
  s.get('deps_file', 'DEPS'),
1227
1323
  True,
1228
- None))
1324
+ None,
1325
+ None,
1326
+ True))
1229
1327
  except KeyError:
1230
1328
  raise gclient_utils.Error('Invalid .gclient file. Solution is '
1231
1329
  'incomplete: %s' % s)
@@ -1309,7 +1407,7 @@ it or fix the checkout.
1309
1407
  exec(gclient_utils.FileRead(filename), scope)
1310
1408
  except SyntaxError as e:
1311
1409
  gclient_utils.SyntaxErrorToError(filename, e)
1312
- return scope['entries']
1410
+ return scope.get('entries', {})
1313
1411
 
1314
1412
  def _EnforceRevisions(self):
1315
1413
  """Checks for revision overrides."""
@@ -1346,7 +1444,8 @@ it or fix the checkout.
1346
1444
  revision_overrides = {}
1347
1445
  # It's unnecessary to check for revision overrides for 'recurse'.
1348
1446
  # Save a few seconds by not calling _EnforceRevisions() in that case.
1349
- if command not in ('diff', 'recurse', 'runhooks', 'status', 'revert'):
1447
+ if command not in ('diff', 'recurse', 'runhooks', 'status', 'revert',
1448
+ 'validate'):
1350
1449
  self._CheckConfig()
1351
1450
  revision_overrides = self._EnforceRevisions()
1352
1451
  pm = None
@@ -1354,13 +1453,14 @@ it or fix the checkout.
1354
1453
  if (setup_color.IS_TTY and not self._options.verbose and progress):
1355
1454
  if command in ('update', 'revert'):
1356
1455
  pm = Progress('Syncing projects', 1)
1357
- elif command == 'recurse':
1456
+ elif command in ('recurse', 'validate'):
1358
1457
  pm = Progress(' '.join(args), 1)
1359
1458
  work_queue = gclient_utils.ExecutionQueue(
1360
1459
  self._options.jobs, pm, ignore_requirements=ignore_requirements,
1361
1460
  verbose=self._options.verbose)
1362
1461
  for s in self.dependencies:
1363
- work_queue.enqueue(s)
1462
+ if s.should_process:
1463
+ work_queue.enqueue(s)
1364
1464
  work_queue.flush(revision_overrides, command, args, options=self._options)
1365
1465
  if revision_overrides:
1366
1466
  print('Please fix your script, having invalid --revision flags will soon '
@@ -1472,7 +1572,8 @@ it or fix the checkout.
1472
1572
  work_queue = gclient_utils.ExecutionQueue(
1473
1573
  self._options.jobs, None, False, verbose=self._options.verbose)
1474
1574
  for s in self.dependencies:
1475
- work_queue.enqueue(s)
1575
+ if s.should_process:
1576
+ work_queue.enqueue(s)
1476
1577
  work_queue.flush({}, None, [], options=self._options)
1477
1578
 
1478
1579
  def GetURLAndRev(dep):
@@ -1616,6 +1717,292 @@ def CMDfetch(parser, args):
1616
1717
  '--jobs=%d' % options.jobs, '--scm=git', 'git', 'fetch'] + args)
1617
1718
 
1618
1719
 
1720
+ class Flattener(object):
1721
+ """Flattens a gclient solution."""
1722
+
1723
+ def __init__(self, client, pin_all_deps=False):
1724
+ """Constructor.
1725
+
1726
+ Arguments:
1727
+ client (GClient): client to flatten
1728
+ pin_all_deps (bool): whether to pin all deps, even if they're not pinned
1729
+ in DEPS
1730
+ """
1731
+ self._client = client
1732
+
1733
+ self._deps_string = None
1734
+
1735
+ self._allowed_hosts = set()
1736
+ self._deps = {}
1737
+ self._deps_os = {}
1738
+ self._hooks = []
1739
+ self._hooks_os = {}
1740
+ self._pre_deps_hooks = []
1741
+ self._vars = {}
1742
+
1743
+ self._flatten(pin_all_deps=pin_all_deps)
1744
+
1745
+ @property
1746
+ def deps_string(self):
1747
+ assert self._deps_string is not None
1748
+ return self._deps_string
1749
+
1750
+ def _flatten(self, pin_all_deps=False):
1751
+ """Runs the flattener. Saves resulting DEPS string.
1752
+
1753
+ Arguments:
1754
+ pin_all_deps (bool): whether to pin all deps, even if they're not pinned
1755
+ in DEPS
1756
+ """
1757
+ for solution in self._client.dependencies:
1758
+ self._flatten_solution(solution)
1759
+
1760
+ if pin_all_deps:
1761
+ for dep in self._deps.itervalues():
1762
+ if dep.parsed_url is None:
1763
+ continue
1764
+ url, revision = gclient_utils.SplitUrlRevision(dep.parsed_url)
1765
+ if revision and gclient_utils.IsGitSha(revision):
1766
+ continue
1767
+ scm = gclient_scm.CreateSCM(
1768
+ dep.parsed_url, self._client.root_dir, dep.name, dep.outbuf)
1769
+ dep._parsed_url = dep._url = '%s@%s' % (
1770
+ url, scm.revinfo(self._client._options, [], None))
1771
+
1772
+ self._deps_string = '\n'.join(
1773
+ _GNSettingsToLines(
1774
+ self._client.dependencies[0]._gn_args_file,
1775
+ self._client.dependencies[0]._gn_args) +
1776
+ _AllowedHostsToLines(self._allowed_hosts) +
1777
+ _DepsToLines(self._deps) +
1778
+ _DepsOsToLines(self._deps_os) +
1779
+ _HooksToLines('hooks', self._hooks) +
1780
+ _HooksToLines('pre_deps_hooks', self._pre_deps_hooks) +
1781
+ _HooksOsToLines(self._hooks_os) +
1782
+ _VarsToLines(self._vars) +
1783
+ ['']) # Ensure newline at end of file.
1784
+
1785
+ def _flatten_solution(self, solution):
1786
+ """Visits a solution in order to flatten it (see CMDflatten).
1787
+
1788
+ Arguments:
1789
+ solution (Dependency): one of top-level solutions in .gclient
1790
+ """
1791
+ self._flatten_dep(solution)
1792
+ self._flatten_recurse(solution)
1793
+
1794
+ def _flatten_dep(self, dep):
1795
+ """Visits a dependency in order to flatten it (see CMDflatten).
1796
+
1797
+ Arguments:
1798
+ dep (Dependency): dependency to process
1799
+ """
1800
+ self._allowed_hosts.update(dep.allowed_hosts)
1801
+
1802
+ assert dep.name not in self._deps
1803
+ self._deps[dep.name] = dep
1804
+
1805
+ for key, value in dep.get_vars().iteritems():
1806
+ assert key not in self._vars
1807
+ self._vars[key] = (dep, value)
1808
+
1809
+ self._hooks.extend([(dep, hook) for hook in dep.orig_deps_hooks])
1810
+ self._pre_deps_hooks.extend([(dep, hook) for hook in dep.pre_deps_hooks])
1811
+
1812
+ for hook_os, os_hooks in dep.os_deps_hooks.iteritems():
1813
+ self._hooks_os.setdefault(hook_os, []).extend(
1814
+ [(dep, hook) for hook in os_hooks])
1815
+
1816
+ self._add_deps_os(dep)
1817
+
1818
+ deps_by_name = dict((d.name, d) for d in dep.dependencies)
1819
+ for recurse_dep_name in (dep.recursedeps or []):
1820
+ self._flatten_recurse(deps_by_name[recurse_dep_name])
1821
+
1822
+ def _flatten_recurse(self, dep):
1823
+ """Helper for flatten that recurses into |dep|'s dependencies.
1824
+
1825
+ Arguments:
1826
+ dep (Dependency): dependency to process
1827
+ """
1828
+ self._add_deps_os(dep)
1829
+
1830
+ for sub_dep in dep.orig_dependencies:
1831
+ self._flatten_dep(sub_dep)
1832
+
1833
+ def _add_deps_os(self, dep):
1834
+ """Helper for flatten that collects deps_os from |dep|.
1835
+
1836
+ Arguments:
1837
+ dep (Dependency): dependency to process
1838
+ """
1839
+ for dep_os, os_deps in dep.os_dependencies.iteritems():
1840
+ for os_dep in os_deps:
1841
+ self._deps_os.setdefault(dep_os, {})[os_dep.name] = os_dep
1842
+
1843
+
1844
+ def CMDflatten(parser, args):
1845
+ """Flattens the solutions into a single DEPS file."""
1846
+ parser.add_option('--output-deps', help='Path to the output DEPS file')
1847
+ parser.add_option(
1848
+ '--pin-all-deps', action='store_true',
1849
+ help=('Pin all deps, even if not pinned in DEPS. CAVEAT: only does so '
1850
+ 'for checked out deps, NOT deps_os.'))
1851
+ options, args = parser.parse_args(args)
1852
+
1853
+ options.nohooks = True
1854
+ client = GClient.LoadCurrentConfig(options)
1855
+
1856
+ # Only print progress if we're writing to a file. Otherwise, progress updates
1857
+ # could obscure intended output.
1858
+ code = client.RunOnDeps('flatten', args, progress=options.output_deps)
1859
+ if code != 0:
1860
+ return code
1861
+
1862
+ flattener = Flattener(client, pin_all_deps=options.pin_all_deps)
1863
+
1864
+ if options.output_deps:
1865
+ with open(options.output_deps, 'w') as f:
1866
+ f.write(flattener.deps_string)
1867
+ else:
1868
+ print(flattener.deps_string)
1869
+
1870
+ return 0
1871
+
1872
+
1873
+ def _GNSettingsToLines(gn_args_file, gn_args):
1874
+ s = []
1875
+ if gn_args_file:
1876
+ s.extend([
1877
+ 'gclient_gn_args_file = "%s"' % gn_args_file,
1878
+ 'gclient_gn_args = %r' % gn_args,
1879
+ ])
1880
+ return s
1881
+
1882
+
1883
+ def _AllowedHostsToLines(allowed_hosts):
1884
+ """Converts |allowed_hosts| set to list of lines for output."""
1885
+ if not allowed_hosts:
1886
+ return []
1887
+ s = ['allowed_hosts = [']
1888
+ for h in sorted(allowed_hosts):
1889
+ s.append(' "%s",' % h)
1890
+ s.extend([']', ''])
1891
+ return s
1892
+
1893
+
1894
+ def _DepsToLines(deps):
1895
+ """Converts |deps| dict to list of lines for output."""
1896
+ if not deps:
1897
+ return []
1898
+ s = ['deps = {']
1899
+ for name, dep in sorted(deps.iteritems()):
1900
+ condition_part = ([' "condition": "%s",' % dep.condition]
1901
+ if dep.condition else [])
1902
+ s.extend([
1903
+ ' # %s' % dep.hierarchy(include_url=False),
1904
+ ' "%s": {' % (name,),
1905
+ ' "url": "%s",' % (dep.url,),
1906
+ ] + condition_part + [
1907
+ ' },',
1908
+ '',
1909
+ ])
1910
+ s.extend(['}', ''])
1911
+ return s
1912
+
1913
+
1914
+ def _DepsOsToLines(deps_os):
1915
+ """Converts |deps_os| dict to list of lines for output."""
1916
+ if not deps_os:
1917
+ return []
1918
+ s = ['deps_os = {']
1919
+ for dep_os, os_deps in sorted(deps_os.iteritems()):
1920
+ s.append(' "%s": {' % dep_os)
1921
+ for name, dep in sorted(os_deps.iteritems()):
1922
+ condition_part = ([' "condition": "%s",' % dep.condition]
1923
+ if dep.condition else [])
1924
+ s.extend([
1925
+ ' # %s' % dep.hierarchy(include_url=False),
1926
+ ' "%s": {' % (name,),
1927
+ ' "url": "%s",' % (dep.url,),
1928
+ ] + condition_part + [
1929
+ ' },',
1930
+ '',
1931
+ ])
1932
+ s.extend([' },', ''])
1933
+ s.extend(['}', ''])
1934
+ return s
1935
+
1936
+
1937
+ def _HooksToLines(name, hooks):
1938
+ """Converts |hooks| list to list of lines for output."""
1939
+ if not hooks:
1940
+ return []
1941
+ s = ['%s = [' % name]
1942
+ for dep, hook in hooks:
1943
+ s.extend([
1944
+ ' # %s' % dep.hierarchy(include_url=False),
1945
+ ' {',
1946
+ ])
1947
+ if hook.name is not None:
1948
+ s.append(' "name": "%s",' % hook.name)
1949
+ if hook.pattern is not None:
1950
+ s.append(' "pattern": "%s",' % hook.pattern)
1951
+ s.extend(
1952
+ # Hooks run in the parent directory of their dep.
1953
+ [' "cwd": "%s",' % os.path.normpath(os.path.dirname(dep.name))] +
1954
+ [' "action": ['] +
1955
+ [' "%s",' % arg for arg in hook.action] +
1956
+ [' ]', ' },', '']
1957
+ )
1958
+ s.extend([']', ''])
1959
+ return s
1960
+
1961
+
1962
+ def _HooksOsToLines(hooks_os):
1963
+ """Converts |hooks| list to list of lines for output."""
1964
+ if not hooks_os:
1965
+ return []
1966
+ s = ['hooks_os = {']
1967
+ for hook_os, os_hooks in hooks_os.iteritems():
1968
+ s.append(' "%s": [' % hook_os)
1969
+ for dep, hook in os_hooks:
1970
+ s.extend([
1971
+ ' # %s' % dep.hierarchy(include_url=False),
1972
+ ' {',
1973
+ ])
1974
+ if hook.name is not None:
1975
+ s.append(' "name": "%s",' % hook.name)
1976
+ if hook.pattern is not None:
1977
+ s.append(' "pattern": "%s",' % hook.pattern)
1978
+ s.extend(
1979
+ # Hooks run in the parent directory of their dep.
1980
+ [' "cwd": "%s",' % os.path.normpath(os.path.dirname(dep.name))] +
1981
+ [' "action": ['] +
1982
+ [' "%s",' % arg for arg in hook.action] +
1983
+ [' ]', ' },', '']
1984
+ )
1985
+ s.extend([' ],', ''])
1986
+ s.extend(['}', ''])
1987
+ return s
1988
+
1989
+
1990
+ def _VarsToLines(variables):
1991
+ """Converts |variables| dict to list of lines for output."""
1992
+ if not variables:
1993
+ return []
1994
+ s = ['vars = {']
1995
+ for key, tup in sorted(variables.iteritems()):
1996
+ dep, value = tup
1997
+ s.extend([
1998
+ ' # %s' % dep.hierarchy(include_url=False),
1999
+ ' "%s": %r,' % (key, value),
2000
+ '',
2001
+ ])
2002
+ s.extend(['}', ''])
2003
+ return s
2004
+
2005
+
1619
2006
  def CMDgrep(parser, args):
1620
2007
  """Greps through git repos managed by gclient.
1621
2008
 
@@ -1862,6 +2249,12 @@ def CMDsync(parser, args):
1862
2249
  help='DEPRECATED: This is a no-op.')
1863
2250
  parser.add_option('-m', '--manually_grab_svn_rev', action='store_true',
1864
2251
  help='DEPRECATED: This is a no-op.')
2252
+ # TODO(phajdan.jr): Remove validation options once default (crbug/570091).
2253
+ parser.add_option('--validate-syntax', action='store_true', default=True,
2254
+ help='Validate the .gclient and DEPS syntax')
2255
+ parser.add_option('--disable-syntax-validation', action='store_false',
2256
+ dest='validate_syntax',
2257
+ help='Disable validation of .gclient and DEPS syntax.')
1865
2258
  (options, args) = parser.parse_args(args)
1866
2259
  client = GClient.LoadCurrentConfig(options)
1867
2260
 
@@ -1892,6 +2285,19 @@ def CMDsync(parser, args):
1892
2285
  CMDupdate = CMDsync
1893
2286
 
1894
2287
 
2288
+ def CMDvalidate(parser, args):
2289
+ """Validates the .gclient and DEPS syntax."""
2290
+ options, args = parser.parse_args(args)
2291
+ options.validate_syntax = True
2292
+ client = GClient.LoadCurrentConfig(options)
2293
+ rv = client.RunOnDeps('validate', args)
2294
+ if rv == 0:
2295
+ print('validate: SUCCESS')
2296
+ else:
2297
+ print('validate: FAILURE')
2298
+ return rv
2299
+
2300
+
1895
2301
  def CMDdiff(parser, args):
1896
2302
  """Displays local diff for every dependencies."""
1897
2303
  parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
@@ -1985,18 +2391,6 @@ def CMDrevinfo(parser, args):
1985
2391
  return 0
1986
2392
 
1987
2393
 
1988
- def CMDhookinfo(parser, args):
1989
- """Outputs the hooks that would be run by `gclient runhooks`."""
1990
- (options, args) = parser.parse_args(args)
1991
- options.force = True
1992
- client = GClient.LoadCurrentConfig(options)
1993
- if not client:
1994
- raise gclient_utils.Error('client not configured; see \'gclient config\'')
1995
- client.RunOnDeps(None, [])
1996
- print('; '.join(' '.join(hook) for hook in client.GetHooks(options)))
1997
- return 0
1998
-
1999
-
2000
2394
  def CMDverify(parser, args):
2001
2395
  """Verifies the DEPS file deps are only from allowed_hosts."""
2002
2396
  (options, args) = parser.parse_args(args)