libv8 8.4.255.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (639) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +19 -0
  3. data/.gitmodules +3 -0
  4. data/.rspec +3 -0
  5. data/.travis.yml +45 -0
  6. data/CHANGELOG.md +111 -0
  7. data/Gemfile +4 -0
  8. data/README.md +152 -0
  9. data/Rakefile +125 -0
  10. data/appveyor.yml.disabled +36 -0
  11. data/ext/libv8/arch.rb +20 -0
  12. data/ext/libv8/builder.rb +106 -0
  13. data/ext/libv8/extconf.rb +7 -0
  14. data/ext/libv8/location.rb +89 -0
  15. data/ext/libv8/paths.rb +28 -0
  16. data/lib/libv8.rb +9 -0
  17. data/lib/libv8/version.rb +3 -0
  18. data/libv8.gemspec +30 -0
  19. data/scaleway.png +0 -0
  20. data/spec/location_spec.rb +69 -0
  21. data/spec/spec_helper.rb +4 -0
  22. data/thefrontside.png +0 -0
  23. data/vendor/depot_tools/.cipd_impl.ps1 +129 -0
  24. data/vendor/depot_tools/.gitattributes +55 -0
  25. data/vendor/depot_tools/.gitignore +92 -0
  26. data/vendor/depot_tools/.style.yapf +4 -0
  27. data/vendor/depot_tools/.vpython +55 -0
  28. data/vendor/depot_tools/.vpython3 +23 -0
  29. data/vendor/depot_tools/CROS_OWNERS +7 -0
  30. data/vendor/depot_tools/GOMA_OWNERS +9 -0
  31. data/vendor/depot_tools/LICENSE +27 -0
  32. data/vendor/depot_tools/LUCI_OWNERS +5 -0
  33. data/vendor/depot_tools/OWNERS +39 -0
  34. data/vendor/depot_tools/PRESUBMIT.py +150 -0
  35. data/vendor/depot_tools/README.gclient.md +67 -0
  36. data/vendor/depot_tools/README.git-cl.md +99 -0
  37. data/vendor/depot_tools/README.md +78 -0
  38. data/vendor/depot_tools/WATCHLISTS +26 -0
  39. data/vendor/depot_tools/auth.py +163 -0
  40. data/vendor/depot_tools/autoninja +36 -0
  41. data/vendor/depot_tools/autoninja.bat +33 -0
  42. data/vendor/depot_tools/autoninja.py +148 -0
  43. data/vendor/depot_tools/bb +12 -0
  44. data/vendor/depot_tools/bb.bat +7 -0
  45. data/vendor/depot_tools/bootstrap/README.md +155 -0
  46. data/vendor/depot_tools/bootstrap/bootstrap.py +356 -0
  47. data/vendor/depot_tools/bootstrap/git-bash.template.sh +12 -0
  48. data/vendor/depot_tools/bootstrap/git.template.bat +5 -0
  49. data/vendor/depot_tools/bootstrap/manifest.txt +27 -0
  50. data/vendor/depot_tools/bootstrap/manifest_bleeding_edge.txt +27 -0
  51. data/vendor/depot_tools/bootstrap/profile.d.python.sh +20 -0
  52. data/vendor/depot_tools/bootstrap/python27.bat +46 -0
  53. data/vendor/depot_tools/bootstrap/python3.bat +46 -0
  54. data/vendor/depot_tools/bootstrap/win_tools.bat +79 -0
  55. data/vendor/depot_tools/bootstrap_python3 +35 -0
  56. data/vendor/depot_tools/breakpad.py +12 -0
  57. data/vendor/depot_tools/cbuildbot +1 -0
  58. data/vendor/depot_tools/chrome_set_ver +1 -0
  59. data/vendor/depot_tools/cipd +247 -0
  60. data/vendor/depot_tools/cipd.bat +67 -0
  61. data/vendor/depot_tools/cipd_bin_setup.bat +6 -0
  62. data/vendor/depot_tools/cipd_bin_setup.sh +22 -0
  63. data/vendor/depot_tools/cipd_client_version +1 -0
  64. data/vendor/depot_tools/cipd_client_version.digests +22 -0
  65. data/vendor/depot_tools/cipd_manifest.txt +63 -0
  66. data/vendor/depot_tools/cipd_manifest.versions +438 -0
  67. data/vendor/depot_tools/cit +8 -0
  68. data/vendor/depot_tools/cit.bat +12 -0
  69. data/vendor/depot_tools/cit.py +167 -0
  70. data/vendor/depot_tools/clang-format +8 -0
  71. data/vendor/depot_tools/clang-format.bat +12 -0
  72. data/vendor/depot_tools/clang_format.py +79 -0
  73. data/vendor/depot_tools/clang_format_merge_driver +8 -0
  74. data/vendor/depot_tools/clang_format_merge_driver.bat +12 -0
  75. data/vendor/depot_tools/clang_format_merge_driver.py +69 -0
  76. data/vendor/depot_tools/codereview.settings +6 -0
  77. data/vendor/depot_tools/compile_single_file +8 -0
  78. data/vendor/depot_tools/compile_single_file.bat +11 -0
  79. data/vendor/depot_tools/compile_single_file.py +79 -0
  80. data/vendor/depot_tools/cpplint.bat +11 -0
  81. data/vendor/depot_tools/cpplint.py +6097 -0
  82. data/vendor/depot_tools/cpplint_chromium.py +50 -0
  83. data/vendor/depot_tools/cros +87 -0
  84. data/vendor/depot_tools/cros_sdk +1 -0
  85. data/vendor/depot_tools/crosjobs +13 -0
  86. data/vendor/depot_tools/detect_host_arch.py +55 -0
  87. data/vendor/depot_tools/dirmd +12 -0
  88. data/vendor/depot_tools/dirmd.bat +7 -0
  89. data/vendor/depot_tools/download_from_google_storage +8 -0
  90. data/vendor/depot_tools/download_from_google_storage.bat +12 -0
  91. data/vendor/depot_tools/download_from_google_storage.py +634 -0
  92. data/vendor/depot_tools/ensure_bootstrap +53 -0
  93. data/vendor/depot_tools/fetch +21 -0
  94. data/vendor/depot_tools/fetch.bat +28 -0
  95. data/vendor/depot_tools/fetch.py +319 -0
  96. data/vendor/depot_tools/fetch_configs/android.py +34 -0
  97. data/vendor/depot_tools/fetch_configs/android_internal.py +34 -0
  98. data/vendor/depot_tools/fetch_configs/breakpad.py +44 -0
  99. data/vendor/depot_tools/fetch_configs/chromium.py +66 -0
  100. data/vendor/depot_tools/fetch_configs/config_util.py +52 -0
  101. data/vendor/depot_tools/fetch_configs/crashpad.py +41 -0
  102. data/vendor/depot_tools/fetch_configs/dart.py +45 -0
  103. data/vendor/depot_tools/fetch_configs/depot_tools.py +44 -0
  104. data/vendor/depot_tools/fetch_configs/devtools-frontend.py +44 -0
  105. data/vendor/depot_tools/fetch_configs/goma_client.py +41 -0
  106. data/vendor/depot_tools/fetch_configs/gyp.py +41 -0
  107. data/vendor/depot_tools/fetch_configs/infra.py +40 -0
  108. data/vendor/depot_tools/fetch_configs/infra_internal.py +45 -0
  109. data/vendor/depot_tools/fetch_configs/inspector_protocol.py +40 -0
  110. data/vendor/depot_tools/fetch_configs/ios.py +34 -0
  111. data/vendor/depot_tools/fetch_configs/ios_internal.py +39 -0
  112. data/vendor/depot_tools/fetch_configs/nacl.py +48 -0
  113. data/vendor/depot_tools/fetch_configs/naclports.py +47 -0
  114. data/vendor/depot_tools/fetch_configs/node-ci.py +41 -0
  115. data/vendor/depot_tools/fetch_configs/pdfium.py +40 -0
  116. data/vendor/depot_tools/fetch_configs/skia.py +41 -0
  117. data/vendor/depot_tools/fetch_configs/skia_buildbot.py +41 -0
  118. data/vendor/depot_tools/fetch_configs/syzygy.py +41 -0
  119. data/vendor/depot_tools/fetch_configs/v8.py +44 -0
  120. data/vendor/depot_tools/fetch_configs/webrtc.py +52 -0
  121. data/vendor/depot_tools/fetch_configs/webrtc_android.py +34 -0
  122. data/vendor/depot_tools/fetch_configs/webrtc_ios.py +34 -0
  123. data/vendor/depot_tools/fix_encoding.py +385 -0
  124. data/vendor/depot_tools/gclient +38 -0
  125. data/vendor/depot_tools/gclient-new-workdir.py +124 -0
  126. data/vendor/depot_tools/gclient.bat +32 -0
  127. data/vendor/depot_tools/gclient.py +3198 -0
  128. data/vendor/depot_tools/gclient_completion.sh +76 -0
  129. data/vendor/depot_tools/gclient_eval.py +891 -0
  130. data/vendor/depot_tools/gclient_paths.py +152 -0
  131. data/vendor/depot_tools/gclient_scm.py +1615 -0
  132. data/vendor/depot_tools/gclient_utils.py +1280 -0
  133. data/vendor/depot_tools/gerrit_client.py +151 -0
  134. data/vendor/depot_tools/gerrit_util.py +996 -0
  135. data/vendor/depot_tools/git-cache +6 -0
  136. data/vendor/depot_tools/git-cl +6 -0
  137. data/vendor/depot_tools/git-crrev-parse +53 -0
  138. data/vendor/depot_tools/git-drover +6 -0
  139. data/vendor/depot_tools/git-find-releases +6 -0
  140. data/vendor/depot_tools/git-footers +6 -0
  141. data/vendor/depot_tools/git-freeze +8 -0
  142. data/vendor/depot_tools/git-gs +9 -0
  143. data/vendor/depot_tools/git-hyper-blame +6 -0
  144. data/vendor/depot_tools/git-map +6 -0
  145. data/vendor/depot_tools/git-map-branches +6 -0
  146. data/vendor/depot_tools/git-mark-merge-base +6 -0
  147. data/vendor/depot_tools/git-nav-downstream +6 -0
  148. data/vendor/depot_tools/git-nav-upstream +6 -0
  149. data/vendor/depot_tools/git-new-branch +6 -0
  150. data/vendor/depot_tools/git-number +6 -0
  151. data/vendor/depot_tools/git-rebase-update +6 -0
  152. data/vendor/depot_tools/git-rename-branch +6 -0
  153. data/vendor/depot_tools/git-reparent-branch +6 -0
  154. data/vendor/depot_tools/git-retry +8 -0
  155. data/vendor/depot_tools/git-runhooks +23 -0
  156. data/vendor/depot_tools/git-squash-branch +6 -0
  157. data/vendor/depot_tools/git-templates/description +3 -0
  158. data/vendor/depot_tools/git-templates/hooks/applypatch-msg +4 -0
  159. data/vendor/depot_tools/git-templates/hooks/post-applypatch +4 -0
  160. data/vendor/depot_tools/git-templates/hooks/post-checkout +4 -0
  161. data/vendor/depot_tools/git-templates/hooks/post-commit +4 -0
  162. data/vendor/depot_tools/git-templates/hooks/post-merge +4 -0
  163. data/vendor/depot_tools/git-templates/hooks/post-update +4 -0
  164. data/vendor/depot_tools/git-templates/hooks/pre-applypatch +4 -0
  165. data/vendor/depot_tools/git-templates/hooks/pre-auto-gc +4 -0
  166. data/vendor/depot_tools/git-templates/hooks/pre-commit +4 -0
  167. data/vendor/depot_tools/git-templates/hooks/pre-rebase +4 -0
  168. data/vendor/depot_tools/git-templates/hooks/prepare-commit-msg +4 -0
  169. data/vendor/depot_tools/git-templates/info/exclude +6 -0
  170. data/vendor/depot_tools/git-thaw +13 -0
  171. data/vendor/depot_tools/git-upstream-diff +9 -0
  172. data/vendor/depot_tools/git_cache.py +786 -0
  173. data/vendor/depot_tools/git_cl.py +5158 -0
  174. data/vendor/depot_tools/git_cl_completion.sh +48 -0
  175. data/vendor/depot_tools/git_common.py +1101 -0
  176. data/vendor/depot_tools/git_dates.py +62 -0
  177. data/vendor/depot_tools/git_drover.py +469 -0
  178. data/vendor/depot_tools/git_find_releases.py +67 -0
  179. data/vendor/depot_tools/git_footers.py +261 -0
  180. data/vendor/depot_tools/git_freezer.py +40 -0
  181. data/vendor/depot_tools/git_hyper_blame.py +391 -0
  182. data/vendor/depot_tools/git_map.py +166 -0
  183. data/vendor/depot_tools/git_map_branches.py +354 -0
  184. data/vendor/depot_tools/git_mark_merge_base.py +73 -0
  185. data/vendor/depot_tools/git_nav_downstream.py +69 -0
  186. data/vendor/depot_tools/git_new_branch.py +82 -0
  187. data/vendor/depot_tools/git_number.py +301 -0
  188. data/vendor/depot_tools/git_rebase_update.py +351 -0
  189. data/vendor/depot_tools/git_rename_branch.py +55 -0
  190. data/vendor/depot_tools/git_reparent_branch.py +101 -0
  191. data/vendor/depot_tools/git_retry.py +181 -0
  192. data/vendor/depot_tools/git_squash_branch.py +28 -0
  193. data/vendor/depot_tools/git_upstream_diff.py +64 -0
  194. data/vendor/depot_tools/gn +8 -0
  195. data/vendor/depot_tools/gn.bat +12 -0
  196. data/vendor/depot_tools/gn.py +78 -0
  197. data/vendor/depot_tools/goma_auth +12 -0
  198. data/vendor/depot_tools/goma_auth.bat +8 -0
  199. data/vendor/depot_tools/goma_ctl +12 -0
  200. data/vendor/depot_tools/goma_ctl.bat +8 -0
  201. data/vendor/depot_tools/gsutil.py +190 -0
  202. data/vendor/depot_tools/gsutil.py.bat +23 -0
  203. data/vendor/depot_tools/gsutil.vpython +120 -0
  204. data/vendor/depot_tools/infra/README.md +1 -0
  205. data/vendor/depot_tools/infra/config/OWNERS +7 -0
  206. data/vendor/depot_tools/infra/config/README.md +1 -0
  207. data/vendor/depot_tools/infra/config/recipes.cfg +26 -0
  208. data/vendor/depot_tools/led +12 -0
  209. data/vendor/depot_tools/led.bat +7 -0
  210. data/vendor/depot_tools/lockfile.py +116 -0
  211. data/vendor/depot_tools/luci-auth +13 -0
  212. data/vendor/depot_tools/luci-auth.bat +8 -0
  213. data/vendor/depot_tools/lucicfg +12 -0
  214. data/vendor/depot_tools/lucicfg.bat +7 -0
  215. data/vendor/depot_tools/mac_toolchain +12 -0
  216. data/vendor/depot_tools/man/html/depot_tools.html +934 -0
  217. data/vendor/depot_tools/man/html/depot_tools_tutorial.html +1593 -0
  218. data/vendor/depot_tools/man/html/git-cl.html +1033 -0
  219. data/vendor/depot_tools/man/html/git-drover.html +1048 -0
  220. data/vendor/depot_tools/man/html/git-footers.html +878 -0
  221. data/vendor/depot_tools/man/html/git-freeze.html +859 -0
  222. data/vendor/depot_tools/man/html/git-hyper-blame.html +878 -0
  223. data/vendor/depot_tools/man/html/git-map-branches.html +904 -0
  224. data/vendor/depot_tools/man/html/git-map.html +887 -0
  225. data/vendor/depot_tools/man/html/git-mark-merge-base.html +826 -0
  226. data/vendor/depot_tools/man/html/git-nav-downstream.html +844 -0
  227. data/vendor/depot_tools/man/html/git-nav-upstream.html +853 -0
  228. data/vendor/depot_tools/man/html/git-new-branch.html +932 -0
  229. data/vendor/depot_tools/man/html/git-rebase-update.html +961 -0
  230. data/vendor/depot_tools/man/html/git-rename-branch.html +794 -0
  231. data/vendor/depot_tools/man/html/git-reparent-branch.html +847 -0
  232. data/vendor/depot_tools/man/html/git-retry.html +858 -0
  233. data/vendor/depot_tools/man/html/git-squash-branch.html +881 -0
  234. data/vendor/depot_tools/man/html/git-thaw.html +794 -0
  235. data/vendor/depot_tools/man/html/git-upstream-diff.html +923 -0
  236. data/vendor/depot_tools/man/man1/git-cl.1 +198 -0
  237. data/vendor/depot_tools/man/man1/git-drover.1 +330 -0
  238. data/vendor/depot_tools/man/man1/git-footers.1 +144 -0
  239. data/vendor/depot_tools/man/man1/git-freeze.1 +113 -0
  240. data/vendor/depot_tools/man/man1/git-hyper-blame.1 +128 -0
  241. data/vendor/depot_tools/man/man1/git-map-branches.1 +210 -0
  242. data/vendor/depot_tools/man/man1/git-map.1 +179 -0
  243. data/vendor/depot_tools/man/man1/git-mark-merge-base.1 +69 -0
  244. data/vendor/depot_tools/man/man1/git-nav-downstream.1 +112 -0
  245. data/vendor/depot_tools/man/man1/git-nav-upstream.1 +122 -0
  246. data/vendor/depot_tools/man/man1/git-new-branch.1 +176 -0
  247. data/vendor/depot_tools/man/man1/git-rebase-update.1 +177 -0
  248. data/vendor/depot_tools/man/man1/git-rename-branch.1 +53 -0
  249. data/vendor/depot_tools/man/man1/git-reparent-branch.1 +93 -0
  250. data/vendor/depot_tools/man/man1/git-retry.1 +108 -0
  251. data/vendor/depot_tools/man/man1/git-squash-branch.1 +129 -0
  252. data/vendor/depot_tools/man/man1/git-thaw.1 +54 -0
  253. data/vendor/depot_tools/man/man1/git-upstream-diff.1 +153 -0
  254. data/vendor/depot_tools/man/man7/depot_tools.7 +139 -0
  255. data/vendor/depot_tools/man/man7/depot_tools_tutorial.7 +1061 -0
  256. data/vendor/depot_tools/man/push_to_gs.sh +4 -0
  257. data/vendor/depot_tools/man/src/.gitignore +5 -0
  258. data/vendor/depot_tools/man/src/_aliases.txt +5 -0
  259. data/vendor/depot_tools/man/src/_footer.txt +8 -0
  260. data/vendor/depot_tools/man/src/_git-cl_desc.helper.txt +1 -0
  261. data/vendor/depot_tools/man/src/_git-drover_desc.helper.txt +2 -0
  262. data/vendor/depot_tools/man/src/_git-footers_desc.helper.txt +1 -0
  263. data/vendor/depot_tools/man/src/_git-freeze_desc.helper.txt +1 -0
  264. data/vendor/depot_tools/man/src/_git-hyper-blame_desc.helper.txt +1 -0
  265. data/vendor/depot_tools/man/src/_git-map-branches_desc.helper.txt +4 -0
  266. data/vendor/depot_tools/man/src/_git-map_desc.helper.txt +3 -0
  267. data/vendor/depot_tools/man/src/_git-mark-merge-base_desc.helper.txt +1 -0
  268. data/vendor/depot_tools/man/src/_git-nav-downstream_desc.helper.txt +1 -0
  269. data/vendor/depot_tools/man/src/_git-nav-upstream_desc.helper.txt +1 -0
  270. data/vendor/depot_tools/man/src/_git-new-branch_desc.helper.txt +1 -0
  271. data/vendor/depot_tools/man/src/_git-rebase-update_desc.helper.txt +1 -0
  272. data/vendor/depot_tools/man/src/_git-rename-branch_desc.helper.txt +1 -0
  273. data/vendor/depot_tools/man/src/_git-reparent-branch_desc.helper.txt +1 -0
  274. data/vendor/depot_tools/man/src/_git-retry_desc.helper.txt +2 -0
  275. data/vendor/depot_tools/man/src/_git-squash-branch_desc.helper.txt +1 -0
  276. data/vendor/depot_tools/man/src/_git-thaw_desc.helper.txt +2 -0
  277. data/vendor/depot_tools/man/src/_git-upstream-diff_desc.helper.txt +1 -0
  278. data/vendor/depot_tools/man/src/_helper_prefix.txt +1 -0
  279. data/vendor/depot_tools/man/src/asciidoc-override.css +7 -0
  280. data/vendor/depot_tools/man/src/common_demo_functions.sh +84 -0
  281. data/vendor/depot_tools/man/src/demo_repo.sh +43 -0
  282. data/vendor/depot_tools/man/src/depot_tools.txt +28 -0
  283. data/vendor/depot_tools/man/src/depot_tools_tutorial.demo.walkthrough.sh +155 -0
  284. data/vendor/depot_tools/man/src/depot_tools_tutorial.txt +432 -0
  285. data/vendor/depot_tools/man/src/filter_demo_output.py +141 -0
  286. data/vendor/depot_tools/man/src/git-cl.txt +119 -0
  287. data/vendor/depot_tools/man/src/git-drover.demo.1.sh +22 -0
  288. data/vendor/depot_tools/man/src/git-drover.demo.2.sh +23 -0
  289. data/vendor/depot_tools/man/src/git-drover.demo.3.sh +27 -0
  290. data/vendor/depot_tools/man/src/git-drover.demo.4.sh +39 -0
  291. data/vendor/depot_tools/man/src/git-drover.demo.common.sh +19 -0
  292. data/vendor/depot_tools/man/src/git-drover.txt +102 -0
  293. data/vendor/depot_tools/man/src/git-footers.demo.1.sh +17 -0
  294. data/vendor/depot_tools/man/src/git-footers.txt +71 -0
  295. data/vendor/depot_tools/man/src/git-freeze.demo.1.sh +23 -0
  296. data/vendor/depot_tools/man/src/git-freeze.txt +54 -0
  297. data/vendor/depot_tools/man/src/git-hyper-blame.demo.1.sh +3 -0
  298. data/vendor/depot_tools/man/src/git-hyper-blame.demo.2.sh +4 -0
  299. data/vendor/depot_tools/man/src/git-hyper-blame.demo.common.sh +57 -0
  300. data/vendor/depot_tools/man/src/git-hyper-blame.txt +85 -0
  301. data/vendor/depot_tools/man/src/git-map-branches.demo.1.sh +8 -0
  302. data/vendor/depot_tools/man/src/git-map-branches.txt +64 -0
  303. data/vendor/depot_tools/man/src/git-map.demo.1.sh +3 -0
  304. data/vendor/depot_tools/man/src/git-map.txt +67 -0
  305. data/vendor/depot_tools/man/src/git-mark-merge-base.txt +46 -0
  306. data/vendor/depot_tools/man/src/git-nav-downstream.demo.1.sh +12 -0
  307. data/vendor/depot_tools/man/src/git-nav-downstream.txt +40 -0
  308. data/vendor/depot_tools/man/src/git-nav-upstream.demo.1.sh +12 -0
  309. data/vendor/depot_tools/man/src/git-nav-upstream.txt +39 -0
  310. data/vendor/depot_tools/man/src/git-new-branch.demo.1.sh +17 -0
  311. data/vendor/depot_tools/man/src/git-new-branch.txt +82 -0
  312. data/vendor/depot_tools/man/src/git-rebase-update.txt +141 -0
  313. data/vendor/depot_tools/man/src/git-rename-branch.txt +28 -0
  314. data/vendor/depot_tools/man/src/git-reparent-branch.txt +61 -0
  315. data/vendor/depot_tools/man/src/git-retry.txt +67 -0
  316. data/vendor/depot_tools/man/src/git-squash-branch.demo.1.sh +12 -0
  317. data/vendor/depot_tools/man/src/git-squash-branch.txt +59 -0
  318. data/vendor/depot_tools/man/src/git-thaw.txt +29 -0
  319. data/vendor/depot_tools/man/src/git-upstream-diff.txt +107 -0
  320. data/vendor/depot_tools/man/src/make_docs.sh +260 -0
  321. data/vendor/depot_tools/man/src/prep_demo_repo.sh +103 -0
  322. data/vendor/depot_tools/metrics.README.md +101 -0
  323. data/vendor/depot_tools/metrics.py +297 -0
  324. data/vendor/depot_tools/metrics_utils.py +293 -0
  325. data/vendor/depot_tools/my_activity.py +971 -0
  326. data/vendor/depot_tools/ninja +44 -0
  327. data/vendor/depot_tools/ninja-linux32 +0 -0
  328. data/vendor/depot_tools/ninja-linux64 +0 -0
  329. data/vendor/depot_tools/ninja-mac +0 -0
  330. data/vendor/depot_tools/ninja.exe +0 -0
  331. data/vendor/depot_tools/ninjalog.README.md +64 -0
  332. data/vendor/depot_tools/ninjalog_uploader.py +233 -0
  333. data/vendor/depot_tools/ninjalog_uploader_wrapper.py +125 -0
  334. data/vendor/depot_tools/owners.py +641 -0
  335. data/vendor/depot_tools/owners_finder.py +385 -0
  336. data/vendor/depot_tools/post_build_ninja_summary.py +350 -0
  337. data/vendor/depot_tools/presubmit_canned_checks.py +1655 -0
  338. data/vendor/depot_tools/presubmit_support.py +1923 -0
  339. data/vendor/depot_tools/profile.xml +8 -0
  340. data/vendor/depot_tools/prpc +13 -0
  341. data/vendor/depot_tools/prpc.bat +8 -0
  342. data/vendor/depot_tools/pylint +9 -0
  343. data/vendor/depot_tools/pylint-1.5 +78 -0
  344. data/vendor/depot_tools/pylint-1.6 +78 -0
  345. data/vendor/depot_tools/pylint-1.7 +78 -0
  346. data/vendor/depot_tools/pylint-1.8 +78 -0
  347. data/vendor/depot_tools/pylint-1.9 +78 -0
  348. data/vendor/depot_tools/pylint.bat +12 -0
  349. data/vendor/depot_tools/pylint_main.py +45 -0
  350. data/vendor/depot_tools/pylintrc +349 -0
  351. data/vendor/depot_tools/python-bin/python3 +7 -0
  352. data/vendor/depot_tools/python_runner.sh +60 -0
  353. data/vendor/depot_tools/rdb +12 -0
  354. data/vendor/depot_tools/rdb.bat +7 -0
  355. data/vendor/depot_tools/recipes/OWNERS +4 -0
  356. data/vendor/depot_tools/recipes/README.recipes.md +1079 -0
  357. data/vendor/depot_tools/recipes/recipe_modules/OWNERS +1 -0
  358. data/vendor/depot_tools/recipes/recipe_modules/bot_update/OWNERS +2 -0
  359. data/vendor/depot_tools/recipes/recipe_modules/bot_update/__init__.py +38 -0
  360. data/vendor/depot_tools/recipes/recipe_modules/bot_update/api.py +516 -0
  361. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic.json +117 -0
  362. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic_luci.json +117 -0
  363. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic_with_branch_heads.json +118 -0
  364. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/clobber.json +211 -0
  365. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/deprecated_got_revision_mapping.json +194 -0
  366. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/gerrit_no_rebase_patch_ref.json +211 -0
  367. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/gerrit_no_reset.json +211 -0
  368. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/input_commit_with_id_without_repo.json +210 -0
  369. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/multiple_patch_refs.json +214 -0
  370. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_apply_patch_on_gclient.json +265 -0
  371. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_cp_checkout_HEAD.json +65 -0
  372. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_cp_checkout_a_branch_head.json +65 -0
  373. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_cp_checkout_a_specific_commit.json +65 -0
  374. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_cp_checkout_master.json +65 -0
  375. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/refs.json +212 -0
  376. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/reset_root_solution_revision.json +210 -0
  377. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/resolve_chromium_fixed_version.json +117 -0
  378. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail.json +95 -0
  379. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch.json +209 -0
  380. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch_download.json +193 -0
  381. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_angle.json +265 -0
  382. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_branch_heads.json +261 -0
  383. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_feature_branch.json +261 -0
  384. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_v8_feature_branch.json +265 -0
  385. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_webrtc.json +265 -0
  386. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8.json +265 -0
  387. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8_head_by_default.json +265 -0
  388. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/unrecognized_commit_repo.json +8 -0
  389. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/with_tags.json +211 -0
  390. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.py +308 -0
  391. data/vendor/depot_tools/recipes/recipe_modules/bot_update/resources/__init__.py +0 -0
  392. data/vendor/depot_tools/recipes/recipe_modules/bot_update/resources/bot_update.py +1258 -0
  393. data/vendor/depot_tools/recipes/recipe_modules/bot_update/test_api.py +93 -0
  394. data/vendor/depot_tools/recipes/recipe_modules/bot_update/tests/do_not_retry_patch_failures_in_cq.py +42 -0
  395. data/vendor/depot_tools/recipes/recipe_modules/bot_update/tests/ensure_checkout.py +35 -0
  396. data/vendor/depot_tools/recipes/recipe_modules/cipd/__init__.py +9 -0
  397. data/vendor/depot_tools/recipes/recipe_modules/cipd/api.py +455 -0
  398. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/basic.json +403 -0
  399. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/basic_pkg.json +403 -0
  400. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/describe-failed.json +82 -0
  401. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/describe-many-instances.json +411 -0
  402. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/mac64.json +403 -0
  403. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/pkg_bad_file.json +315 -0
  404. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/pkg_bad_mode.json +313 -0
  405. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/pkg_bad_verfile.json +313 -0
  406. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/win64.json +403 -0
  407. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.py +187 -0
  408. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/junk arch.json +5 -0
  409. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/junk bits.json +5 -0
  410. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_arm_32.json +12 -0
  411. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_arm_64.json +12 -0
  412. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_intel_32.json +12 -0
  413. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_intel_64.json +12 -0
  414. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_mips_64.json +12 -0
  415. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/mac_intel_64.json +12 -0
  416. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/win_intel_32.json +12 -0
  417. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/win_intel_64.json +12 -0
  418. data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.py +59 -0
  419. data/vendor/depot_tools/recipes/recipe_modules/cipd/test_api.py +93 -0
  420. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/__init__.py +9 -0
  421. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/api.py +75 -0
  422. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.expected/basic.json +83 -0
  423. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.expected/basic_luci.json +83 -0
  424. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.expected/win.json +83 -0
  425. data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.py +55 -0
  426. data/vendor/depot_tools/recipes/recipe_modules/gclient/__init__.py +13 -0
  427. data/vendor/depot_tools/recipes/recipe_modules/gclient/api.py +428 -0
  428. data/vendor/depot_tools/recipes/recipe_modules/gclient/config.py +462 -0
  429. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/basic.json +238 -0
  430. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/revision.json +240 -0
  431. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/tryserver.json +238 -0
  432. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.py +95 -0
  433. data/vendor/depot_tools/recipes/recipe_modules/gclient/resources/diff_deps.py +16 -0
  434. data/vendor/depot_tools/recipes/recipe_modules/gclient/test_api.py +36 -0
  435. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.expected/basic.json +55 -0
  436. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.expected/dont have revision yet.json +84 -0
  437. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.expected/no change, exception.json +83 -0
  438. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.expected/windows.json +55 -0
  439. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.py +88 -0
  440. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/patch_project.py +92 -0
  441. data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/sync_failure.py +24 -0
  442. data/vendor/depot_tools/recipes/recipe_modules/gerrit/__init__.py +8 -0
  443. data/vendor/depot_tools/recipes/recipe_modules/gerrit/api.py +178 -0
  444. data/vendor/depot_tools/recipes/recipe_modules/gerrit/examples/full.expected/basic.json +284 -0
  445. data/vendor/depot_tools/recipes/recipe_modules/gerrit/examples/full.py +73 -0
  446. data/vendor/depot_tools/recipes/recipe_modules/gerrit/test_api.py +53 -0
  447. data/vendor/depot_tools/recipes/recipe_modules/git/__init__.py +11 -0
  448. data/vendor/depot_tools/recipes/recipe_modules/git/api.py +405 -0
  449. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic.json +217 -0
  450. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_branch.json +217 -0
  451. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_file_name.json +219 -0
  452. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_hash.json +216 -0
  453. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_ref.json +217 -0
  454. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_submodule_update_force.json +218 -0
  455. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_tags.json +218 -0
  456. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/can_fail_build.json +164 -0
  457. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/cannot_fail_build.json +220 -0
  458. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/cat-file_test.json +239 -0
  459. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_delta.json +290 -0
  460. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_failed.json +220 -0
  461. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_with_bad_output.json +222 -0
  462. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_with_bad_output_fails_build.json +111 -0
  463. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/curl_trace_file.json +218 -0
  464. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/git-cache-checkout.json +265 -0
  465. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/platform_win.json +217 -0
  466. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/rebase_failed.json +221 -0
  467. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/remote_not_origin.json +219 -0
  468. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/set_got_revision.json +218 -0
  469. data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.py +170 -0
  470. data/vendor/depot_tools/recipes/recipe_modules/git/resources/git_setup.py +52 -0
  471. data/vendor/depot_tools/recipes/recipe_modules/git/test_api.py +18 -0
  472. data/vendor/depot_tools/recipes/recipe_modules/git_cl/__init__.py +5 -0
  473. data/vendor/depot_tools/recipes/recipe_modules/git_cl/api.py +50 -0
  474. data/vendor/depot_tools/recipes/recipe_modules/git_cl/config.py +22 -0
  475. data/vendor/depot_tools/recipes/recipe_modules/git_cl/examples/full.expected/basic.json +105 -0
  476. data/vendor/depot_tools/recipes/recipe_modules/git_cl/examples/full.py +47 -0
  477. data/vendor/depot_tools/recipes/recipe_modules/gitiles/OWNERS +2 -0
  478. data/vendor/depot_tools/recipes/recipe_modules/gitiles/__init__.py +12 -0
  479. data/vendor/depot_tools/recipes/recipe_modules/gitiles/api.py +257 -0
  480. data/vendor/depot_tools/recipes/recipe_modules/gitiles/examples/full.expected/basic.json +596 -0
  481. data/vendor/depot_tools/recipes/recipe_modules/gitiles/examples/full.py +93 -0
  482. data/vendor/depot_tools/recipes/recipe_modules/gitiles/resources/gerrit_client.py +251 -0
  483. data/vendor/depot_tools/recipes/recipe_modules/gitiles/test_api.py +95 -0
  484. data/vendor/depot_tools/recipes/recipe_modules/gitiles/tests/parse_repo_url.expected/basic.json +5 -0
  485. data/vendor/depot_tools/recipes/recipe_modules/gitiles/tests/parse_repo_url.py +49 -0
  486. data/vendor/depot_tools/recipes/recipe_modules/gsutil/__init__.py +4 -0
  487. data/vendor/depot_tools/recipes/recipe_modules/gsutil/api.py +222 -0
  488. data/vendor/depot_tools/recipes/recipe_modules/gsutil/examples/full.expected/basic.json +247 -0
  489. data/vendor/depot_tools/recipes/recipe_modules/gsutil/examples/full.py +92 -0
  490. data/vendor/depot_tools/recipes/recipe_modules/gsutil/resources/gsutil_smart_retry.py +69 -0
  491. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/__init__.py +36 -0
  492. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/api.py +140 -0
  493. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/ancient_version.json +83 -0
  494. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/automatic_version.json +83 -0
  495. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/explicit_version.json +83 -0
  496. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/linux.json +21 -0
  497. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/mac.json +83 -0
  498. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/win.json +21 -0
  499. data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.py +42 -0
  500. data/vendor/depot_tools/recipes/recipe_modules/presubmit/__init__.py +27 -0
  501. data/vendor/depot_tools/recipes/recipe_modules/presubmit/api.py +251 -0
  502. data/vendor/depot_tools/recipes/recipe_modules/presubmit/examples/full.expected/basic.json +27 -0
  503. data/vendor/depot_tools/recipes/recipe_modules/presubmit/examples/full.py +19 -0
  504. data/vendor/depot_tools/recipes/recipe_modules/presubmit/properties.proto +14 -0
  505. data/vendor/depot_tools/recipes/recipe_modules/presubmit/test_api.py +19 -0
  506. data/vendor/depot_tools/recipes/recipe_modules/presubmit/tests/execute.py +247 -0
  507. data/vendor/depot_tools/recipes/recipe_modules/presubmit/tests/prepare.py +49 -0
  508. data/vendor/depot_tools/recipes/recipe_modules/tryserver/__init__.py +18 -0
  509. data/vendor/depot_tools/recipes/recipe_modules/tryserver/api.py +264 -0
  510. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/basic_tags.json +57 -0
  511. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_gerrit_patch.json +190 -0
  512. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_gerrit_patch_and_target_ref.json +190 -0
  513. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_wrong_patch.json +21 -0
  514. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_wrong_patch_new.json +22 -0
  515. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.py +95 -0
  516. data/vendor/depot_tools/recipes/recipe_modules/tryserver/test_api.py +14 -0
  517. data/vendor/depot_tools/recipes/recipe_modules/tryserver/tests/gerrit_change_fetch_ref_timeout.py +29 -0
  518. data/vendor/depot_tools/recipes/recipe_modules/tryserver/tests/gerrit_change_owner.expected/basic.json +5 -0
  519. data/vendor/depot_tools/recipes/recipe_modules/tryserver/tests/gerrit_change_owner.py +22 -0
  520. data/vendor/depot_tools/recipes/recipe_modules/tryserver/tests/gerrit_change_target_ref.py +32 -0
  521. data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/__init__.py +25 -0
  522. data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/api.py +137 -0
  523. data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.expected/linux.json +21 -0
  524. data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.expected/mac.json +21 -0
  525. data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.expected/win.json +108 -0
  526. data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.py +21 -0
  527. data/vendor/depot_tools/recipes/recipes.py +249 -0
  528. data/vendor/depot_tools/recipes/recipes/fetch_end_to_end_test.expected/basic.json +175 -0
  529. data/vendor/depot_tools/recipes/recipes/fetch_end_to_end_test.py +56 -0
  530. data/vendor/depot_tools/recipes/trigger_recipe_roller.txt +13 -0
  531. data/vendor/depot_tools/repo +1194 -0
  532. data/vendor/depot_tools/roll-dep +21 -0
  533. data/vendor/depot_tools/roll-dep.bat +21 -0
  534. data/vendor/depot_tools/roll_dep.py +282 -0
  535. data/vendor/depot_tools/scm.py +415 -0
  536. data/vendor/depot_tools/setup_color.py +130 -0
  537. data/vendor/depot_tools/split_cl.py +263 -0
  538. data/vendor/depot_tools/subcommand.py +261 -0
  539. data/vendor/depot_tools/subprocess2.py +258 -0
  540. data/vendor/depot_tools/third_party/__init__.py +5 -0
  541. data/vendor/depot_tools/third_party/colorama/LICENSE.txt +27 -0
  542. data/vendor/depot_tools/third_party/colorama/README.chromium +12 -0
  543. data/vendor/depot_tools/third_party/colorama/README.rst +346 -0
  544. data/vendor/depot_tools/third_party/colorama/__init__.py +6 -0
  545. data/vendor/depot_tools/third_party/colorama/ansi.py +102 -0
  546. data/vendor/depot_tools/third_party/colorama/ansitowin32.py +257 -0
  547. data/vendor/depot_tools/third_party/colorama/initialise.py +80 -0
  548. data/vendor/depot_tools/third_party/colorama/win32.py +152 -0
  549. data/vendor/depot_tools/third_party/colorama/winterm.py +169 -0
  550. data/vendor/depot_tools/third_party/coverage/AUTHORS.txt +43 -0
  551. data/vendor/depot_tools/third_party/coverage/PKG-INFO +41 -0
  552. data/vendor/depot_tools/third_party/coverage/README.chromium +13 -0
  553. data/vendor/depot_tools/third_party/coverage/__init__.py +120 -0
  554. data/vendor/depot_tools/third_party/coverage/__main__.py +4 -0
  555. data/vendor/depot_tools/third_party/coverage/annotate.py +101 -0
  556. data/vendor/depot_tools/third_party/coverage/backward.py +184 -0
  557. data/vendor/depot_tools/third_party/coverage/bytecode.py +75 -0
  558. data/vendor/depot_tools/third_party/coverage/cmdline.py +740 -0
  559. data/vendor/depot_tools/third_party/coverage/codeunit.py +145 -0
  560. data/vendor/depot_tools/third_party/coverage/collector.py +353 -0
  561. data/vendor/depot_tools/third_party/coverage/config.py +213 -0
  562. data/vendor/depot_tools/third_party/coverage/control.py +776 -0
  563. data/vendor/depot_tools/third_party/coverage/data.py +278 -0
  564. data/vendor/depot_tools/third_party/coverage/debug.py +54 -0
  565. data/vendor/depot_tools/third_party/coverage/execfile.py +171 -0
  566. data/vendor/depot_tools/third_party/coverage/files.py +309 -0
  567. data/vendor/depot_tools/third_party/coverage/fullcoverage/encodings.py +57 -0
  568. data/vendor/depot_tools/third_party/coverage/html.py +387 -0
  569. data/vendor/depot_tools/third_party/coverage/htmlfiles/coverage_html.js +376 -0
  570. data/vendor/depot_tools/third_party/coverage/htmlfiles/index.html +104 -0
  571. data/vendor/depot_tools/third_party/coverage/htmlfiles/jquery-1.4.3.min.js +166 -0
  572. data/vendor/depot_tools/third_party/coverage/htmlfiles/jquery.hotkeys.js +99 -0
  573. data/vendor/depot_tools/third_party/coverage/htmlfiles/jquery.isonscreen.js +53 -0
  574. data/vendor/depot_tools/third_party/coverage/htmlfiles/jquery.min.js +166 -0
  575. data/vendor/depot_tools/third_party/coverage/htmlfiles/jquery.tablesorter.min.js +2 -0
  576. data/vendor/depot_tools/third_party/coverage/htmlfiles/keybd_closed.png +0 -0
  577. data/vendor/depot_tools/third_party/coverage/htmlfiles/keybd_open.png +0 -0
  578. data/vendor/depot_tools/third_party/coverage/htmlfiles/pyfile.html +90 -0
  579. data/vendor/depot_tools/third_party/coverage/htmlfiles/style.css +300 -0
  580. data/vendor/depot_tools/third_party/coverage/misc.py +163 -0
  581. data/vendor/depot_tools/third_party/coverage/parser.py +666 -0
  582. data/vendor/depot_tools/third_party/coverage/phystokens.py +208 -0
  583. data/vendor/depot_tools/third_party/coverage/report.py +92 -0
  584. data/vendor/depot_tools/third_party/coverage/results.py +286 -0
  585. data/vendor/depot_tools/third_party/coverage/summary.py +86 -0
  586. data/vendor/depot_tools/third_party/coverage/templite.py +166 -0
  587. data/vendor/depot_tools/third_party/coverage/version.py +9 -0
  588. data/vendor/depot_tools/third_party/coverage/xmlreport.py +155 -0
  589. data/vendor/depot_tools/third_party/httplib2/LICENSE +1339 -0
  590. data/vendor/depot_tools/third_party/httplib2/README.chromium +15 -0
  591. data/vendor/depot_tools/third_party/httplib2/__init__.py +1780 -0
  592. data/vendor/depot_tools/third_party/httplib2/cacerts.txt +2196 -0
  593. data/vendor/depot_tools/third_party/httplib2/iri2uri.py +110 -0
  594. data/vendor/depot_tools/third_party/httplib2/socks.py +448 -0
  595. data/vendor/depot_tools/third_party/repo/COPYING +202 -0
  596. data/vendor/depot_tools/third_party/repo/README.chromium +4 -0
  597. data/vendor/depot_tools/third_party/repo/__init__.py +0 -0
  598. data/vendor/depot_tools/third_party/repo/progress.py +117 -0
  599. data/vendor/depot_tools/third_party/retry_decorator/LICENSE.google +30 -0
  600. data/vendor/depot_tools/third_party/retry_decorator/__init__.py +0 -0
  601. data/vendor/depot_tools/third_party/retry_decorator/decorators.py +45 -0
  602. data/vendor/depot_tools/third_party/schema/.editorconfig +15 -0
  603. data/vendor/depot_tools/third_party/schema/.gitignore +174 -0
  604. data/vendor/depot_tools/third_party/schema/.travis.yml +37 -0
  605. data/vendor/depot_tools/third_party/schema/LICENSE-MIT +19 -0
  606. data/vendor/depot_tools/third_party/schema/MANIFEST.in +1 -0
  607. data/vendor/depot_tools/third_party/schema/README.chromium +12 -0
  608. data/vendor/depot_tools/third_party/schema/README.rst +382 -0
  609. data/vendor/depot_tools/third_party/schema/__init__.py +1 -0
  610. data/vendor/depot_tools/third_party/schema/schema.py +338 -0
  611. data/vendor/depot_tools/third_party/schema/setup.cfg +5 -0
  612. data/vendor/depot_tools/third_party/schema/setup.py +30 -0
  613. data/vendor/depot_tools/third_party/schema/test_schema.py +556 -0
  614. data/vendor/depot_tools/third_party/schema/tox.ini +33 -0
  615. data/vendor/depot_tools/third_party/six/LICENSE.txt +18 -0
  616. data/vendor/depot_tools/third_party/six/README.chromium +10 -0
  617. data/vendor/depot_tools/third_party/six/__init__.py +762 -0
  618. data/vendor/depot_tools/update_depot_tools +138 -0
  619. data/vendor/depot_tools/update_depot_tools.bat +65 -0
  620. data/vendor/depot_tools/update_depot_tools_toggle.py +38 -0
  621. data/vendor/depot_tools/upload_metrics.py +26 -0
  622. data/vendor/depot_tools/upload_to_google_storage.py +306 -0
  623. data/vendor/depot_tools/vpython +42 -0
  624. data/vendor/depot_tools/vpython.bat +7 -0
  625. data/vendor/depot_tools/vpython3 +55 -0
  626. data/vendor/depot_tools/vpython3.bat +12 -0
  627. data/vendor/depot_tools/watchlists.py +141 -0
  628. data/vendor/depot_tools/weekly +54 -0
  629. data/vendor/depot_tools/win32imports.py +61 -0
  630. data/vendor/depot_tools/win_toolchain/OWNERS +2 -0
  631. data/vendor/depot_tools/win_toolchain/README.md +74 -0
  632. data/vendor/depot_tools/win_toolchain/get_toolchain_if_necessary.py +599 -0
  633. data/vendor/depot_tools/win_toolchain/package_from_installed.py +524 -0
  634. data/vendor/depot_tools/wtf +81 -0
  635. data/vendor/depot_tools/yapf +21 -0
  636. data/vendor/depot_tools/yapf.bat +12 -0
  637. data/vendor/depot_tools/zsh-goodies/README +6 -0
  638. data/vendor/depot_tools/zsh-goodies/_gclient +14 -0
  639. metadata +729 -0
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env bash
2
+ # Copyright (c) 2009 The Chromium Authors. All rights reserved.
3
+ # Use of this source code is governed by a BSD-style license that can be
4
+ # found in the LICENSE file.
5
+
6
+ base_dir=$(dirname "$0")
7
+
8
+ if [[ "#grep#fetch#cleanup#diff#setdep#" != *"#$1#"* ]]; then
9
+ # Shall skip authomatic update?
10
+ if [[ $DEPOT_TOOLS_UPDATE != 0 ]]; then
11
+ "$base_dir"/update_depot_tools "$@"
12
+ case $? in
13
+ 123)
14
+ # msys environment was upgraded, need to quit.
15
+ exit 0
16
+ ;;
17
+ 0)
18
+ ;;
19
+ *)
20
+ exit $?
21
+ esac
22
+ fi
23
+ fi
24
+
25
+ # Ensure that "depot_tools" is somewhere in PATH so this tool can be used
26
+ # standalone, but allow other PATH manipulations to take priority.
27
+ PATH=$PATH:$base_dir
28
+
29
+ if [[ $GCLIENT_PY3 == 1 ]]; then
30
+ # Explicitly run on Python 3
31
+ PYTHONDONTWRITEBYTECODE=1 exec vpython3 "$base_dir/gclient.py" "$@"
32
+ elif [[ $GCLIENT_PY3 == 0 ]]; then
33
+ # Explicitly run on Python 2
34
+ PYTHONDONTWRITEBYTECODE=1 exec vpython "$base_dir/gclient.py" "$@"
35
+ else
36
+ # Run on Python 3, allows default to be flipped.
37
+ PYTHONDONTWRITEBYTECODE=1 exec vpython3 "$base_dir/gclient.py" "$@"
38
+ fi
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env python
2
+ # Copyright 2013 The Chromium Authors. All rights reserved.
3
+ # Use of this source code is governed by a BSD-style license that can be
4
+ # found in the LICENSE file.
5
+ #
6
+ # Usage:
7
+ # gclient-new-workdir.py [options] <repository> <new_workdir>
8
+ #
9
+
10
+ from __future__ import print_function
11
+
12
+ import argparse
13
+ import os
14
+ import shutil
15
+ import subprocess
16
+ import sys
17
+ import textwrap
18
+
19
+ import git_common
20
+
21
+
22
+ def parse_options():
23
+ if sys.platform == 'win32':
24
+ print('ERROR: This script cannot run on Windows because it uses symlinks.')
25
+ sys.exit(1)
26
+
27
+ parser = argparse.ArgumentParser(description='''\
28
+ Clone an existing gclient directory, taking care of all sub-repositories.
29
+ Works similarly to 'git new-workdir'.''')
30
+ parser.add_argument('repository', type=os.path.abspath,
31
+ help='should contain a .gclient file')
32
+ parser.add_argument('new_workdir', help='must not exist')
33
+ parser.add_argument('--reflink', action='store_true', default=None,
34
+ help='''force to use "cp --reflink" for speed and disk
35
+ space. need supported FS like btrfs or ZFS.''')
36
+ parser.add_argument('--no-reflink', action='store_false', dest='reflink',
37
+ help='''force not to use "cp --reflink" even on supported
38
+ FS like btrfs or ZFS.''')
39
+ args = parser.parse_args()
40
+
41
+ if not os.path.exists(args.repository):
42
+ parser.error('Repository "%s" does not exist.' % args.repository)
43
+
44
+ gclient = os.path.join(args.repository, '.gclient')
45
+ if not os.path.exists(gclient):
46
+ parser.error('No .gclient file at "%s".' % gclient)
47
+
48
+ if os.path.exists(args.new_workdir):
49
+ parser.error('New workdir "%s" already exists.' % args.new_workdir)
50
+
51
+ return args
52
+
53
+
54
+ def support_cow(src, dest):
55
+ # 'cp --reflink' always succeeds when 'src' is a symlink or a directory
56
+ assert os.path.isfile(src) and not os.path.islink(src)
57
+ try:
58
+ subprocess.check_output(['cp', '-a', '--reflink', src, dest],
59
+ stderr=subprocess.STDOUT)
60
+ except subprocess.CalledProcessError:
61
+ return False
62
+ finally:
63
+ if os.path.isfile(dest):
64
+ os.remove(dest)
65
+ return True
66
+
67
+
68
+ def try_vol_snapshot(src, dest):
69
+ try:
70
+ subprocess.check_call(['btrfs', 'subvol', 'snapshot', src, dest],
71
+ stderr=subprocess.STDOUT)
72
+ except (subprocess.CalledProcessError, OSError):
73
+ return False
74
+ return True
75
+
76
+
77
+ def main():
78
+ args = parse_options()
79
+
80
+ gclient = os.path.join(args.repository, '.gclient')
81
+ if os.path.islink(gclient):
82
+ gclient = os.path.realpath(gclient)
83
+ new_gclient = os.path.join(args.new_workdir, '.gclient')
84
+
85
+ if try_vol_snapshot(args.repository, args.new_workdir):
86
+ args.reflink = True
87
+ else:
88
+ os.makedirs(args.new_workdir)
89
+ if args.reflink is None:
90
+ args.reflink = support_cow(gclient, new_gclient)
91
+ if args.reflink:
92
+ print('Copy-on-write support is detected.')
93
+ os.symlink(gclient, new_gclient)
94
+
95
+ for root, dirs, _ in os.walk(args.repository):
96
+ if '.git' in dirs:
97
+ workdir = root.replace(args.repository, args.new_workdir, 1)
98
+ print('Creating: %s' % workdir)
99
+
100
+ if args.reflink:
101
+ if not os.path.exists(workdir):
102
+ print('Copying: %s' % workdir)
103
+ subprocess.check_call(['cp', '-a', '--reflink', root, workdir])
104
+ shutil.rmtree(os.path.join(workdir, '.git'))
105
+
106
+ git_common.make_workdir(os.path.join(root, '.git'),
107
+ os.path.join(workdir, '.git'))
108
+ if args.reflink:
109
+ subprocess.check_call(['cp', '-a', '--reflink',
110
+ os.path.join(root, '.git', 'index'),
111
+ os.path.join(workdir, '.git', 'index')])
112
+ else:
113
+ subprocess.check_call(['git', 'checkout', '-f'], cwd=workdir)
114
+
115
+ if args.reflink:
116
+ print(textwrap.dedent('''\
117
+ The repo was copied with copy-on-write, and the artifacts were retained.
118
+ More details on http://crbug.com/721585.
119
+
120
+ Depending on your usage pattern, you might want to do "gn gen"
121
+ on the output directories. More details: http://crbug.com/723856.'''))
122
+
123
+ if __name__ == '__main__':
124
+ sys.exit(main())
@@ -0,0 +1,32 @@
1
+ @echo off
2
+ :: Copyright (c) 2012 The Chromium Authors. All rights reserved.
3
+ :: Use of this source code is governed by a BSD-style license that can be
4
+ :: found in the LICENSE file.
5
+ setlocal
6
+
7
+ :: Shall skip automatic update?
8
+ IF "%DEPOT_TOOLS_UPDATE%" == "0" GOTO :CALL_GCLIENT
9
+
10
+ :: Synchronize the root directory before deferring control back to gclient.py.
11
+ call "%~dp0update_depot_tools.bat" %*
12
+ :: Abort the script if we failed to update depot_tools.
13
+ IF %errorlevel% NEQ 0 (
14
+ goto :EOF
15
+ )
16
+
17
+ :CALL_GCLIENT
18
+ :: Ensure that "depot_tools" is somewhere in PATH so this tool can be used
19
+ :: standalone, but allow other PATH manipulations to take priority.
20
+ set PATH=%PATH%;%~dp0
21
+
22
+ :: Defer control.
23
+ IF "%GCLIENT_PY3%" == "1" (
24
+ :: Explicitly run on Python 3
25
+ call vpython3 "%~dp0gclient.py" %*
26
+ ) ELSE IF "%GCLIENT_PY3%" == "0" (
27
+ :: Explicitly run on Python 2
28
+ call vpython "%~dp0gclient.py" %*
29
+ ) ELSE (
30
+ :: Run on Python 3, allows default to be flipped.
31
+ call vpython3 "%~dp0gclient.py" %*
32
+ )
@@ -0,0 +1,3198 @@
1
+ #!/usr/bin/env python
2
+ # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3
+ # Use of this source code is governed by a BSD-style license that can be
4
+ # found in the LICENSE file.
5
+
6
+ """Meta checkout dependency manager for Git."""
7
+ # Files
8
+ # .gclient : Current client configuration, written by 'config' command.
9
+ # Format is a Python script defining 'solutions', a list whose
10
+ # entries each are maps binding the strings "name" and "url"
11
+ # to strings specifying the name and location of the client
12
+ # module, as well as "custom_deps" to a map similar to the
13
+ # deps section of the DEPS file below, as well as
14
+ # "custom_hooks" to a list similar to the hooks sections of
15
+ # the DEPS file below.
16
+ # .gclient_entries : A cache constructed by 'update' command. Format is a
17
+ # Python script defining 'entries', a list of the names
18
+ # of all modules in the client
19
+ # <module>/DEPS : Python script defining var 'deps' as a map from each
20
+ # requisite submodule name to a URL where it can be found (via
21
+ # one SCM)
22
+ #
23
+ # Hooks
24
+ # .gclient and DEPS files may optionally contain a list named "hooks" to
25
+ # allow custom actions to be performed based on files that have changed in the
26
+ # working copy as a result of a "sync"/"update" or "revert" operation. This
27
+ # can be prevented by using --nohooks (hooks run by default). Hooks can also
28
+ # be forced to run with the "runhooks" operation. If "sync" is run with
29
+ # --force, all known but not suppressed hooks will run regardless of the state
30
+ # of the working copy.
31
+ #
32
+ # Each item in a "hooks" list is a dict, containing these two keys:
33
+ # "pattern" The associated value is a string containing a regular
34
+ # expression. When a file whose pathname matches the expression
35
+ # is checked out, updated, or reverted, the hook's "action" will
36
+ # run.
37
+ # "action" A list describing a command to run along with its arguments, if
38
+ # any. An action command will run at most one time per gclient
39
+ # invocation, regardless of how many files matched the pattern.
40
+ # The action is executed in the same directory as the .gclient
41
+ # file. If the first item in the list is the string "python",
42
+ # the current Python interpreter (sys.executable) will be used
43
+ # to run the command. If the list contains string
44
+ # "$matching_files" it will be removed from the list and the list
45
+ # will be extended by the list of matching files.
46
+ # "name" An optional string specifying the group to which a hook belongs
47
+ # for overriding and organizing.
48
+ #
49
+ # Example:
50
+ # hooks = [
51
+ # { "pattern": "\\.(gif|jpe?g|pr0n|png)$",
52
+ # "action": ["python", "image_indexer.py", "--all"]},
53
+ # { "pattern": ".",
54
+ # "name": "gyp",
55
+ # "action": ["python", "src/build/gyp_chromium"]},
56
+ # ]
57
+ #
58
+ # Pre-DEPS Hooks
59
+ # DEPS files may optionally contain a list named "pre_deps_hooks". These are
60
+ # the same as normal hooks, except that they run before the DEPS are
61
+ # processed. Pre-DEPS run with "sync" and "revert" unless the --noprehooks
62
+ # flag is used.
63
+ #
64
+ # Specifying a target OS
65
+ # An optional key named "target_os" may be added to a gclient file to specify
66
+ # one or more additional operating systems that should be considered when
67
+ # processing the deps_os/hooks_os dict of a DEPS file.
68
+ #
69
+ # Example:
70
+ # target_os = [ "android" ]
71
+ #
72
+ # If the "target_os_only" key is also present and true, then *only* the
73
+ # operating systems listed in "target_os" will be used.
74
+ #
75
+ # Example:
76
+ # target_os = [ "ios" ]
77
+ # target_os_only = True
78
+ #
79
+ # Specifying a target CPU
80
+ # To specify a target CPU, the variables target_cpu and target_cpu_only
81
+ # are available and are analogous to target_os and target_os_only.
82
+
83
+ from __future__ import print_function
84
+
85
+ __version__ = '0.7'
86
+
87
+ import collections
88
+ import copy
89
+ import json
90
+ import logging
91
+ import optparse
92
+ import os
93
+ import platform
94
+ import posixpath
95
+ import pprint
96
+ import re
97
+ import sys
98
+ import time
99
+
100
+ try:
101
+ import urlparse
102
+ except ImportError: # For Py3 compatibility
103
+ import urllib.parse as urlparse
104
+
105
+ import detect_host_arch
106
+ import fix_encoding
107
+ import gclient_eval
108
+ import gclient_scm
109
+ import gclient_paths
110
+ import gclient_utils
111
+ import git_cache
112
+ import metrics
113
+ import metrics_utils
114
+ from third_party.repo.progress import Progress
115
+ import subcommand
116
+ import subprocess2
117
+ import setup_color
118
+
119
+ from third_party import six
120
+
121
+ # TODO(crbug.com/953884): Remove this when python3 migration is done.
122
+ if six.PY3:
123
+ # pylint: disable=redefined-builtin
124
+ basestring = str
125
+
126
+
127
+ DEPOT_TOOLS_DIR = os.path.dirname(os.path.abspath(os.path.realpath(__file__)))
128
+
129
+ # Singleton object to represent an unset cache_dir (as opposed to a disabled
130
+ # one, e.g. if a spec explicitly says `cache_dir = None`.)
131
+ UNSET_CACHE_DIR = object()
132
+
133
+
134
+ class GNException(Exception):
135
+ pass
136
+
137
+
138
+ def ToGNString(value, allow_dicts = True):
139
+ """Returns a stringified GN equivalent of the Python value.
140
+
141
+ allow_dicts indicates if this function will allow converting dictionaries
142
+ to GN scopes. This is only possible at the top level, you can't nest a
143
+ GN scope in a list, so this should be set to False for recursive calls."""
144
+ if isinstance(value, basestring):
145
+ if value.find('\n') >= 0:
146
+ raise GNException("Trying to print a string with a newline in it.")
147
+ return '"' + \
148
+ value.replace('\\', '\\\\').replace('"', '\\"').replace('$', '\\$') + \
149
+ '"'
150
+
151
+ if sys.version_info.major == 2 and isinstance(value, unicode):
152
+ return ToGNString(value.encode('utf-8'))
153
+
154
+ if isinstance(value, bool):
155
+ if value:
156
+ return "true"
157
+ return "false"
158
+
159
+ # NOTE: some type handling removed compared to chromium/src copy.
160
+
161
+ raise GNException("Unsupported type when printing to GN.")
162
+
163
+
164
+ class Hook(object):
165
+ """Descriptor of command ran before/after sync or on demand."""
166
+
167
+ def __init__(self, action, pattern=None, name=None, cwd=None, condition=None,
168
+ variables=None, verbose=False, cwd_base=None):
169
+ """Constructor.
170
+
171
+ Arguments:
172
+ action (list of basestring): argv of the command to run
173
+ pattern (basestring regex): noop with git; deprecated
174
+ name (basestring): optional name; no effect on operation
175
+ cwd (basestring): working directory to use
176
+ condition (basestring): condition when to run the hook
177
+ variables (dict): variables for evaluating the condition
178
+ """
179
+ self._action = gclient_utils.freeze(action)
180
+ self._pattern = pattern
181
+ self._name = name
182
+ self._cwd = cwd
183
+ self._condition = condition
184
+ self._variables = variables
185
+ self._verbose = verbose
186
+ self._cwd_base = cwd_base
187
+
188
+ @staticmethod
189
+ def from_dict(d, variables=None, verbose=False, conditions=None,
190
+ cwd_base=None):
191
+ """Creates a Hook instance from a dict like in the DEPS file."""
192
+ # Merge any local and inherited conditions.
193
+ gclient_eval.UpdateCondition(d, 'and', conditions)
194
+ return Hook(
195
+ d['action'],
196
+ d.get('pattern'),
197
+ d.get('name'),
198
+ d.get('cwd'),
199
+ d.get('condition'),
200
+ variables=variables,
201
+ # Always print the header if not printing to a TTY.
202
+ verbose=verbose or not setup_color.IS_TTY,
203
+ cwd_base=cwd_base)
204
+
205
+ @property
206
+ def action(self):
207
+ return self._action
208
+
209
+ @property
210
+ def pattern(self):
211
+ return self._pattern
212
+
213
+ @property
214
+ def name(self):
215
+ return self._name
216
+
217
+ @property
218
+ def condition(self):
219
+ return self._condition
220
+
221
+ @property
222
+ def effective_cwd(self):
223
+ cwd = self._cwd_base
224
+ if self._cwd:
225
+ cwd = os.path.join(cwd, self._cwd)
226
+ return cwd
227
+
228
+ def matches(self, file_list):
229
+ """Returns true if the pattern matches any of files in the list."""
230
+ if not self._pattern:
231
+ return True
232
+ pattern = re.compile(self._pattern)
233
+ return bool([f for f in file_list if pattern.search(f)])
234
+
235
+ def run(self):
236
+ """Executes the hook's command (provided the condition is met)."""
237
+ if (self._condition and
238
+ not gclient_eval.EvaluateCondition(self._condition, self._variables)):
239
+ return
240
+
241
+ cmd = [arg for arg in self._action]
242
+
243
+ if cmd[0] == 'python':
244
+ cmd[0] = 'vpython'
245
+ if cmd[0] == 'vpython' and _detect_host_os() == 'win':
246
+ cmd[0] += '.bat'
247
+
248
+ try:
249
+ start_time = time.time()
250
+ gclient_utils.CheckCallAndFilter(
251
+ cmd, cwd=self.effective_cwd, print_stdout=True, show_header=True,
252
+ always_show_header=self._verbose)
253
+ except (gclient_utils.Error, subprocess2.CalledProcessError) as e:
254
+ # Use a discrete exit status code of 2 to indicate that a hook action
255
+ # failed. Users of this script may wish to treat hook action failures
256
+ # differently from VC failures.
257
+ print('Error: %s' % str(e), file=sys.stderr)
258
+ sys.exit(2)
259
+ finally:
260
+ elapsed_time = time.time() - start_time
261
+ if elapsed_time > 10:
262
+ print("Hook '%s' took %.2f secs" % (
263
+ gclient_utils.CommandToStr(cmd), elapsed_time))
264
+
265
+
266
+ class DependencySettings(object):
267
+ """Immutable configuration settings."""
268
+ def __init__(
269
+ self, parent, url, managed, custom_deps, custom_vars,
270
+ custom_hooks, deps_file, should_process, relative, condition):
271
+ # These are not mutable:
272
+ self._parent = parent
273
+ self._deps_file = deps_file
274
+ self._url = url
275
+ # The condition as string (or None). Useful to keep e.g. for flatten.
276
+ self._condition = condition
277
+ # 'managed' determines whether or not this dependency is synced/updated by
278
+ # gclient after gclient checks it out initially. The difference between
279
+ # 'managed' and 'should_process' is that the user specifies 'managed' via
280
+ # the --unmanaged command-line flag or a .gclient config, where
281
+ # 'should_process' is dynamically set by gclient if it goes over its
282
+ # recursion limit and controls gclient's behavior so it does not misbehave.
283
+ self._managed = managed
284
+ self._should_process = should_process
285
+ # If this is a recursed-upon sub-dependency, and the parent has
286
+ # use_relative_paths set, then this dependency should check out its own
287
+ # dependencies relative to that parent's path for this, rather than
288
+ # relative to the .gclient file.
289
+ self._relative = relative
290
+ # This is a mutable value which has the list of 'target_os' OSes listed in
291
+ # the current deps file.
292
+ self.local_target_os = None
293
+
294
+ # These are only set in .gclient and not in DEPS files.
295
+ self._custom_vars = custom_vars or {}
296
+ self._custom_deps = custom_deps or {}
297
+ self._custom_hooks = custom_hooks or []
298
+
299
+ # Post process the url to remove trailing slashes.
300
+ if isinstance(self.url, basestring):
301
+ # urls are sometime incorrectly written as proto://host/path/@rev. Replace
302
+ # it to proto://host/path@rev.
303
+ self.set_url(self.url.replace('/@', '@'))
304
+ elif not isinstance(self.url, (None.__class__)):
305
+ raise gclient_utils.Error(
306
+ ('dependency url must be either string or None, '
307
+ 'instead of %s') % self.url.__class__.__name__)
308
+
309
+ # Make any deps_file path platform-appropriate.
310
+ if self._deps_file:
311
+ for sep in ['/', '\\']:
312
+ self._deps_file = self._deps_file.replace(sep, os.sep)
313
+
314
+ @property
315
+ def deps_file(self):
316
+ return self._deps_file
317
+
318
+ @property
319
+ def managed(self):
320
+ return self._managed
321
+
322
+ @property
323
+ def parent(self):
324
+ return self._parent
325
+
326
+ @property
327
+ def root(self):
328
+ """Returns the root node, a GClient object."""
329
+ if not self.parent:
330
+ # This line is to signal pylint that it could be a GClient instance.
331
+ return self or GClient(None, None)
332
+ return self.parent.root
333
+
334
+ @property
335
+ def should_process(self):
336
+ """True if this dependency should be processed, i.e. checked out."""
337
+ return self._should_process
338
+
339
+ @property
340
+ def custom_vars(self):
341
+ return self._custom_vars.copy()
342
+
343
+ @property
344
+ def custom_deps(self):
345
+ return self._custom_deps.copy()
346
+
347
+ @property
348
+ def custom_hooks(self):
349
+ return self._custom_hooks[:]
350
+
351
+ @property
352
+ def url(self):
353
+ """URL after variable expansion."""
354
+ return self._url
355
+
356
+ @property
357
+ def condition(self):
358
+ return self._condition
359
+
360
+ @property
361
+ def target_os(self):
362
+ if self.local_target_os is not None:
363
+ return tuple(set(self.local_target_os).union(self.parent.target_os))
364
+ else:
365
+ return self.parent.target_os
366
+
367
+ @property
368
+ def target_cpu(self):
369
+ return self.parent.target_cpu
370
+
371
+ def set_url(self, url):
372
+ self._url = url
373
+
374
+ def get_custom_deps(self, name, url):
375
+ """Returns a custom deps if applicable."""
376
+ if self.parent:
377
+ url = self.parent.get_custom_deps(name, url)
378
+ # None is a valid return value to disable a dependency.
379
+ return self.custom_deps.get(name, url)
380
+
381
+
382
+ class Dependency(gclient_utils.WorkItem, DependencySettings):
383
+ """Object that represents a dependency checkout."""
384
+
385
+ def __init__(self, parent, name, url, managed, custom_deps,
386
+ custom_vars, custom_hooks, deps_file, should_process,
387
+ should_recurse, relative, condition, print_outbuf=False):
388
+ gclient_utils.WorkItem.__init__(self, name)
389
+ DependencySettings.__init__(
390
+ self, parent, url, managed, custom_deps, custom_vars,
391
+ custom_hooks, deps_file, should_process, relative, condition)
392
+
393
+ # This is in both .gclient and DEPS files:
394
+ self._deps_hooks = []
395
+
396
+ self._pre_deps_hooks = []
397
+
398
+ # Calculates properties:
399
+ self._dependencies = []
400
+ self._vars = {}
401
+
402
+ # A cache of the files affected by the current operation, necessary for
403
+ # hooks.
404
+ self._file_list = []
405
+ # List of host names from which dependencies are allowed.
406
+ # Default is an empty set, meaning unspecified in DEPS file, and hence all
407
+ # hosts will be allowed. Non-empty set means whitelist of hosts.
408
+ # allowed_hosts var is scoped to its DEPS file, and so it isn't recursive.
409
+ self._allowed_hosts = frozenset()
410
+ self._gn_args_from = None
411
+ # Spec for .gni output to write (if any).
412
+ self._gn_args_file = None
413
+ self._gn_args = []
414
+ # If it is not set to True, the dependency wasn't processed for its child
415
+ # dependency, i.e. its DEPS wasn't read.
416
+ self._deps_parsed = False
417
+ # This dependency has been processed, i.e. checked out
418
+ self._processed = False
419
+ # This dependency had its pre-DEPS hooks run
420
+ self._pre_deps_hooks_ran = False
421
+ # This dependency had its hook run
422
+ self._hooks_ran = False
423
+ # This is the scm used to checkout self.url. It may be used by dependencies
424
+ # to get the datetime of the revision we checked out.
425
+ self._used_scm = None
426
+ self._used_revision = None
427
+ # The actual revision we ended up getting, or None if that information is
428
+ # unavailable
429
+ self._got_revision = None
430
+ # Whether this dependency should use relative paths.
431
+ self._use_relative_paths = False
432
+
433
+ # recursedeps is a mutable value that selectively overrides the default
434
+ # 'no recursion' setting on a dep-by-dep basis.
435
+ #
436
+ # It will be a dictionary of {deps_name: depfile_namee}
437
+ self.recursedeps = {}
438
+
439
+ # Whether we should process this dependency's DEPS file.
440
+ self._should_recurse = should_recurse
441
+
442
+ self._OverrideUrl()
443
+ # This is inherited from WorkItem. We want the URL to be a resource.
444
+ if self.url and isinstance(self.url, basestring):
445
+ # The url is usually given to gclient either as https://blah@123
446
+ # or just https://blah. The @123 portion is irrelevant.
447
+ self.resources.append(self.url.split('@')[0])
448
+
449
+ # Controls whether we want to print git's output when we first clone the
450
+ # dependency
451
+ self.print_outbuf = print_outbuf
452
+
453
+ if not self.name and self.parent:
454
+ raise gclient_utils.Error('Dependency without name')
455
+
456
+ def _OverrideUrl(self):
457
+ """Resolves the parsed url from the parent hierarchy."""
458
+ parsed_url = self.get_custom_deps(self._name, self.url)
459
+ if parsed_url != self.url:
460
+ logging.info('Dependency(%s)._OverrideUrl(%s) -> %s', self._name,
461
+ self.url, parsed_url)
462
+ self.set_url(parsed_url)
463
+ return
464
+
465
+ if self.url is None:
466
+ logging.info('Dependency(%s)._OverrideUrl(None) -> None', self._name)
467
+ return
468
+
469
+ if not isinstance(self.url, basestring):
470
+ raise gclient_utils.Error('Unknown url type')
471
+
472
+ # self.url is a local path
473
+ path, at, rev = self.url.partition('@')
474
+ if os.path.isdir(path):
475
+ return
476
+
477
+ # self.url is a URL
478
+ parsed_url = urlparse.urlparse(self.url)
479
+ if parsed_url[0] or re.match(r'^\w+\@[\w\.-]+\:[\w\/]+', parsed_url[2]):
480
+ return
481
+
482
+ # self.url is relative to the parent's URL.
483
+ if not path.startswith('/'):
484
+ raise gclient_utils.Error(
485
+ 'relative DEPS entry \'%s\' must begin with a slash' % self.url)
486
+
487
+ parent_url = self.parent.url
488
+ parent_path = self.parent.url.split('@')[0]
489
+ if os.path.isdir(parent_path):
490
+ # Parent's URL is a local path. Get parent's URL dirname and append
491
+ # self.url.
492
+ parent_path = os.path.dirname(parent_path)
493
+ parsed_url = parent_path + path.replace('/', os.sep) + at + rev
494
+ else:
495
+ # Parent's URL is a URL. Get parent's URL, strip from the last '/'
496
+ # (equivalent to unix dirname) and append self.url.
497
+ parsed_url = parent_url[:parent_url.rfind('/')] + self.url
498
+
499
+ logging.info('Dependency(%s)._OverrideUrl(%s) -> %s', self.name,
500
+ self.url, parsed_url)
501
+ self.set_url(parsed_url)
502
+
503
+ def PinToActualRevision(self):
504
+ """Updates self.url to the revision checked out on disk."""
505
+ if self.url is None:
506
+ return
507
+ url = None
508
+ scm = self.CreateSCM()
509
+ if os.path.isdir(scm.checkout_path):
510
+ revision = scm.revinfo(None, None, None)
511
+ url = '%s@%s' % (gclient_utils.SplitUrlRevision(self.url)[0], revision)
512
+ self.set_url(url)
513
+
514
+ def ToLines(self):
515
+ s = []
516
+ condition_part = ([' "condition": %r,' % self.condition]
517
+ if self.condition else [])
518
+ s.extend([
519
+ ' # %s' % self.hierarchy(include_url=False),
520
+ ' "%s": {' % (self.name,),
521
+ ' "url": "%s",' % (self.url,),
522
+ ] + condition_part + [
523
+ ' },',
524
+ '',
525
+ ])
526
+ return s
527
+
528
+ @property
529
+ def requirements(self):
530
+ """Calculate the list of requirements."""
531
+ requirements = set()
532
+ # self.parent is implicitly a requirement. This will be recursive by
533
+ # definition.
534
+ if self.parent and self.parent.name:
535
+ requirements.add(self.parent.name)
536
+
537
+ # For a tree with at least 2 levels*, the leaf node needs to depend
538
+ # on the level higher up in an orderly way.
539
+ # This becomes messy for >2 depth as the DEPS file format is a dictionary,
540
+ # thus unsorted, while the .gclient format is a list thus sorted.
541
+ #
542
+ # Interestingly enough, the following condition only works in the case we
543
+ # want: self is a 2nd level node. 3rd level node wouldn't need this since
544
+ # they already have their parent as a requirement.
545
+ if self.parent and self.parent.parent and not self.parent.parent.parent:
546
+ requirements |= set(i.name for i in self.root.dependencies if i.name)
547
+
548
+ if self.name:
549
+ requirements |= set(
550
+ obj.name for obj in self.root.subtree(False)
551
+ if (obj is not self
552
+ and obj.name and
553
+ self.name.startswith(posixpath.join(obj.name, ''))))
554
+ requirements = tuple(sorted(requirements))
555
+ logging.info('Dependency(%s).requirements = %s' % (self.name, requirements))
556
+ return requirements
557
+
558
+ @property
559
+ def should_recurse(self):
560
+ return self._should_recurse
561
+
562
+ def verify_validity(self):
563
+ """Verifies that this Dependency is fine to add as a child of another one.
564
+
565
+ Returns True if this entry should be added, False if it is a duplicate of
566
+ another entry.
567
+ """
568
+ logging.info('Dependency(%s).verify_validity()' % self.name)
569
+ if self.name in [s.name for s in self.parent.dependencies]:
570
+ raise gclient_utils.Error(
571
+ 'The same name "%s" appears multiple times in the deps section' %
572
+ self.name)
573
+ if not self.should_process:
574
+ # Return early, no need to set requirements.
575
+ return not any(d.name == self.name for d in self.root.subtree(True))
576
+
577
+ # This require a full tree traversal with locks.
578
+ siblings = [d for d in self.root.subtree(False) if d.name == self.name]
579
+ for sibling in siblings:
580
+ # Allow to have only one to be None or ''.
581
+ if self.url != sibling.url and bool(self.url) == bool(sibling.url):
582
+ raise gclient_utils.Error(
583
+ ('Dependency %s specified more than once:\n'
584
+ ' %s [%s]\n'
585
+ 'vs\n'
586
+ ' %s [%s]') % (
587
+ self.name,
588
+ sibling.hierarchy(),
589
+ sibling.url,
590
+ self.hierarchy(),
591
+ self.url))
592
+ # In theory we could keep it as a shadow of the other one. In
593
+ # practice, simply ignore it.
594
+ logging.warning("Won't process duplicate dependency %s" % sibling)
595
+ return False
596
+ return True
597
+
598
+ def _postprocess_deps(self, deps, rel_prefix):
599
+ """Performs post-processing of deps compared to what's in the DEPS file."""
600
+ # Make sure the dict is mutable, e.g. in case it's frozen.
601
+ deps = dict(deps)
602
+
603
+ # If a line is in custom_deps, but not in the solution, we want to append
604
+ # this line to the solution.
605
+ for dep_name, dep_info in self.custom_deps.items():
606
+ if dep_name not in deps:
607
+ deps[dep_name] = {'url': dep_info, 'dep_type': 'git'}
608
+
609
+ # Make child deps conditional on any parent conditions. This ensures that,
610
+ # when flattened, recursed entries have the correct restrictions, even if
611
+ # not explicitly set in the recursed DEPS file. For instance, if
612
+ # "src/ios_foo" is conditional on "checkout_ios=True", then anything
613
+ # recursively included by "src/ios_foo/DEPS" should also require
614
+ # "checkout_ios=True".
615
+ if self.condition:
616
+ for value in deps.values():
617
+ gclient_eval.UpdateCondition(value, 'and', self.condition)
618
+
619
+ if rel_prefix:
620
+ logging.warning('use_relative_paths enabled.')
621
+ rel_deps = {}
622
+ for d, url in deps.items():
623
+ # normpath is required to allow DEPS to use .. in their
624
+ # dependency local path.
625
+ rel_deps[os.path.normpath(os.path.join(rel_prefix, d))] = url
626
+ logging.warning('Updating deps by prepending %s.', rel_prefix)
627
+ deps = rel_deps
628
+
629
+ return deps
630
+
631
+ def _deps_to_objects(self, deps, use_relative_paths):
632
+ """Convert a deps dict to a dict of Dependency objects."""
633
+ deps_to_add = []
634
+ for name, dep_value in deps.items():
635
+ should_process = self.should_process
636
+ if dep_value is None:
637
+ continue
638
+
639
+ condition = dep_value.get('condition')
640
+ dep_type = dep_value.get('dep_type')
641
+
642
+ if condition and not self._get_option('process_all_deps', False):
643
+ should_process = should_process and gclient_eval.EvaluateCondition(
644
+ condition, self.get_vars())
645
+
646
+ # The following option is only set by the 'revinfo' command.
647
+ if self._get_option('ignore_dep_type', None) == dep_type:
648
+ continue
649
+
650
+ if dep_type == 'cipd':
651
+ cipd_root = self.GetCipdRoot()
652
+ for package in dep_value.get('packages', []):
653
+ deps_to_add.append(
654
+ CipdDependency(
655
+ parent=self,
656
+ name=name,
657
+ dep_value=package,
658
+ cipd_root=cipd_root,
659
+ custom_vars=self.custom_vars,
660
+ should_process=should_process,
661
+ relative=use_relative_paths,
662
+ condition=condition))
663
+ else:
664
+ url = dep_value.get('url')
665
+ deps_to_add.append(
666
+ GitDependency(
667
+ parent=self,
668
+ name=name,
669
+ url=url,
670
+ managed=True,
671
+ custom_deps=None,
672
+ custom_vars=self.custom_vars,
673
+ custom_hooks=None,
674
+ deps_file=self.recursedeps.get(name, self.deps_file),
675
+ should_process=should_process,
676
+ should_recurse=name in self.recursedeps,
677
+ relative=use_relative_paths,
678
+ condition=condition))
679
+
680
+ deps_to_add.sort(key=lambda x: x.name)
681
+ return deps_to_add
682
+
683
+ def ParseDepsFile(self):
684
+ """Parses the DEPS file for this dependency."""
685
+ assert not self.deps_parsed
686
+ assert not self.dependencies
687
+
688
+ deps_content = None
689
+
690
+ # First try to locate the configured deps file. If it's missing, fallback
691
+ # to DEPS.
692
+ deps_files = [self.deps_file]
693
+ if 'DEPS' not in deps_files:
694
+ deps_files.append('DEPS')
695
+ for deps_file in deps_files:
696
+ filepath = os.path.join(self.root.root_dir, self.name, deps_file)
697
+ if os.path.isfile(filepath):
698
+ logging.info(
699
+ 'ParseDepsFile(%s): %s file found at %s', self.name, deps_file,
700
+ filepath)
701
+ break
702
+ logging.info(
703
+ 'ParseDepsFile(%s): No %s file found at %s', self.name, deps_file,
704
+ filepath)
705
+
706
+ if os.path.isfile(filepath):
707
+ deps_content = gclient_utils.FileRead(filepath)
708
+ logging.debug('ParseDepsFile(%s) read:\n%s', self.name, deps_content)
709
+
710
+ local_scope = {}
711
+ if deps_content:
712
+ try:
713
+ local_scope = gclient_eval.Parse(
714
+ deps_content, filepath, self.get_vars(), self.get_builtin_vars())
715
+ except SyntaxError as e:
716
+ gclient_utils.SyntaxErrorToError(filepath, e)
717
+
718
+ if 'allowed_hosts' in local_scope:
719
+ try:
720
+ self._allowed_hosts = frozenset(local_scope.get('allowed_hosts'))
721
+ except TypeError: # raised if non-iterable
722
+ pass
723
+ if not self._allowed_hosts:
724
+ logging.warning("allowed_hosts is specified but empty %s",
725
+ self._allowed_hosts)
726
+ raise gclient_utils.Error(
727
+ 'ParseDepsFile(%s): allowed_hosts must be absent '
728
+ 'or a non-empty iterable' % self.name)
729
+
730
+ self._gn_args_from = local_scope.get('gclient_gn_args_from')
731
+ self._gn_args_file = local_scope.get('gclient_gn_args_file')
732
+ self._gn_args = local_scope.get('gclient_gn_args', [])
733
+ # It doesn't make sense to set all of these, since setting gn_args_from to
734
+ # another DEPS will make gclient ignore any other local gn_args* settings.
735
+ assert not (self._gn_args_from and self._gn_args_file), \
736
+ 'Only specify one of "gclient_gn_args_from" or ' \
737
+ '"gclient_gn_args_file + gclient_gn_args".'
738
+
739
+ self._vars = local_scope.get('vars', {})
740
+ if self.parent:
741
+ for key, value in self.parent.get_vars().items():
742
+ if key in self._vars:
743
+ self._vars[key] = value
744
+ # Since we heavily post-process things, freeze ones which should
745
+ # reflect original state of DEPS.
746
+ self._vars = gclient_utils.freeze(self._vars)
747
+
748
+ # If use_relative_paths is set in the DEPS file, regenerate
749
+ # the dictionary using paths relative to the directory containing
750
+ # the DEPS file. Also update recursedeps if use_relative_paths is
751
+ # enabled.
752
+ # If the deps file doesn't set use_relative_paths, but the parent did
753
+ # (and therefore set self.relative on this Dependency object), then we
754
+ # want to modify the deps and recursedeps by prepending the parent
755
+ # directory of this dependency.
756
+ self._use_relative_paths = local_scope.get('use_relative_paths', False)
757
+ rel_prefix = None
758
+ if self._use_relative_paths:
759
+ rel_prefix = self.name
760
+ elif self._relative:
761
+ rel_prefix = os.path.dirname(self.name)
762
+
763
+ if 'recursion' in local_scope:
764
+ logging.warning(
765
+ '%s: Ignoring recursion = %d.', self.name, local_scope['recursion'])
766
+
767
+ if 'recursedeps' in local_scope:
768
+ for ent in local_scope['recursedeps']:
769
+ if isinstance(ent, basestring):
770
+ self.recursedeps[ent] = self.deps_file
771
+ else: # (depname, depsfilename)
772
+ self.recursedeps[ent[0]] = ent[1]
773
+ logging.warning('Found recursedeps %r.', repr(self.recursedeps))
774
+
775
+ if rel_prefix:
776
+ logging.warning('Updating recursedeps by prepending %s.', rel_prefix)
777
+ rel_deps = {}
778
+ for depname, options in self.recursedeps.items():
779
+ rel_deps[
780
+ os.path.normpath(os.path.join(rel_prefix, depname))] = options
781
+ self.recursedeps = rel_deps
782
+ # To get gn_args from another DEPS, that DEPS must be recursed into.
783
+ if self._gn_args_from:
784
+ assert self.recursedeps and self._gn_args_from in self.recursedeps, \
785
+ 'The "gclient_gn_args_from" value must be in recursedeps.'
786
+
787
+ # If present, save 'target_os' in the local_target_os property.
788
+ if 'target_os' in local_scope:
789
+ self.local_target_os = local_scope['target_os']
790
+
791
+ deps = local_scope.get('deps', {})
792
+ deps_to_add = self._deps_to_objects(
793
+ self._postprocess_deps(deps, rel_prefix), self._use_relative_paths)
794
+
795
+ # compute which working directory should be used for hooks
796
+ use_relative_hooks = local_scope.get('use_relative_hooks', False)
797
+ hooks_cwd = self.root.root_dir
798
+ if use_relative_hooks:
799
+ if not self._use_relative_paths:
800
+ raise gclient_utils.Error(
801
+ 'ParseDepsFile(%s): use_relative_hooks must be used with '
802
+ 'use_relative_paths' % self.name)
803
+ hooks_cwd = os.path.join(hooks_cwd, self.name)
804
+ logging.warning('Updating hook base working directory to %s.',
805
+ hooks_cwd)
806
+
807
+ # override named sets of hooks by the custom hooks
808
+ hooks_to_run = []
809
+ hook_names_to_suppress = [c.get('name', '') for c in self.custom_hooks]
810
+ for hook in local_scope.get('hooks', []):
811
+ if hook.get('name', '') not in hook_names_to_suppress:
812
+ hooks_to_run.append(hook)
813
+
814
+ # add the replacements and any additions
815
+ for hook in self.custom_hooks:
816
+ if 'action' in hook:
817
+ hooks_to_run.append(hook)
818
+
819
+ if self.should_recurse:
820
+ self._pre_deps_hooks = [
821
+ Hook.from_dict(hook, variables=self.get_vars(), verbose=True,
822
+ conditions=self.condition, cwd_base=hooks_cwd)
823
+ for hook in local_scope.get('pre_deps_hooks', [])
824
+ ]
825
+
826
+ self.add_dependencies_and_close(deps_to_add, hooks_to_run,
827
+ hooks_cwd=hooks_cwd)
828
+ logging.info('ParseDepsFile(%s) done' % self.name)
829
+
830
+ def _get_option(self, attr, default):
831
+ obj = self
832
+ while not hasattr(obj, '_options'):
833
+ obj = obj.parent
834
+ return getattr(obj._options, attr, default)
835
+
836
+ def add_dependencies_and_close(self, deps_to_add, hooks, hooks_cwd=None):
837
+ """Adds the dependencies, hooks and mark the parsing as done."""
838
+ if hooks_cwd == None:
839
+ hooks_cwd = self.root.root_dir
840
+
841
+ for dep in deps_to_add:
842
+ if dep.verify_validity():
843
+ self.add_dependency(dep)
844
+ self._mark_as_parsed([
845
+ Hook.from_dict(
846
+ h, variables=self.get_vars(), verbose=self.root._options.verbose,
847
+ conditions=self.condition, cwd_base=hooks_cwd)
848
+ for h in hooks
849
+ ])
850
+
851
+ def findDepsFromNotAllowedHosts(self):
852
+ """Returns a list of dependencies from not allowed hosts.
853
+
854
+ If allowed_hosts is not set, allows all hosts and returns empty list.
855
+ """
856
+ if not self._allowed_hosts:
857
+ return []
858
+ bad_deps = []
859
+ for dep in self._dependencies:
860
+ # Don't enforce this for custom_deps.
861
+ if dep.name in self._custom_deps:
862
+ continue
863
+ if isinstance(dep.url, basestring):
864
+ parsed_url = urlparse.urlparse(dep.url)
865
+ if parsed_url.netloc and parsed_url.netloc not in self._allowed_hosts:
866
+ bad_deps.append(dep)
867
+ return bad_deps
868
+
869
+ def FuzzyMatchUrl(self, candidates):
870
+ """Attempts to find this dependency in the list of candidates.
871
+
872
+ It looks first for the URL of this dependency in the list of
873
+ candidates. If it doesn't succeed, and the URL ends in '.git', it will try
874
+ looking for the URL minus '.git'. Finally it will try to look for the name
875
+ of the dependency.
876
+
877
+ Args:
878
+ candidates: list, dict. The list of candidates in which to look for this
879
+ dependency. It can contain URLs as above, or dependency names like
880
+ "src/some/dep".
881
+
882
+ Returns:
883
+ If this dependency is not found in the list of candidates, returns None.
884
+ Otherwise, it returns under which name did we find this dependency:
885
+ - Its parsed url: "https://example.com/src.git'
886
+ - Its parsed url minus '.git': "https://example.com/src"
887
+ - Its name: "src"
888
+ """
889
+ if self.url:
890
+ origin, _ = gclient_utils.SplitUrlRevision(self.url)
891
+ if origin in candidates:
892
+ return origin
893
+ if origin.endswith('.git') and origin[:-len('.git')] in candidates:
894
+ return origin[:-len('.git')]
895
+ if origin + '.git' in candidates:
896
+ return origin + '.git'
897
+ if self.name in candidates:
898
+ return self.name
899
+ return None
900
+
901
+ # Arguments number differs from overridden method
902
+ # pylint: disable=arguments-differ
903
+ def run(self, revision_overrides, command, args, work_queue, options,
904
+ patch_refs, target_branches):
905
+ """Runs |command| then parse the DEPS file."""
906
+ logging.info('Dependency(%s).run()' % self.name)
907
+ assert self._file_list == []
908
+ if not self.should_process:
909
+ return
910
+ # When running runhooks, there's no need to consult the SCM.
911
+ # All known hooks are expected to run unconditionally regardless of working
912
+ # copy state, so skip the SCM status check.
913
+ run_scm = command not in (
914
+ 'flatten', 'runhooks', 'recurse', 'validate', None)
915
+ file_list = [] if not options.nohooks else None
916
+ revision_override = revision_overrides.pop(
917
+ self.FuzzyMatchUrl(revision_overrides), None)
918
+ if not revision_override and not self.managed:
919
+ revision_override = 'unmanaged'
920
+ if run_scm and self.url:
921
+ # Create a shallow copy to mutate revision.
922
+ options = copy.copy(options)
923
+ options.revision = revision_override
924
+ self._used_revision = options.revision
925
+ self._used_scm = self.CreateSCM(out_cb=work_queue.out_cb)
926
+ self._got_revision = self._used_scm.RunCommand(command, options, args,
927
+ file_list)
928
+
929
+ patch_repo = self.url.split('@')[0]
930
+ patch_ref = patch_refs.pop(self.FuzzyMatchUrl(patch_refs), None)
931
+ target_branch = target_branches.pop(
932
+ self.FuzzyMatchUrl(target_branches), None)
933
+ if command == 'update' and patch_ref is not None:
934
+ self._used_scm.apply_patch_ref(patch_repo, patch_ref, target_branch,
935
+ options, file_list)
936
+
937
+ if file_list:
938
+ file_list = [os.path.join(self.name, f.strip()) for f in file_list]
939
+
940
+ # TODO(phajdan.jr): We should know exactly when the paths are absolute.
941
+ # Convert all absolute paths to relative.
942
+ for i in range(len(file_list or [])):
943
+ # It depends on the command being executed (like runhooks vs sync).
944
+ if not os.path.isabs(file_list[i]):
945
+ continue
946
+ prefix = os.path.commonprefix(
947
+ [self.root.root_dir.lower(), file_list[i].lower()])
948
+ file_list[i] = file_list[i][len(prefix):]
949
+ # Strip any leading path separators.
950
+ while file_list[i].startswith(('\\', '/')):
951
+ file_list[i] = file_list[i][1:]
952
+
953
+ if self.should_recurse:
954
+ self.ParseDepsFile()
955
+
956
+ self._run_is_done(file_list or [])
957
+
958
+ if self.should_recurse:
959
+ if command in ('update', 'revert') and not options.noprehooks:
960
+ self.RunPreDepsHooks()
961
+ # Parse the dependencies of this dependency.
962
+ for s in self.dependencies:
963
+ if s.should_process:
964
+ work_queue.enqueue(s)
965
+
966
+ if command == 'recurse':
967
+ # Skip file only checkout.
968
+ scm = self.GetScmName()
969
+ if not options.scm or scm in options.scm:
970
+ cwd = os.path.normpath(os.path.join(self.root.root_dir, self.name))
971
+ # Pass in the SCM type as an env variable. Make sure we don't put
972
+ # unicode strings in the environment.
973
+ env = os.environ.copy()
974
+ if scm:
975
+ env['GCLIENT_SCM'] = str(scm)
976
+ if self.url:
977
+ env['GCLIENT_URL'] = str(self.url)
978
+ env['GCLIENT_DEP_PATH'] = str(self.name)
979
+ if options.prepend_dir and scm == 'git':
980
+ print_stdout = False
981
+ def filter_fn(line):
982
+ """Git-specific path marshaling. It is optimized for git-grep."""
983
+
984
+ def mod_path(git_pathspec):
985
+ match = re.match('^(\\S+?:)?([^\0]+)$', git_pathspec)
986
+ modified_path = os.path.join(self.name, match.group(2))
987
+ branch = match.group(1) or ''
988
+ return '%s%s' % (branch, modified_path)
989
+
990
+ match = re.match('^Binary file ([^\0]+) matches$', line)
991
+ if match:
992
+ print('Binary file %s matches\n' % mod_path(match.group(1)))
993
+ return
994
+
995
+ items = line.split('\0')
996
+ if len(items) == 2 and items[1]:
997
+ print('%s : %s' % (mod_path(items[0]), items[1]))
998
+ elif len(items) >= 2:
999
+ # Multiple null bytes or a single trailing null byte indicate
1000
+ # git is likely displaying filenames only (such as with -l)
1001
+ print('\n'.join(mod_path(path) for path in items if path))
1002
+ else:
1003
+ print(line)
1004
+ else:
1005
+ print_stdout = True
1006
+ filter_fn = None
1007
+
1008
+ if self.url is None:
1009
+ print('Skipped omitted dependency %s' % cwd, file=sys.stderr)
1010
+ elif os.path.isdir(cwd):
1011
+ try:
1012
+ gclient_utils.CheckCallAndFilter(
1013
+ args, cwd=cwd, env=env, print_stdout=print_stdout,
1014
+ filter_fn=filter_fn,
1015
+ )
1016
+ except subprocess2.CalledProcessError:
1017
+ if not options.ignore:
1018
+ raise
1019
+ else:
1020
+ print('Skipped missing %s' % cwd, file=sys.stderr)
1021
+
1022
+ def GetScmName(self):
1023
+ raise NotImplementedError()
1024
+
1025
+ def CreateSCM(self, out_cb=None):
1026
+ raise NotImplementedError()
1027
+
1028
+ def HasGNArgsFile(self):
1029
+ return self._gn_args_file is not None
1030
+
1031
+ def WriteGNArgsFile(self):
1032
+ lines = ['# Generated from %r' % self.deps_file]
1033
+ variables = self.get_vars()
1034
+ for arg in self._gn_args:
1035
+ value = variables[arg]
1036
+ if isinstance(value, gclient_eval.ConstantString):
1037
+ value = value.value
1038
+ elif isinstance(value, basestring):
1039
+ value = gclient_eval.EvaluateCondition(value, variables)
1040
+ lines.append('%s = %s' % (arg, ToGNString(value)))
1041
+
1042
+ # When use_relative_paths is set, gn_args_file is relative to this DEPS
1043
+ path_prefix = self.root.root_dir
1044
+ if self._use_relative_paths:
1045
+ path_prefix = os.path.join(path_prefix, self.name)
1046
+
1047
+ with open(os.path.join(path_prefix, self._gn_args_file), 'wb') as f:
1048
+ f.write('\n'.join(lines).encode('utf-8', 'replace'))
1049
+
1050
+ @gclient_utils.lockedmethod
1051
+ def _run_is_done(self, file_list):
1052
+ # Both these are kept for hooks that are run as a separate tree traversal.
1053
+ self._file_list = file_list
1054
+ self._processed = True
1055
+
1056
+ def GetHooks(self, options):
1057
+ """Evaluates all hooks, and return them in a flat list.
1058
+
1059
+ RunOnDeps() must have been called before to load the DEPS.
1060
+ """
1061
+ result = []
1062
+ if not self.should_process or not self.should_recurse:
1063
+ # Don't run the hook when it is above recursion_limit.
1064
+ return result
1065
+ # If "--force" was specified, run all hooks regardless of what files have
1066
+ # changed.
1067
+ if self.deps_hooks:
1068
+ # TODO(maruel): If the user is using git, then we don't know
1069
+ # what files have changed so we always run all hooks. It'd be nice to fix
1070
+ # that.
1071
+ result.extend(self.deps_hooks)
1072
+ for s in self.dependencies:
1073
+ result.extend(s.GetHooks(options))
1074
+ return result
1075
+
1076
+ def RunHooksRecursively(self, options, progress):
1077
+ assert self.hooks_ran == False
1078
+ self._hooks_ran = True
1079
+ hooks = self.GetHooks(options)
1080
+ if progress:
1081
+ progress._total = len(hooks)
1082
+ for hook in hooks:
1083
+ if progress:
1084
+ progress.update(extra=hook.name or '')
1085
+ hook.run()
1086
+ if progress:
1087
+ progress.end()
1088
+
1089
+ def RunPreDepsHooks(self):
1090
+ assert self.processed
1091
+ assert self.deps_parsed
1092
+ assert not self.pre_deps_hooks_ran
1093
+ assert not self.hooks_ran
1094
+ for s in self.dependencies:
1095
+ assert not s.processed
1096
+ self._pre_deps_hooks_ran = True
1097
+ for hook in self.pre_deps_hooks:
1098
+ hook.run()
1099
+
1100
+ def GetCipdRoot(self):
1101
+ if self.root is self:
1102
+ # Let's not infinitely recurse. If this is root and isn't an
1103
+ # instance of GClient, do nothing.
1104
+ return None
1105
+ return self.root.GetCipdRoot()
1106
+
1107
+ def subtree(self, include_all):
1108
+ """Breadth first recursion excluding root node."""
1109
+ dependencies = self.dependencies
1110
+ for d in dependencies:
1111
+ if d.should_process or include_all:
1112
+ yield d
1113
+ for d in dependencies:
1114
+ for i in d.subtree(include_all):
1115
+ yield i
1116
+
1117
+ @gclient_utils.lockedmethod
1118
+ def add_dependency(self, new_dep):
1119
+ self._dependencies.append(new_dep)
1120
+
1121
+ @gclient_utils.lockedmethod
1122
+ def _mark_as_parsed(self, new_hooks):
1123
+ self._deps_hooks.extend(new_hooks)
1124
+ self._deps_parsed = True
1125
+
1126
+ @property
1127
+ @gclient_utils.lockedmethod
1128
+ def dependencies(self):
1129
+ return tuple(self._dependencies)
1130
+
1131
+ @property
1132
+ @gclient_utils.lockedmethod
1133
+ def deps_hooks(self):
1134
+ return tuple(self._deps_hooks)
1135
+
1136
+ @property
1137
+ @gclient_utils.lockedmethod
1138
+ def pre_deps_hooks(self):
1139
+ return tuple(self._pre_deps_hooks)
1140
+
1141
+ @property
1142
+ @gclient_utils.lockedmethod
1143
+ def deps_parsed(self):
1144
+ """This is purely for debugging purposes. It's not used anywhere."""
1145
+ return self._deps_parsed
1146
+
1147
+ @property
1148
+ @gclient_utils.lockedmethod
1149
+ def processed(self):
1150
+ return self._processed
1151
+
1152
+ @property
1153
+ @gclient_utils.lockedmethod
1154
+ def pre_deps_hooks_ran(self):
1155
+ return self._pre_deps_hooks_ran
1156
+
1157
+ @property
1158
+ @gclient_utils.lockedmethod
1159
+ def hooks_ran(self):
1160
+ return self._hooks_ran
1161
+
1162
+ @property
1163
+ @gclient_utils.lockedmethod
1164
+ def allowed_hosts(self):
1165
+ return self._allowed_hosts
1166
+
1167
+ @property
1168
+ @gclient_utils.lockedmethod
1169
+ def file_list(self):
1170
+ return tuple(self._file_list)
1171
+
1172
+ @property
1173
+ def used_scm(self):
1174
+ """SCMWrapper instance for this dependency or None if not processed yet."""
1175
+ return self._used_scm
1176
+
1177
+ @property
1178
+ @gclient_utils.lockedmethod
1179
+ def got_revision(self):
1180
+ return self._got_revision
1181
+
1182
+ @property
1183
+ def file_list_and_children(self):
1184
+ result = list(self.file_list)
1185
+ for d in self.dependencies:
1186
+ result.extend(d.file_list_and_children)
1187
+ return tuple(result)
1188
+
1189
+ def __str__(self):
1190
+ out = []
1191
+ for i in ('name', 'url', 'custom_deps',
1192
+ 'custom_vars', 'deps_hooks', 'file_list', 'should_process',
1193
+ 'processed', 'hooks_ran', 'deps_parsed', 'requirements',
1194
+ 'allowed_hosts'):
1195
+ # First try the native property if it exists.
1196
+ if hasattr(self, '_' + i):
1197
+ value = getattr(self, '_' + i, False)
1198
+ else:
1199
+ value = getattr(self, i, False)
1200
+ if value:
1201
+ out.append('%s: %s' % (i, value))
1202
+
1203
+ for d in self.dependencies:
1204
+ out.extend([' ' + x for x in str(d).splitlines()])
1205
+ out.append('')
1206
+ return '\n'.join(out)
1207
+
1208
+ def __repr__(self):
1209
+ return '%s: %s' % (self.name, self.url)
1210
+
1211
+ def hierarchy(self, include_url=True):
1212
+ """Returns a human-readable hierarchical reference to a Dependency."""
1213
+ def format_name(d):
1214
+ if include_url:
1215
+ return '%s(%s)' % (d.name, d.url)
1216
+ return d.name
1217
+ out = format_name(self)
1218
+ i = self.parent
1219
+ while i and i.name:
1220
+ out = '%s -> %s' % (format_name(i), out)
1221
+ i = i.parent
1222
+ return out
1223
+
1224
+ def hierarchy_data(self):
1225
+ """Returns a machine-readable hierarchical reference to a Dependency."""
1226
+ d = self
1227
+ out = []
1228
+ while d and d.name:
1229
+ out.insert(0, (d.name, d.url))
1230
+ d = d.parent
1231
+ return tuple(out)
1232
+
1233
+ def get_builtin_vars(self):
1234
+ return {
1235
+ 'checkout_android': 'android' in self.target_os,
1236
+ 'checkout_chromeos': 'chromeos' in self.target_os,
1237
+ 'checkout_fuchsia': 'fuchsia' in self.target_os,
1238
+ 'checkout_ios': 'ios' in self.target_os,
1239
+ 'checkout_linux': 'unix' in self.target_os,
1240
+ 'checkout_mac': 'mac' in self.target_os,
1241
+ 'checkout_win': 'win' in self.target_os,
1242
+ 'host_os': _detect_host_os(),
1243
+
1244
+ 'checkout_arm': 'arm' in self.target_cpu,
1245
+ 'checkout_arm64': 'arm64' in self.target_cpu,
1246
+ 'checkout_x86': 'x86' in self.target_cpu,
1247
+ 'checkout_mips': 'mips' in self.target_cpu,
1248
+ 'checkout_mips64': 'mips64' in self.target_cpu,
1249
+ 'checkout_ppc': 'ppc' in self.target_cpu,
1250
+ 'checkout_s390': 's390' in self.target_cpu,
1251
+ 'checkout_x64': 'x64' in self.target_cpu,
1252
+ 'host_cpu': detect_host_arch.HostArch(),
1253
+ }
1254
+
1255
+ def get_vars(self):
1256
+ """Returns a dictionary of effective variable values
1257
+ (DEPS file contents with applied custom_vars overrides)."""
1258
+ # Variable precedence (last has highest):
1259
+ # - DEPS vars
1260
+ # - parents, from first to last
1261
+ # - built-in
1262
+ # - custom_vars overrides
1263
+ result = {}
1264
+ result.update(self._vars)
1265
+ if self.parent:
1266
+ merge_vars(result, self.parent.get_vars())
1267
+ # Provide some built-in variables.
1268
+ result.update(self.get_builtin_vars())
1269
+ merge_vars(result, self.custom_vars)
1270
+
1271
+ return result
1272
+
1273
+
1274
+ _PLATFORM_MAPPING = {
1275
+ 'cygwin': 'win',
1276
+ 'darwin': 'mac',
1277
+ 'linux2': 'linux',
1278
+ 'linux': 'linux',
1279
+ 'win32': 'win',
1280
+ 'aix6': 'aix',
1281
+ }
1282
+
1283
+
1284
+ def merge_vars(result, new_vars):
1285
+ for k, v in new_vars.items():
1286
+ if k in result:
1287
+ if isinstance(result[k], gclient_eval.ConstantString):
1288
+ if isinstance(v, gclient_eval.ConstantString):
1289
+ result[k] = v
1290
+ else:
1291
+ result[k].value = v
1292
+ else:
1293
+ result[k] = v
1294
+ else:
1295
+ result[k] = v
1296
+
1297
+
1298
+ def _detect_host_os():
1299
+ return _PLATFORM_MAPPING[sys.platform]
1300
+
1301
+
1302
+ class GitDependency(Dependency):
1303
+ """A Dependency object that represents a single git checkout."""
1304
+
1305
+ #override
1306
+ def GetScmName(self):
1307
+ """Always 'git'."""
1308
+ return 'git'
1309
+
1310
+ #override
1311
+ def CreateSCM(self, out_cb=None):
1312
+ """Create a Wrapper instance suitable for handling this git dependency."""
1313
+ return gclient_scm.GitWrapper(
1314
+ self.url, self.root.root_dir, self.name, self.outbuf, out_cb,
1315
+ print_outbuf=self.print_outbuf)
1316
+
1317
+
1318
+ class GClient(GitDependency):
1319
+ """Object that represent a gclient checkout. A tree of Dependency(), one per
1320
+ solution or DEPS entry."""
1321
+
1322
+ DEPS_OS_CHOICES = {
1323
+ "aix6": "unix",
1324
+ "win32": "win",
1325
+ "win": "win",
1326
+ "cygwin": "win",
1327
+ "darwin": "mac",
1328
+ "mac": "mac",
1329
+ "unix": "unix",
1330
+ "linux": "unix",
1331
+ "linux2": "unix",
1332
+ "linux3": "unix",
1333
+ "android": "android",
1334
+ "ios": "ios",
1335
+ "fuchsia": "fuchsia",
1336
+ "chromeos": "chromeos",
1337
+ }
1338
+
1339
+ DEFAULT_CLIENT_FILE_TEXT = ("""\
1340
+ solutions = [
1341
+ { "name" : %(solution_name)r,
1342
+ "url" : %(solution_url)r,
1343
+ "deps_file" : %(deps_file)r,
1344
+ "managed" : %(managed)r,
1345
+ "custom_deps" : {
1346
+ },
1347
+ "custom_vars": %(custom_vars)r,
1348
+ },
1349
+ ]
1350
+ """)
1351
+
1352
+ DEFAULT_CLIENT_CACHE_DIR_TEXT = ("""\
1353
+ cache_dir = %(cache_dir)r
1354
+ """)
1355
+
1356
+
1357
+ DEFAULT_SNAPSHOT_FILE_TEXT = ("""\
1358
+ # Snapshot generated with gclient revinfo --snapshot
1359
+ solutions = %(solution_list)s
1360
+ """)
1361
+
1362
+ def __init__(self, root_dir, options):
1363
+ # Do not change previous behavior. Only solution level and immediate DEPS
1364
+ # are processed.
1365
+ self._recursion_limit = 2
1366
+ super(GClient, self).__init__(
1367
+ parent=None,
1368
+ name=None,
1369
+ url=None,
1370
+ managed=True,
1371
+ custom_deps=None,
1372
+ custom_vars=None,
1373
+ custom_hooks=None,
1374
+ deps_file='unused',
1375
+ should_process=True,
1376
+ should_recurse=True,
1377
+ relative=None,
1378
+ condition=None,
1379
+ print_outbuf=True)
1380
+
1381
+ self._options = options
1382
+ if options.deps_os:
1383
+ enforced_os = options.deps_os.split(',')
1384
+ else:
1385
+ enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')]
1386
+ if 'all' in enforced_os:
1387
+ enforced_os = self.DEPS_OS_CHOICES.values()
1388
+ self._enforced_os = tuple(set(enforced_os))
1389
+ self._enforced_cpu = detect_host_arch.HostArch(),
1390
+ self._root_dir = root_dir
1391
+ self._cipd_root = None
1392
+ self.config_content = None
1393
+
1394
+ def _CheckConfig(self):
1395
+ """Verify that the config matches the state of the existing checked-out
1396
+ solutions."""
1397
+ for dep in self.dependencies:
1398
+ if dep.managed and dep.url:
1399
+ scm = dep.CreateSCM()
1400
+ actual_url = scm.GetActualRemoteURL(self._options)
1401
+ if actual_url and not scm.DoesRemoteURLMatch(self._options):
1402
+ mirror = scm.GetCacheMirror()
1403
+ if mirror:
1404
+ mirror_string = '%s (exists=%s)' % (mirror.mirror_path,
1405
+ mirror.exists())
1406
+ else:
1407
+ mirror_string = 'not used'
1408
+ raise gclient_utils.Error(
1409
+ '''
1410
+ Your .gclient file seems to be broken. The requested URL is different from what
1411
+ is actually checked out in %(checkout_path)s.
1412
+
1413
+ The .gclient file contains:
1414
+ URL: %(expected_url)s (%(expected_scm)s)
1415
+ Cache mirror: %(mirror_string)s
1416
+
1417
+ The local checkout in %(checkout_path)s reports:
1418
+ %(actual_url)s (%(actual_scm)s)
1419
+
1420
+ You should ensure that the URL listed in .gclient is correct and either change
1421
+ it or fix the checkout.
1422
+ ''' % {
1423
+ 'checkout_path': os.path.join(self.root_dir, dep.name),
1424
+ 'expected_url': dep.url,
1425
+ 'expected_scm': dep.GetScmName(),
1426
+ 'mirror_string': mirror_string,
1427
+ 'actual_url': actual_url,
1428
+ 'actual_scm': dep.GetScmName()
1429
+ })
1430
+
1431
+ def SetConfig(self, content):
1432
+ assert not self.dependencies
1433
+ config_dict = {}
1434
+ self.config_content = content
1435
+ try:
1436
+ exec(content, config_dict)
1437
+ except SyntaxError as e:
1438
+ gclient_utils.SyntaxErrorToError('.gclient', e)
1439
+
1440
+ # Append any target OS that is not already being enforced to the tuple.
1441
+ target_os = config_dict.get('target_os', [])
1442
+ if config_dict.get('target_os_only', False):
1443
+ self._enforced_os = tuple(set(target_os))
1444
+ else:
1445
+ self._enforced_os = tuple(set(self._enforced_os).union(target_os))
1446
+
1447
+ # Append any target CPU that is not already being enforced to the tuple.
1448
+ target_cpu = config_dict.get('target_cpu', [])
1449
+ if config_dict.get('target_cpu_only', False):
1450
+ self._enforced_cpu = tuple(set(target_cpu))
1451
+ else:
1452
+ self._enforced_cpu = tuple(set(self._enforced_cpu).union(target_cpu))
1453
+
1454
+ cache_dir = config_dict.get('cache_dir', UNSET_CACHE_DIR)
1455
+ if cache_dir is not UNSET_CACHE_DIR:
1456
+ if cache_dir:
1457
+ cache_dir = os.path.join(self.root_dir, cache_dir)
1458
+ cache_dir = os.path.abspath(cache_dir)
1459
+
1460
+ git_cache.Mirror.SetCachePath(cache_dir)
1461
+
1462
+ if not target_os and config_dict.get('target_os_only', False):
1463
+ raise gclient_utils.Error('Can\'t use target_os_only if target_os is '
1464
+ 'not specified')
1465
+
1466
+ if not target_cpu and config_dict.get('target_cpu_only', False):
1467
+ raise gclient_utils.Error('Can\'t use target_cpu_only if target_cpu is '
1468
+ 'not specified')
1469
+
1470
+ deps_to_add = []
1471
+ for s in config_dict.get('solutions', []):
1472
+ try:
1473
+ deps_to_add.append(GitDependency(
1474
+ parent=self,
1475
+ name=s['name'],
1476
+ url=s['url'],
1477
+ managed=s.get('managed', True),
1478
+ custom_deps=s.get('custom_deps', {}),
1479
+ custom_vars=s.get('custom_vars', {}),
1480
+ custom_hooks=s.get('custom_hooks', []),
1481
+ deps_file=s.get('deps_file', 'DEPS'),
1482
+ should_process=True,
1483
+ should_recurse=True,
1484
+ relative=None,
1485
+ condition=None,
1486
+ print_outbuf=True))
1487
+ except KeyError:
1488
+ raise gclient_utils.Error('Invalid .gclient file. Solution is '
1489
+ 'incomplete: %s' % s)
1490
+ metrics.collector.add(
1491
+ 'project_urls',
1492
+ [
1493
+ dep.FuzzyMatchUrl(metrics_utils.KNOWN_PROJECT_URLS)
1494
+ for dep in deps_to_add
1495
+ if dep.FuzzyMatchUrl(metrics_utils.KNOWN_PROJECT_URLS)
1496
+ ]
1497
+ )
1498
+
1499
+ self.add_dependencies_and_close(deps_to_add, config_dict.get('hooks', []))
1500
+ logging.info('SetConfig() done')
1501
+
1502
+ def SaveConfig(self):
1503
+ gclient_utils.FileWrite(os.path.join(self.root_dir,
1504
+ self._options.config_filename),
1505
+ self.config_content)
1506
+
1507
+ @staticmethod
1508
+ def LoadCurrentConfig(options):
1509
+ """Searches for and loads a .gclient file relative to the current working
1510
+ dir. Returns a GClient object."""
1511
+ if options.spec:
1512
+ client = GClient('.', options)
1513
+ client.SetConfig(options.spec)
1514
+ else:
1515
+ if options.verbose:
1516
+ print('Looking for %s starting from %s\n' % (
1517
+ options.config_filename, os.getcwd()))
1518
+ path = gclient_paths.FindGclientRoot(os.getcwd(), options.config_filename)
1519
+ if not path:
1520
+ if options.verbose:
1521
+ print('Couldn\'t find configuration file.')
1522
+ return None
1523
+ client = GClient(path, options)
1524
+ client.SetConfig(gclient_utils.FileRead(
1525
+ os.path.join(path, options.config_filename)))
1526
+
1527
+ if (options.revisions and
1528
+ len(client.dependencies) > 1 and
1529
+ any('@' not in r for r in options.revisions)):
1530
+ print(
1531
+ ('You must specify the full solution name like --revision %s@%s\n'
1532
+ 'when you have multiple solutions setup in your .gclient file.\n'
1533
+ 'Other solutions present are: %s.') % (
1534
+ client.dependencies[0].name,
1535
+ options.revisions[0],
1536
+ ', '.join(s.name for s in client.dependencies[1:])),
1537
+ file=sys.stderr)
1538
+ return client
1539
+
1540
+ def SetDefaultConfig(self, solution_name, deps_file, solution_url,
1541
+ managed=True, cache_dir=UNSET_CACHE_DIR,
1542
+ custom_vars=None):
1543
+ text = self.DEFAULT_CLIENT_FILE_TEXT
1544
+ format_dict = {
1545
+ 'solution_name': solution_name,
1546
+ 'solution_url': solution_url,
1547
+ 'deps_file': deps_file,
1548
+ 'managed': managed,
1549
+ 'custom_vars': custom_vars or {},
1550
+ }
1551
+
1552
+ if cache_dir is not UNSET_CACHE_DIR:
1553
+ text += self.DEFAULT_CLIENT_CACHE_DIR_TEXT
1554
+ format_dict['cache_dir'] = cache_dir
1555
+
1556
+ self.SetConfig(text % format_dict)
1557
+
1558
+ def _SaveEntries(self):
1559
+ """Creates a .gclient_entries file to record the list of unique checkouts.
1560
+
1561
+ The .gclient_entries file lives in the same directory as .gclient.
1562
+ """
1563
+ # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It
1564
+ # makes testing a bit too fun.
1565
+ result = 'entries = {\n'
1566
+ for entry in self.root.subtree(False):
1567
+ result += ' %s: %s,\n' % (pprint.pformat(entry.name),
1568
+ pprint.pformat(entry.url))
1569
+ result += '}\n'
1570
+ file_path = os.path.join(self.root_dir, self._options.entries_filename)
1571
+ logging.debug(result)
1572
+ gclient_utils.FileWrite(file_path, result)
1573
+
1574
+ def _ReadEntries(self):
1575
+ """Read the .gclient_entries file for the given client.
1576
+
1577
+ Returns:
1578
+ A sequence of solution names, which will be empty if there is the
1579
+ entries file hasn't been created yet.
1580
+ """
1581
+ scope = {}
1582
+ filename = os.path.join(self.root_dir, self._options.entries_filename)
1583
+ if not os.path.exists(filename):
1584
+ return {}
1585
+ try:
1586
+ exec(gclient_utils.FileRead(filename), scope)
1587
+ except SyntaxError as e:
1588
+ gclient_utils.SyntaxErrorToError(filename, e)
1589
+ return scope.get('entries', {})
1590
+
1591
+ def _EnforceRevisions(self):
1592
+ """Checks for revision overrides."""
1593
+ revision_overrides = {}
1594
+ if self._options.head:
1595
+ return revision_overrides
1596
+ if not self._options.revisions:
1597
+ return revision_overrides
1598
+ solutions_names = [s.name for s in self.dependencies]
1599
+ index = 0
1600
+ for revision in self._options.revisions:
1601
+ if not '@' in revision:
1602
+ # Support for --revision 123
1603
+ revision = '%s@%s' % (solutions_names[index], revision)
1604
+ name, rev = revision.split('@', 1)
1605
+ revision_overrides[name] = rev
1606
+ index += 1
1607
+ return revision_overrides
1608
+
1609
+ def _EnforcePatchRefsAndBranches(self):
1610
+ """Checks for patch refs."""
1611
+ patch_refs = {}
1612
+ target_branches = {}
1613
+ if not self._options.patch_refs:
1614
+ return patch_refs, target_branches
1615
+ for given_patch_ref in self._options.patch_refs:
1616
+ patch_repo, _, patch_ref = given_patch_ref.partition('@')
1617
+ if not patch_repo or not patch_ref or ':' not in patch_ref:
1618
+ raise gclient_utils.Error(
1619
+ 'Wrong revision format: %s should be of the form '
1620
+ 'patch_repo@target_branch:patch_ref.' % given_patch_ref)
1621
+ target_branch, _, patch_ref = patch_ref.partition(':')
1622
+ target_branches[patch_repo] = target_branch
1623
+ patch_refs[patch_repo] = patch_ref
1624
+ return patch_refs, target_branches
1625
+
1626
+ def _RemoveUnversionedGitDirs(self):
1627
+ """Remove directories that are no longer part of the checkout.
1628
+
1629
+ Notify the user if there is an orphaned entry in their working copy.
1630
+ Only delete the directory if there are no changes in it, and
1631
+ delete_unversioned_trees is set to true.
1632
+ """
1633
+
1634
+ entries = [i.name for i in self.root.subtree(False) if i.url]
1635
+ full_entries = [os.path.join(self.root_dir, e.replace('/', os.path.sep))
1636
+ for e in entries]
1637
+
1638
+ for entry, prev_url in self._ReadEntries().items():
1639
+ if not prev_url:
1640
+ # entry must have been overridden via .gclient custom_deps
1641
+ continue
1642
+ # Fix path separator on Windows.
1643
+ entry_fixed = entry.replace('/', os.path.sep)
1644
+ e_dir = os.path.join(self.root_dir, entry_fixed)
1645
+ # Use entry and not entry_fixed there.
1646
+ if (entry not in entries and
1647
+ (not any(path.startswith(entry + '/') for path in entries)) and
1648
+ os.path.exists(e_dir)):
1649
+ # The entry has been removed from DEPS.
1650
+ scm = gclient_scm.GitWrapper(
1651
+ prev_url, self.root_dir, entry_fixed, self.outbuf)
1652
+
1653
+ # Check to see if this directory is now part of a higher-up checkout.
1654
+ scm_root = None
1655
+ try:
1656
+ scm_root = gclient_scm.scm.GIT.GetCheckoutRoot(scm.checkout_path)
1657
+ except subprocess2.CalledProcessError:
1658
+ pass
1659
+ if not scm_root:
1660
+ logging.warning('Could not find checkout root for %s. Unable to '
1661
+ 'determine whether it is part of a higher-level '
1662
+ 'checkout, so not removing.' % entry)
1663
+ continue
1664
+
1665
+ # This is to handle the case of third_party/WebKit migrating from
1666
+ # being a DEPS entry to being part of the main project.
1667
+ # If the subproject is a Git project, we need to remove its .git
1668
+ # folder. Otherwise git operations on that folder will have different
1669
+ # effects depending on the current working directory.
1670
+ if os.path.abspath(scm_root) == os.path.abspath(e_dir):
1671
+ e_par_dir = os.path.join(e_dir, os.pardir)
1672
+ if gclient_scm.scm.GIT.IsInsideWorkTree(e_par_dir):
1673
+ par_scm_root = gclient_scm.scm.GIT.GetCheckoutRoot(e_par_dir)
1674
+ # rel_e_dir : relative path of entry w.r.t. its parent repo.
1675
+ rel_e_dir = os.path.relpath(e_dir, par_scm_root)
1676
+ if gclient_scm.scm.GIT.IsDirectoryVersioned(
1677
+ par_scm_root, rel_e_dir):
1678
+ save_dir = scm.GetGitBackupDirPath()
1679
+ # Remove any eventual stale backup dir for the same project.
1680
+ if os.path.exists(save_dir):
1681
+ gclient_utils.rmtree(save_dir)
1682
+ os.rename(os.path.join(e_dir, '.git'), save_dir)
1683
+ # When switching between the two states (entry/ is a subproject
1684
+ # -> entry/ is part of the outer project), it is very likely
1685
+ # that some files are changed in the checkout, unless we are
1686
+ # jumping *exactly* across the commit which changed just DEPS.
1687
+ # In such case we want to cleanup any eventual stale files
1688
+ # (coming from the old subproject) in order to end up with a
1689
+ # clean checkout.
1690
+ gclient_scm.scm.GIT.CleanupDir(par_scm_root, rel_e_dir)
1691
+ assert not os.path.exists(os.path.join(e_dir, '.git'))
1692
+ print('\nWARNING: \'%s\' has been moved from DEPS to a higher '
1693
+ 'level checkout. The git folder containing all the local'
1694
+ ' branches has been saved to %s.\n'
1695
+ 'If you don\'t care about its state you can safely '
1696
+ 'remove that folder to free up space.' % (entry, save_dir))
1697
+ continue
1698
+
1699
+ if scm_root in full_entries:
1700
+ logging.info('%s is part of a higher level checkout, not removing',
1701
+ scm.GetCheckoutRoot())
1702
+ continue
1703
+
1704
+ file_list = []
1705
+ scm.status(self._options, [], file_list)
1706
+ modified_files = file_list != []
1707
+ if (not self._options.delete_unversioned_trees or
1708
+ (modified_files and not self._options.force)):
1709
+ # There are modified files in this entry. Keep warning until
1710
+ # removed.
1711
+ self.add_dependency(
1712
+ GitDependency(
1713
+ parent=self,
1714
+ name=entry,
1715
+ url=prev_url,
1716
+ managed=False,
1717
+ custom_deps={},
1718
+ custom_vars={},
1719
+ custom_hooks=[],
1720
+ deps_file=None,
1721
+ should_process=True,
1722
+ should_recurse=False,
1723
+ relative=None,
1724
+ condition=None))
1725
+ if modified_files and self._options.delete_unversioned_trees:
1726
+ print('\nWARNING: \'%s\' is no longer part of this client.\n'
1727
+ 'Despite running \'gclient sync -D\' no action was taken '
1728
+ 'as there are modifications.\nIt is recommended you revert '
1729
+ 'all changes or run \'gclient sync -D --force\' next '
1730
+ 'time.' % entry_fixed)
1731
+ else:
1732
+ print('\nWARNING: \'%s\' is no longer part of this client.\n'
1733
+ 'It is recommended that you manually remove it or use '
1734
+ '\'gclient sync -D\' next time.' % entry_fixed)
1735
+ else:
1736
+ # Delete the entry
1737
+ print('\n________ deleting \'%s\' in \'%s\'' % (
1738
+ entry_fixed, self.root_dir))
1739
+ gclient_utils.rmtree(e_dir)
1740
+ # record the current list of entries for next time
1741
+ self._SaveEntries()
1742
+
1743
+ def RunOnDeps(self, command, args, ignore_requirements=False, progress=True):
1744
+ """Runs a command on each dependency in a client and its dependencies.
1745
+
1746
+ Args:
1747
+ command: The command to use (e.g., 'status' or 'diff')
1748
+ args: list of str - extra arguments to add to the command line.
1749
+ """
1750
+ if not self.dependencies:
1751
+ raise gclient_utils.Error('No solution specified')
1752
+
1753
+ revision_overrides = {}
1754
+ patch_refs = {}
1755
+ target_branches = {}
1756
+ # It's unnecessary to check for revision overrides for 'recurse'.
1757
+ # Save a few seconds by not calling _EnforceRevisions() in that case.
1758
+ if command not in ('diff', 'recurse', 'runhooks', 'status', 'revert',
1759
+ 'validate'):
1760
+ self._CheckConfig()
1761
+ revision_overrides = self._EnforceRevisions()
1762
+
1763
+ if command == 'update':
1764
+ patch_refs, target_branches = self._EnforcePatchRefsAndBranches()
1765
+ # Disable progress for non-tty stdout.
1766
+ should_show_progress = (
1767
+ setup_color.IS_TTY and not self._options.verbose and progress)
1768
+ pm = None
1769
+ if should_show_progress:
1770
+ if command in ('update', 'revert'):
1771
+ pm = Progress('Syncing projects', 1)
1772
+ elif command in ('recurse', 'validate'):
1773
+ pm = Progress(' '.join(args), 1)
1774
+ work_queue = gclient_utils.ExecutionQueue(
1775
+ self._options.jobs, pm, ignore_requirements=ignore_requirements,
1776
+ verbose=self._options.verbose)
1777
+ for s in self.dependencies:
1778
+ if s.should_process:
1779
+ work_queue.enqueue(s)
1780
+ work_queue.flush(revision_overrides, command, args, options=self._options,
1781
+ patch_refs=patch_refs, target_branches=target_branches)
1782
+
1783
+ if revision_overrides:
1784
+ print('Please fix your script, having invalid --revision flags will soon '
1785
+ 'be considered an error.', file=sys.stderr)
1786
+
1787
+ if patch_refs:
1788
+ raise gclient_utils.Error(
1789
+ 'The following --patch-ref flags were not used. Please fix it:\n%s' %
1790
+ ('\n'.join(
1791
+ patch_repo + '@' + patch_ref
1792
+ for patch_repo, patch_ref in patch_refs.items())))
1793
+
1794
+ # Once all the dependencies have been processed, it's now safe to write
1795
+ # out the gn_args_file and run the hooks.
1796
+ if command == 'update':
1797
+ gn_args_dep = self.dependencies[0]
1798
+ if gn_args_dep._gn_args_from:
1799
+ deps_map = dict([(dep.name, dep) for dep in gn_args_dep.dependencies])
1800
+ gn_args_dep = deps_map.get(gn_args_dep._gn_args_from)
1801
+ if gn_args_dep and gn_args_dep.HasGNArgsFile():
1802
+ gn_args_dep.WriteGNArgsFile()
1803
+
1804
+ self._RemoveUnversionedGitDirs()
1805
+
1806
+ # Sync CIPD dependencies once removed deps are deleted. In case a git
1807
+ # dependency was moved to CIPD, we want to remove the old git directory
1808
+ # first and then sync the CIPD dep.
1809
+ if self._cipd_root:
1810
+ self._cipd_root.run(command)
1811
+
1812
+ if not self._options.nohooks:
1813
+ if should_show_progress:
1814
+ pm = Progress('Running hooks', 1)
1815
+ self.RunHooksRecursively(self._options, pm)
1816
+
1817
+
1818
+ return 0
1819
+
1820
+ def PrintRevInfo(self):
1821
+ if not self.dependencies:
1822
+ raise gclient_utils.Error('No solution specified')
1823
+ # Load all the settings.
1824
+ work_queue = gclient_utils.ExecutionQueue(
1825
+ self._options.jobs, None, False, verbose=self._options.verbose)
1826
+ for s in self.dependencies:
1827
+ if s.should_process:
1828
+ work_queue.enqueue(s)
1829
+ work_queue.flush({}, None, [], options=self._options, patch_refs=None,
1830
+ target_branches=None)
1831
+
1832
+ def ShouldPrintRevision(dep):
1833
+ return (not self._options.filter
1834
+ or dep.FuzzyMatchUrl(self._options.filter))
1835
+
1836
+ if self._options.snapshot:
1837
+ json_output = []
1838
+ # First level at .gclient
1839
+ for d in self.dependencies:
1840
+ entries = {}
1841
+ def GrabDeps(dep):
1842
+ """Recursively grab dependencies."""
1843
+ for d in dep.dependencies:
1844
+ d.PinToActualRevision()
1845
+ if ShouldPrintRevision(d):
1846
+ entries[d.name] = d.url
1847
+ GrabDeps(d)
1848
+ GrabDeps(d)
1849
+ json_output.append({
1850
+ 'name': d.name,
1851
+ 'solution_url': d.url,
1852
+ 'deps_file': d.deps_file,
1853
+ 'managed': d.managed,
1854
+ 'custom_deps': entries,
1855
+ })
1856
+ if self._options.output_json == '-':
1857
+ print(json.dumps(json_output, indent=2, separators=(',', ': ')))
1858
+ elif self._options.output_json:
1859
+ with open(self._options.output_json, 'w') as f:
1860
+ json.dump(json_output, f)
1861
+ else:
1862
+ # Print the snapshot configuration file
1863
+ print(self.DEFAULT_SNAPSHOT_FILE_TEXT % {
1864
+ 'solution_list': pprint.pformat(json_output, indent=2),
1865
+ })
1866
+ else:
1867
+ entries = {}
1868
+ for d in self.root.subtree(False):
1869
+ if self._options.actual:
1870
+ d.PinToActualRevision()
1871
+ if ShouldPrintRevision(d):
1872
+ entries[d.name] = d.url
1873
+ if self._options.output_json:
1874
+ json_output = {
1875
+ name: {
1876
+ 'url': rev.split('@')[0] if rev else None,
1877
+ 'rev': rev.split('@')[1] if rev and '@' in rev else None,
1878
+ }
1879
+ for name, rev in entries.items()
1880
+ }
1881
+ if self._options.output_json == '-':
1882
+ print(json.dumps(json_output, indent=2, separators=(',', ': ')))
1883
+ else:
1884
+ with open(self._options.output_json, 'w') as f:
1885
+ json.dump(json_output, f)
1886
+ else:
1887
+ keys = sorted(entries.keys())
1888
+ for x in keys:
1889
+ print('%s: %s' % (x, entries[x]))
1890
+ logging.info(str(self))
1891
+
1892
+ def ParseDepsFile(self):
1893
+ """No DEPS to parse for a .gclient file."""
1894
+ raise gclient_utils.Error('Internal error')
1895
+
1896
+ def PrintLocationAndContents(self):
1897
+ # Print out the .gclient file. This is longer than if we just printed the
1898
+ # client dict, but more legible, and it might contain helpful comments.
1899
+ print('Loaded .gclient config in %s:\n%s' % (
1900
+ self.root_dir, self.config_content))
1901
+
1902
+ def GetCipdRoot(self):
1903
+ if not self._cipd_root:
1904
+ self._cipd_root = gclient_scm.CipdRoot(
1905
+ self.root_dir,
1906
+ # TODO(jbudorick): Support other service URLs as necessary.
1907
+ # Service URLs should be constant over the scope of a cipd
1908
+ # root, so a var per DEPS file specifying the service URL
1909
+ # should suffice.
1910
+ 'https://chrome-infra-packages.appspot.com')
1911
+ return self._cipd_root
1912
+
1913
+ @property
1914
+ def root_dir(self):
1915
+ """Root directory of gclient checkout."""
1916
+ return self._root_dir
1917
+
1918
+ @property
1919
+ def enforced_os(self):
1920
+ """What deps_os entries that are to be parsed."""
1921
+ return self._enforced_os
1922
+
1923
+ @property
1924
+ def target_os(self):
1925
+ return self._enforced_os
1926
+
1927
+ @property
1928
+ def target_cpu(self):
1929
+ return self._enforced_cpu
1930
+
1931
+
1932
+ class CipdDependency(Dependency):
1933
+ """A Dependency object that represents a single CIPD package."""
1934
+
1935
+ def __init__(
1936
+ self, parent, name, dep_value, cipd_root,
1937
+ custom_vars, should_process, relative, condition):
1938
+ package = dep_value['package']
1939
+ version = dep_value['version']
1940
+ url = urlparse.urljoin(
1941
+ cipd_root.service_url, '%s@%s' % (package, version))
1942
+ super(CipdDependency, self).__init__(
1943
+ parent=parent,
1944
+ name=name + ':' + package,
1945
+ url=url,
1946
+ managed=None,
1947
+ custom_deps=None,
1948
+ custom_vars=custom_vars,
1949
+ custom_hooks=None,
1950
+ deps_file=None,
1951
+ should_process=should_process,
1952
+ should_recurse=False,
1953
+ relative=relative,
1954
+ condition=condition)
1955
+ self._cipd_package = None
1956
+ self._cipd_root = cipd_root
1957
+ # CIPD wants /-separated paths, even on Windows.
1958
+ native_subdir_path = os.path.relpath(
1959
+ os.path.join(self.root.root_dir, name), cipd_root.root_dir)
1960
+ self._cipd_subdir = posixpath.join(*native_subdir_path.split(os.sep))
1961
+ self._package_name = package
1962
+ self._package_version = version
1963
+
1964
+ #override
1965
+ def run(self, revision_overrides, command, args, work_queue, options,
1966
+ patch_refs, target_branches):
1967
+ """Runs |command| then parse the DEPS file."""
1968
+ logging.info('CipdDependency(%s).run()' % self.name)
1969
+ if not self.should_process:
1970
+ return
1971
+ self._CreatePackageIfNecessary()
1972
+ super(CipdDependency, self).run(revision_overrides, command, args,
1973
+ work_queue, options, patch_refs,
1974
+ target_branches)
1975
+
1976
+ def _CreatePackageIfNecessary(self):
1977
+ # We lazily create the CIPD package to make sure that only packages
1978
+ # that we want (as opposed to all packages defined in all DEPS files
1979
+ # we parse) get added to the root and subsequently ensured.
1980
+ if not self._cipd_package:
1981
+ self._cipd_package = self._cipd_root.add_package(
1982
+ self._cipd_subdir, self._package_name, self._package_version)
1983
+
1984
+ def ParseDepsFile(self):
1985
+ """CIPD dependencies are not currently allowed to have nested deps."""
1986
+ self.add_dependencies_and_close([], [])
1987
+
1988
+ #override
1989
+ def verify_validity(self):
1990
+ """CIPD dependencies allow duplicate name for packages in same directory."""
1991
+ logging.info('Dependency(%s).verify_validity()' % self.name)
1992
+ return True
1993
+
1994
+ #override
1995
+ def GetScmName(self):
1996
+ """Always 'cipd'."""
1997
+ return 'cipd'
1998
+
1999
+ #override
2000
+ def CreateSCM(self, out_cb=None):
2001
+ """Create a Wrapper instance suitable for handling this CIPD dependency."""
2002
+ self._CreatePackageIfNecessary()
2003
+ return gclient_scm.CipdWrapper(
2004
+ self.url, self.root.root_dir, self.name, self.outbuf, out_cb,
2005
+ root=self._cipd_root, package=self._cipd_package)
2006
+
2007
+ def hierarchy(self, include_url=False):
2008
+ return self.parent.hierarchy(include_url) + ' -> ' + self._cipd_subdir
2009
+
2010
+ def ToLines(self):
2011
+ """Return a list of lines representing this in a DEPS file."""
2012
+ def escape_cipd_var(package):
2013
+ return package.replace('{', '{{').replace('}', '}}')
2014
+
2015
+ s = []
2016
+ self._CreatePackageIfNecessary()
2017
+ if self._cipd_package.authority_for_subdir:
2018
+ condition_part = ([' "condition": %r,' % self.condition]
2019
+ if self.condition else [])
2020
+ s.extend([
2021
+ ' # %s' % self.hierarchy(include_url=False),
2022
+ ' "%s": {' % (self.name.split(':')[0],),
2023
+ ' "packages": [',
2024
+ ])
2025
+ for p in sorted(
2026
+ self._cipd_root.packages(self._cipd_subdir),
2027
+ key=lambda x: x.name):
2028
+ s.extend([
2029
+ ' {',
2030
+ ' "package": "%s",' % escape_cipd_var(p.name),
2031
+ ' "version": "%s",' % p.version,
2032
+ ' },',
2033
+ ])
2034
+
2035
+ s.extend([
2036
+ ' ],',
2037
+ ' "dep_type": "cipd",',
2038
+ ] + condition_part + [
2039
+ ' },',
2040
+ '',
2041
+ ])
2042
+ return s
2043
+
2044
+
2045
+ #### gclient commands.
2046
+
2047
+
2048
+ @subcommand.usage('[command] [args ...]')
2049
+ @metrics.collector.collect_metrics('gclient recurse')
2050
+ def CMDrecurse(parser, args):
2051
+ """Operates [command args ...] on all the dependencies.
2052
+
2053
+ Runs a shell command on all entries.
2054
+ Sets GCLIENT_DEP_PATH environment variable as the dep's relative location to
2055
+ root directory of the checkout.
2056
+ """
2057
+ # Stop parsing at the first non-arg so that these go through to the command
2058
+ parser.disable_interspersed_args()
2059
+ parser.add_option('-s', '--scm', action='append', default=[],
2060
+ help='Choose scm types to operate upon.')
2061
+ parser.add_option('-i', '--ignore', action='store_true',
2062
+ help='Ignore non-zero return codes from subcommands.')
2063
+ parser.add_option('--prepend-dir', action='store_true',
2064
+ help='Prepend relative dir for use with git <cmd> --null.')
2065
+ parser.add_option('--no-progress', action='store_true',
2066
+ help='Disable progress bar that shows sub-command updates')
2067
+ options, args = parser.parse_args(args)
2068
+ if not args:
2069
+ print('Need to supply a command!', file=sys.stderr)
2070
+ return 1
2071
+ root_and_entries = gclient_utils.GetGClientRootAndEntries()
2072
+ if not root_and_entries:
2073
+ print(
2074
+ 'You need to run gclient sync at least once to use \'recurse\'.\n'
2075
+ 'This is because .gclient_entries needs to exist and be up to date.',
2076
+ file=sys.stderr)
2077
+ return 1
2078
+
2079
+ # Normalize options.scm to a set()
2080
+ scm_set = set()
2081
+ for scm in options.scm:
2082
+ scm_set.update(scm.split(','))
2083
+ options.scm = scm_set
2084
+
2085
+ options.nohooks = True
2086
+ client = GClient.LoadCurrentConfig(options)
2087
+ if not client:
2088
+ raise gclient_utils.Error('client not configured; see \'gclient config\'')
2089
+ return client.RunOnDeps('recurse', args, ignore_requirements=True,
2090
+ progress=not options.no_progress)
2091
+
2092
+
2093
+ @subcommand.usage('[args ...]')
2094
+ @metrics.collector.collect_metrics('gclient fetch')
2095
+ def CMDfetch(parser, args):
2096
+ """Fetches upstream commits for all modules.
2097
+
2098
+ Completely git-specific. Simply runs 'git fetch [args ...]' for each module.
2099
+ """
2100
+ (options, args) = parser.parse_args(args)
2101
+ return CMDrecurse(OptionParser(), [
2102
+ '--jobs=%d' % options.jobs, '--scm=git', 'git', 'fetch'] + args)
2103
+
2104
+
2105
+ class Flattener(object):
2106
+ """Flattens a gclient solution."""
2107
+
2108
+ def __init__(self, client, pin_all_deps=False):
2109
+ """Constructor.
2110
+
2111
+ Arguments:
2112
+ client (GClient): client to flatten
2113
+ pin_all_deps (bool): whether to pin all deps, even if they're not pinned
2114
+ in DEPS
2115
+ """
2116
+ self._client = client
2117
+
2118
+ self._deps_string = None
2119
+ self._deps_files = set()
2120
+
2121
+ self._allowed_hosts = set()
2122
+ self._deps = {}
2123
+ self._hooks = []
2124
+ self._pre_deps_hooks = []
2125
+ self._vars = {}
2126
+
2127
+ self._flatten(pin_all_deps=pin_all_deps)
2128
+
2129
+ @property
2130
+ def deps_string(self):
2131
+ assert self._deps_string is not None
2132
+ return self._deps_string
2133
+
2134
+ @property
2135
+ def deps_files(self):
2136
+ return self._deps_files
2137
+
2138
+ def _pin_dep(self, dep):
2139
+ """Pins a dependency to specific full revision sha.
2140
+
2141
+ Arguments:
2142
+ dep (Dependency): dependency to process
2143
+ """
2144
+ if dep.url is None:
2145
+ return
2146
+
2147
+ # Make sure the revision is always fully specified (a hash),
2148
+ # as opposed to refs or tags which might change. Similarly,
2149
+ # shortened shas might become ambiguous; make sure to always
2150
+ # use full one for pinning.
2151
+ revision = gclient_utils.SplitUrlRevision(dep.url)[1]
2152
+ if not revision or not gclient_utils.IsFullGitSha(revision):
2153
+ dep.PinToActualRevision()
2154
+
2155
+ def _flatten(self, pin_all_deps=False):
2156
+ """Runs the flattener. Saves resulting DEPS string.
2157
+
2158
+ Arguments:
2159
+ pin_all_deps (bool): whether to pin all deps, even if they're not pinned
2160
+ in DEPS
2161
+ """
2162
+ for solution in self._client.dependencies:
2163
+ self._add_dep(solution)
2164
+ self._flatten_dep(solution)
2165
+
2166
+ if pin_all_deps:
2167
+ for dep in self._deps.values():
2168
+ self._pin_dep(dep)
2169
+
2170
+ def add_deps_file(dep):
2171
+ # Only include DEPS files referenced by recursedeps.
2172
+ if not dep.should_recurse:
2173
+ return
2174
+ deps_file = dep.deps_file
2175
+ deps_path = os.path.join(self._client.root_dir, dep.name, deps_file)
2176
+ if not os.path.exists(deps_path):
2177
+ # gclient has a fallback that if deps_file doesn't exist, it'll try
2178
+ # DEPS. Do the same here.
2179
+ deps_file = 'DEPS'
2180
+ deps_path = os.path.join(self._client.root_dir, dep.name, deps_file)
2181
+ if not os.path.exists(deps_path):
2182
+ return
2183
+ assert dep.url
2184
+ self._deps_files.add((dep.url, deps_file, dep.hierarchy_data()))
2185
+ for dep in self._deps.values():
2186
+ add_deps_file(dep)
2187
+
2188
+ gn_args_dep = self._deps.get(self._client.dependencies[0]._gn_args_from,
2189
+ self._client.dependencies[0])
2190
+ self._deps_string = '\n'.join(
2191
+ _GNSettingsToLines(gn_args_dep._gn_args_file, gn_args_dep._gn_args) +
2192
+ _AllowedHostsToLines(self._allowed_hosts) +
2193
+ _DepsToLines(self._deps) +
2194
+ _HooksToLines('hooks', self._hooks) +
2195
+ _HooksToLines('pre_deps_hooks', self._pre_deps_hooks) +
2196
+ _VarsToLines(self._vars) +
2197
+ ['# %s, %s' % (url, deps_file)
2198
+ for url, deps_file, _ in sorted(self._deps_files)] +
2199
+ ['']) # Ensure newline at end of file.
2200
+
2201
+ def _add_dep(self, dep):
2202
+ """Helper to add a dependency to flattened DEPS.
2203
+
2204
+ Arguments:
2205
+ dep (Dependency): dependency to add
2206
+ """
2207
+ assert dep.name not in self._deps or self._deps.get(dep.name) == dep, (
2208
+ dep.name, self._deps.get(dep.name))
2209
+ if dep.url:
2210
+ self._deps[dep.name] = dep
2211
+
2212
+ def _flatten_dep(self, dep):
2213
+ """Visits a dependency in order to flatten it (see CMDflatten).
2214
+
2215
+ Arguments:
2216
+ dep (Dependency): dependency to process
2217
+ """
2218
+ logging.debug('_flatten_dep(%s)', dep.name)
2219
+
2220
+ assert dep.deps_parsed, (
2221
+ "Attempted to flatten %s but it has not been processed." % dep.name)
2222
+
2223
+ self._allowed_hosts.update(dep.allowed_hosts)
2224
+
2225
+ # Only include vars explicitly listed in the DEPS files or gclient solution,
2226
+ # not automatic, local overrides (i.e. not all of dep.get_vars()).
2227
+ hierarchy = dep.hierarchy(include_url=False)
2228
+ for key, value in dep._vars.items():
2229
+ # Make sure there are no conflicting variables. It is fine however
2230
+ # to use same variable name, as long as the value is consistent.
2231
+ assert key not in self._vars or self._vars[key][1] == value, (
2232
+ "dep:%s key:%s value:%s != %s" % (
2233
+ dep.name, key, value, self._vars[key][1]))
2234
+ self._vars[key] = (hierarchy, value)
2235
+ # Override explicit custom variables.
2236
+ for key, value in dep.custom_vars.items():
2237
+ # Do custom_vars that don't correspond to DEPS vars ever make sense? DEPS
2238
+ # conditionals shouldn't be using vars that aren't also defined in the
2239
+ # DEPS (presubmit actually disallows this), so any new custom_var must be
2240
+ # unused in the DEPS, so no need to add it to the flattened output either.
2241
+ if key not in self._vars:
2242
+ continue
2243
+ # Don't "override" existing vars if it's actually the same value.
2244
+ elif self._vars[key][1] == value:
2245
+ continue
2246
+ # Anything else is overriding a default value from the DEPS.
2247
+ self._vars[key] = (hierarchy + ' [custom_var override]', value)
2248
+
2249
+ self._pre_deps_hooks.extend([(dep, hook) for hook in dep.pre_deps_hooks])
2250
+ self._hooks.extend([(dep, hook) for hook in dep.deps_hooks])
2251
+
2252
+ for sub_dep in dep.dependencies:
2253
+ self._add_dep(sub_dep)
2254
+
2255
+ for d in dep.dependencies:
2256
+ if d.should_recurse:
2257
+ self._flatten_dep(d)
2258
+
2259
+
2260
+ @metrics.collector.collect_metrics('gclient flatten')
2261
+ def CMDflatten(parser, args):
2262
+ """Flattens the solutions into a single DEPS file."""
2263
+ parser.add_option('--output-deps', help='Path to the output DEPS file')
2264
+ parser.add_option(
2265
+ '--output-deps-files',
2266
+ help=('Path to the output metadata about DEPS files referenced by '
2267
+ 'recursedeps.'))
2268
+ parser.add_option(
2269
+ '--pin-all-deps', action='store_true',
2270
+ help=('Pin all deps, even if not pinned in DEPS. CAVEAT: only does so '
2271
+ 'for checked out deps, NOT deps_os.'))
2272
+ options, args = parser.parse_args(args)
2273
+
2274
+ options.nohooks = True
2275
+ options.process_all_deps = True
2276
+ client = GClient.LoadCurrentConfig(options)
2277
+
2278
+ # Only print progress if we're writing to a file. Otherwise, progress updates
2279
+ # could obscure intended output.
2280
+ code = client.RunOnDeps('flatten', args, progress=options.output_deps)
2281
+ if code != 0:
2282
+ return code
2283
+
2284
+ flattener = Flattener(client, pin_all_deps=options.pin_all_deps)
2285
+
2286
+ if options.output_deps:
2287
+ with open(options.output_deps, 'w') as f:
2288
+ f.write(flattener.deps_string)
2289
+ else:
2290
+ print(flattener.deps_string)
2291
+
2292
+ deps_files = [{'url': d[0], 'deps_file': d[1], 'hierarchy': d[2]}
2293
+ for d in sorted(flattener.deps_files)]
2294
+ if options.output_deps_files:
2295
+ with open(options.output_deps_files, 'w') as f:
2296
+ json.dump(deps_files, f)
2297
+
2298
+ return 0
2299
+
2300
+
2301
+ def _GNSettingsToLines(gn_args_file, gn_args):
2302
+ s = []
2303
+ if gn_args_file:
2304
+ s.extend([
2305
+ 'gclient_gn_args_file = "%s"' % gn_args_file,
2306
+ 'gclient_gn_args = %r' % gn_args,
2307
+ ])
2308
+ return s
2309
+
2310
+
2311
+ def _AllowedHostsToLines(allowed_hosts):
2312
+ """Converts |allowed_hosts| set to list of lines for output."""
2313
+ if not allowed_hosts:
2314
+ return []
2315
+ s = ['allowed_hosts = [']
2316
+ for h in sorted(allowed_hosts):
2317
+ s.append(' "%s",' % h)
2318
+ s.extend([']', ''])
2319
+ return s
2320
+
2321
+
2322
+ def _DepsToLines(deps):
2323
+ """Converts |deps| dict to list of lines for output."""
2324
+ if not deps:
2325
+ return []
2326
+ s = ['deps = {']
2327
+ for _, dep in sorted(deps.items()):
2328
+ s.extend(dep.ToLines())
2329
+ s.extend(['}', ''])
2330
+ return s
2331
+
2332
+
2333
+ def _DepsOsToLines(deps_os):
2334
+ """Converts |deps_os| dict to list of lines for output."""
2335
+ if not deps_os:
2336
+ return []
2337
+ s = ['deps_os = {']
2338
+ for dep_os, os_deps in sorted(deps_os.items()):
2339
+ s.append(' "%s": {' % dep_os)
2340
+ for name, dep in sorted(os_deps.items()):
2341
+ condition_part = ([' "condition": %r,' % dep.condition]
2342
+ if dep.condition else [])
2343
+ s.extend([
2344
+ ' # %s' % dep.hierarchy(include_url=False),
2345
+ ' "%s": {' % (name,),
2346
+ ' "url": "%s",' % (dep.url,),
2347
+ ] + condition_part + [
2348
+ ' },',
2349
+ '',
2350
+ ])
2351
+ s.extend([' },', ''])
2352
+ s.extend(['}', ''])
2353
+ return s
2354
+
2355
+
2356
+ def _HooksToLines(name, hooks):
2357
+ """Converts |hooks| list to list of lines for output."""
2358
+ if not hooks:
2359
+ return []
2360
+ s = ['%s = [' % name]
2361
+ for dep, hook in hooks:
2362
+ s.extend([
2363
+ ' # %s' % dep.hierarchy(include_url=False),
2364
+ ' {',
2365
+ ])
2366
+ if hook.name is not None:
2367
+ s.append(' "name": "%s",' % hook.name)
2368
+ if hook.pattern is not None:
2369
+ s.append(' "pattern": "%s",' % hook.pattern)
2370
+ if hook.condition is not None:
2371
+ s.append(' "condition": %r,' % hook.condition)
2372
+ # Flattened hooks need to be written relative to the root gclient dir
2373
+ cwd = os.path.relpath(os.path.normpath(hook.effective_cwd))
2374
+ s.extend(
2375
+ [' "cwd": "%s",' % cwd] +
2376
+ [' "action": ['] +
2377
+ [' "%s",' % arg for arg in hook.action] +
2378
+ [' ]', ' },', '']
2379
+ )
2380
+ s.extend([']', ''])
2381
+ return s
2382
+
2383
+
2384
+ def _HooksOsToLines(hooks_os):
2385
+ """Converts |hooks| list to list of lines for output."""
2386
+ if not hooks_os:
2387
+ return []
2388
+ s = ['hooks_os = {']
2389
+ for hook_os, os_hooks in hooks_os.items():
2390
+ s.append(' "%s": [' % hook_os)
2391
+ for dep, hook in os_hooks:
2392
+ s.extend([
2393
+ ' # %s' % dep.hierarchy(include_url=False),
2394
+ ' {',
2395
+ ])
2396
+ if hook.name is not None:
2397
+ s.append(' "name": "%s",' % hook.name)
2398
+ if hook.pattern is not None:
2399
+ s.append(' "pattern": "%s",' % hook.pattern)
2400
+ if hook.condition is not None:
2401
+ s.append(' "condition": %r,' % hook.condition)
2402
+ # Flattened hooks need to be written relative to the root gclient dir
2403
+ cwd = os.path.relpath(os.path.normpath(hook.effective_cwd))
2404
+ s.extend(
2405
+ [' "cwd": "%s",' % cwd] +
2406
+ [' "action": ['] +
2407
+ [' "%s",' % arg for arg in hook.action] +
2408
+ [' ]', ' },', '']
2409
+ )
2410
+ s.extend([' ],', ''])
2411
+ s.extend(['}', ''])
2412
+ return s
2413
+
2414
+
2415
+ def _VarsToLines(variables):
2416
+ """Converts |variables| dict to list of lines for output."""
2417
+ if not variables:
2418
+ return []
2419
+ s = ['vars = {']
2420
+ for key, tup in sorted(variables.items()):
2421
+ hierarchy, value = tup
2422
+ s.extend([
2423
+ ' # %s' % hierarchy,
2424
+ ' "%s": %r,' % (key, value),
2425
+ '',
2426
+ ])
2427
+ s.extend(['}', ''])
2428
+ return s
2429
+
2430
+
2431
+ @metrics.collector.collect_metrics('gclient grep')
2432
+ def CMDgrep(parser, args):
2433
+ """Greps through git repos managed by gclient.
2434
+
2435
+ Runs 'git grep [args...]' for each module.
2436
+ """
2437
+ # We can't use optparse because it will try to parse arguments sent
2438
+ # to git grep and throw an error. :-(
2439
+ if not args or re.match('(-h|--help)$', args[0]):
2440
+ print(
2441
+ 'Usage: gclient grep [-j <N>] git-grep-args...\n\n'
2442
+ 'Example: "gclient grep -j10 -A2 RefCountedBase" runs\n"git grep '
2443
+ '-A2 RefCountedBase" on each of gclient\'s git\nrepos with up to '
2444
+ '10 jobs.\n\nBonus: page output by appending "|& less -FRSX" to the'
2445
+ ' end of your query.',
2446
+ file=sys.stderr)
2447
+ return 1
2448
+
2449
+ jobs_arg = ['--jobs=1']
2450
+ if re.match(r'(-j|--jobs=)\d+$', args[0]):
2451
+ jobs_arg, args = args[:1], args[1:]
2452
+ elif re.match(r'(-j|--jobs)$', args[0]):
2453
+ jobs_arg, args = args[:2], args[2:]
2454
+
2455
+ return CMDrecurse(
2456
+ parser,
2457
+ jobs_arg + ['--ignore', '--prepend-dir', '--no-progress', '--scm=git',
2458
+ 'git', 'grep', '--null', '--color=Always'] + args)
2459
+
2460
+
2461
+ @metrics.collector.collect_metrics('gclient root')
2462
+ def CMDroot(parser, args):
2463
+ """Outputs the solution root (or current dir if there isn't one)."""
2464
+ (options, args) = parser.parse_args(args)
2465
+ client = GClient.LoadCurrentConfig(options)
2466
+ if client:
2467
+ print(os.path.abspath(client.root_dir))
2468
+ else:
2469
+ print(os.path.abspath('.'))
2470
+
2471
+
2472
+ @subcommand.usage('[url]')
2473
+ @metrics.collector.collect_metrics('gclient config')
2474
+ def CMDconfig(parser, args):
2475
+ """Creates a .gclient file in the current directory.
2476
+
2477
+ This specifies the configuration for further commands. After update/sync,
2478
+ top-level DEPS files in each module are read to determine dependent
2479
+ modules to operate on as well. If optional [url] parameter is
2480
+ provided, then configuration is read from a specified Subversion server
2481
+ URL.
2482
+ """
2483
+ # We do a little dance with the --gclientfile option. 'gclient config' is the
2484
+ # only command where it's acceptable to have both '--gclientfile' and '--spec'
2485
+ # arguments. So, we temporarily stash any --gclientfile parameter into
2486
+ # options.output_config_file until after the (gclientfile xor spec) error
2487
+ # check.
2488
+ parser.remove_option('--gclientfile')
2489
+ parser.add_option('--gclientfile', dest='output_config_file',
2490
+ help='Specify an alternate .gclient file')
2491
+ parser.add_option('--name',
2492
+ help='overrides the default name for the solution')
2493
+ parser.add_option('--deps-file', default='DEPS',
2494
+ help='overrides the default name for the DEPS file for the '
2495
+ 'main solutions and all sub-dependencies')
2496
+ parser.add_option('--unmanaged', action='store_true', default=False,
2497
+ help='overrides the default behavior to make it possible '
2498
+ 'to have the main solution untouched by gclient '
2499
+ '(gclient will check out unmanaged dependencies but '
2500
+ 'will never sync them)')
2501
+ parser.add_option('--cache-dir', default=UNSET_CACHE_DIR,
2502
+ help='Cache all git repos into this dir and do shared '
2503
+ 'clones from the cache, instead of cloning directly '
2504
+ 'from the remote. Pass "None" to disable cache, even '
2505
+ 'if globally enabled due to $GIT_CACHE_PATH.')
2506
+ parser.add_option('--custom-var', action='append', dest='custom_vars',
2507
+ default=[],
2508
+ help='overrides variables; key=value syntax')
2509
+ parser.set_defaults(config_filename=None)
2510
+ (options, args) = parser.parse_args(args)
2511
+ if options.output_config_file:
2512
+ setattr(options, 'config_filename', getattr(options, 'output_config_file'))
2513
+ if ((options.spec and args) or len(args) > 2 or
2514
+ (not options.spec and not args)):
2515
+ parser.error('Inconsistent arguments. Use either --spec or one or 2 args')
2516
+
2517
+ if (options.cache_dir is not UNSET_CACHE_DIR
2518
+ and options.cache_dir.lower() == 'none'):
2519
+ options.cache_dir = None
2520
+
2521
+ custom_vars = {}
2522
+ for arg in options.custom_vars:
2523
+ kv = arg.split('=', 1)
2524
+ if len(kv) != 2:
2525
+ parser.error('Invalid --custom-var argument: %r' % arg)
2526
+ custom_vars[kv[0]] = gclient_eval.EvaluateCondition(kv[1], {})
2527
+
2528
+ client = GClient('.', options)
2529
+ if options.spec:
2530
+ client.SetConfig(options.spec)
2531
+ else:
2532
+ base_url = args[0].rstrip('/')
2533
+ if not options.name:
2534
+ name = base_url.split('/')[-1]
2535
+ if name.endswith('.git'):
2536
+ name = name[:-4]
2537
+ else:
2538
+ # specify an alternate relpath for the given URL.
2539
+ name = options.name
2540
+ if not os.path.abspath(os.path.join(os.getcwd(), name)).startswith(
2541
+ os.getcwd()):
2542
+ parser.error('Do not pass a relative path for --name.')
2543
+ if any(x in ('..', '.', '/', '\\') for x in name.split(os.sep)):
2544
+ parser.error('Do not include relative path components in --name.')
2545
+
2546
+ deps_file = options.deps_file
2547
+ client.SetDefaultConfig(name, deps_file, base_url,
2548
+ managed=not options.unmanaged,
2549
+ cache_dir=options.cache_dir,
2550
+ custom_vars=custom_vars)
2551
+ client.SaveConfig()
2552
+ return 0
2553
+
2554
+
2555
+ @subcommand.epilog("""Example:
2556
+ gclient pack > patch.txt
2557
+ generate simple patch for configured client and dependences
2558
+ """)
2559
+ @metrics.collector.collect_metrics('gclient pack')
2560
+ def CMDpack(parser, args):
2561
+ """Generates a patch which can be applied at the root of the tree.
2562
+
2563
+ Internally, runs 'git diff' on each checked out module and
2564
+ dependencies, and performs minimal postprocessing of the output. The
2565
+ resulting patch is printed to stdout and can be applied to a freshly
2566
+ checked out tree via 'patch -p0 < patchfile'.
2567
+ """
2568
+ parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
2569
+ help='override deps for the specified (comma-separated) '
2570
+ 'platform(s); \'all\' will process all deps_os '
2571
+ 'references')
2572
+ parser.remove_option('--jobs')
2573
+ (options, args) = parser.parse_args(args)
2574
+ # Force jobs to 1 so the stdout is not annotated with the thread ids
2575
+ options.jobs = 1
2576
+ client = GClient.LoadCurrentConfig(options)
2577
+ if not client:
2578
+ raise gclient_utils.Error('client not configured; see \'gclient config\'')
2579
+ if options.verbose:
2580
+ client.PrintLocationAndContents()
2581
+ return client.RunOnDeps('pack', args)
2582
+
2583
+
2584
+ @metrics.collector.collect_metrics('gclient status')
2585
+ def CMDstatus(parser, args):
2586
+ """Shows modification status for every dependencies."""
2587
+ parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
2588
+ help='override deps for the specified (comma-separated) '
2589
+ 'platform(s); \'all\' will process all deps_os '
2590
+ 'references')
2591
+ (options, args) = parser.parse_args(args)
2592
+ client = GClient.LoadCurrentConfig(options)
2593
+ if not client:
2594
+ raise gclient_utils.Error('client not configured; see \'gclient config\'')
2595
+ if options.verbose:
2596
+ client.PrintLocationAndContents()
2597
+ return client.RunOnDeps('status', args)
2598
+
2599
+
2600
+ @subcommand.epilog("""Examples:
2601
+ gclient sync
2602
+ update files from SCM according to current configuration,
2603
+ *for modules which have changed since last update or sync*
2604
+ gclient sync --force
2605
+ update files from SCM according to current configuration, for
2606
+ all modules (useful for recovering files deleted from local copy)
2607
+ gclient sync --revision src@31000
2608
+ update src directory to r31000
2609
+
2610
+ JSON output format:
2611
+ If the --output-json option is specified, the following document structure will
2612
+ be emitted to the provided file. 'null' entries may occur for subprojects which
2613
+ are present in the gclient solution, but were not processed (due to custom_deps,
2614
+ os_deps, etc.)
2615
+
2616
+ {
2617
+ "solutions" : {
2618
+ "<name>": { # <name> is the posix-normalized path to the solution.
2619
+ "revision": [<git id hex string>|null],
2620
+ "scm": ["git"|null],
2621
+ }
2622
+ }
2623
+ }
2624
+ """)
2625
+ @metrics.collector.collect_metrics('gclient sync')
2626
+ def CMDsync(parser, args):
2627
+ """Checkout/update all modules."""
2628
+ parser.add_option('-f', '--force', action='store_true',
2629
+ help='force update even for unchanged modules')
2630
+ parser.add_option('-n', '--nohooks', action='store_true',
2631
+ help='don\'t run hooks after the update is complete')
2632
+ parser.add_option('-p', '--noprehooks', action='store_true',
2633
+ help='don\'t run pre-DEPS hooks', default=False)
2634
+ parser.add_option('-r', '--revision', action='append',
2635
+ dest='revisions', metavar='REV', default=[],
2636
+ help='Enforces revision/hash for the solutions with the '
2637
+ 'format src@rev. The src@ part is optional and can be '
2638
+ 'skipped. You can also specify URLs instead of paths '
2639
+ 'and gclient will find the solution corresponding to '
2640
+ 'the given URL. If a path is also specified, the URL '
2641
+ 'takes precedence. -r can be used multiple times when '
2642
+ '.gclient has multiple solutions configured, and will '
2643
+ 'work even if the src@ part is skipped.')
2644
+ parser.add_option('--patch-ref', action='append',
2645
+ dest='patch_refs', metavar='GERRIT_REF', default=[],
2646
+ help='Patches the given reference with the format '
2647
+ 'dep@target-ref:patch-ref. '
2648
+ 'For |dep|, you can specify URLs as well as paths, '
2649
+ 'with URLs taking preference. '
2650
+ '|patch-ref| will be applied to |dep|, rebased on top '
2651
+ 'of what |dep| was synced to, and a soft reset will '
2652
+ 'be done. Use --no-rebase-patch-ref and '
2653
+ '--no-reset-patch-ref to disable this behavior. '
2654
+ '|target-ref| is the target branch against which a '
2655
+ 'patch was created, it is used to determine which '
2656
+ 'commits from the |patch-ref| actually constitute a '
2657
+ 'patch.')
2658
+ parser.add_option('--with_branch_heads', action='store_true',
2659
+ help='Clone git "branch_heads" refspecs in addition to '
2660
+ 'the default refspecs. This adds about 1/2GB to a '
2661
+ 'full checkout. (git only)')
2662
+ parser.add_option('--with_tags', action='store_true',
2663
+ help='Clone git tags in addition to the default refspecs.')
2664
+ parser.add_option('-H', '--head', action='store_true',
2665
+ help='DEPRECATED: only made sense with safesync urls.')
2666
+ parser.add_option('-D', '--delete_unversioned_trees', action='store_true',
2667
+ help='Deletes from the working copy any dependencies that '
2668
+ 'have been removed since the last sync, as long as '
2669
+ 'there are no local modifications. When used with '
2670
+ '--force, such dependencies are removed even if they '
2671
+ 'have local modifications. When used with --reset, '
2672
+ 'all untracked directories are removed from the '
2673
+ 'working copy, excluding those which are explicitly '
2674
+ 'ignored in the repository.')
2675
+ parser.add_option('-R', '--reset', action='store_true',
2676
+ help='resets any local changes before updating (git only)')
2677
+ parser.add_option('-M', '--merge', action='store_true',
2678
+ help='merge upstream changes instead of trying to '
2679
+ 'fast-forward or rebase')
2680
+ parser.add_option('-A', '--auto_rebase', action='store_true',
2681
+ help='Automatically rebase repositories against local '
2682
+ 'checkout during update (git only).')
2683
+ parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
2684
+ help='override deps for the specified (comma-separated) '
2685
+ 'platform(s); \'all\' will process all deps_os '
2686
+ 'references')
2687
+ parser.add_option('--process-all-deps', action='store_true',
2688
+ help='Check out all deps, even for different OS-es, '
2689
+ 'or with conditions evaluating to false')
2690
+ parser.add_option('--upstream', action='store_true',
2691
+ help='Make repo state match upstream branch.')
2692
+ parser.add_option('--output-json',
2693
+ help='Output a json document to this path containing '
2694
+ 'summary information about the sync.')
2695
+ parser.add_option('--no-history', action='store_true',
2696
+ help='GIT ONLY - Reduces the size/time of the checkout at '
2697
+ 'the cost of no history. Requires Git 1.9+')
2698
+ parser.add_option('--shallow', action='store_true',
2699
+ help='GIT ONLY - Do a shallow clone into the cache dir. '
2700
+ 'Requires Git 1.9+')
2701
+ parser.add_option('--no_bootstrap', '--no-bootstrap',
2702
+ action='store_true',
2703
+ help='Don\'t bootstrap from Google Storage.')
2704
+ parser.add_option('--ignore_locks',
2705
+ action='store_true',
2706
+ help='No longer used.')
2707
+ parser.add_option('--break_repo_locks',
2708
+ action='store_true',
2709
+ help='No longer used.')
2710
+ parser.add_option('--lock_timeout', type='int', default=5000,
2711
+ help='GIT ONLY - Deadline (in seconds) to wait for git '
2712
+ 'cache lock to become available. Default is %default.')
2713
+ parser.add_option('--no-rebase-patch-ref', action='store_false',
2714
+ dest='rebase_patch_ref', default=True,
2715
+ help='Bypass rebase of the patch ref after checkout.')
2716
+ parser.add_option('--no-reset-patch-ref', action='store_false',
2717
+ dest='reset_patch_ref', default=True,
2718
+ help='Bypass calling reset after patching the ref.')
2719
+ (options, args) = parser.parse_args(args)
2720
+ client = GClient.LoadCurrentConfig(options)
2721
+
2722
+ if not client:
2723
+ raise gclient_utils.Error('client not configured; see \'gclient config\'')
2724
+
2725
+ if options.ignore_locks:
2726
+ print('Warning: ignore_locks is no longer used. Please remove its usage.')
2727
+
2728
+ if options.break_repo_locks:
2729
+ print('Warning: break_repo_locks is no longer used. Please remove its '
2730
+ 'usage.')
2731
+
2732
+ if options.revisions and options.head:
2733
+ # TODO(maruel): Make it a parser.error if it doesn't break any builder.
2734
+ print('Warning: you cannot use both --head and --revision')
2735
+
2736
+ if options.verbose:
2737
+ client.PrintLocationAndContents()
2738
+ ret = client.RunOnDeps('update', args)
2739
+ if options.output_json:
2740
+ slns = {}
2741
+ for d in client.subtree(True):
2742
+ normed = d.name.replace('\\', '/').rstrip('/') + '/'
2743
+ slns[normed] = {
2744
+ 'revision': d.got_revision,
2745
+ 'scm': d.used_scm.name if d.used_scm else None,
2746
+ 'url': str(d.url) if d.url else None,
2747
+ 'was_processed': d.should_process,
2748
+ }
2749
+ with open(options.output_json, 'w') as f:
2750
+ json.dump({'solutions': slns}, f)
2751
+ return ret
2752
+
2753
+
2754
+ CMDupdate = CMDsync
2755
+
2756
+
2757
+ @metrics.collector.collect_metrics('gclient validate')
2758
+ def CMDvalidate(parser, args):
2759
+ """Validates the .gclient and DEPS syntax."""
2760
+ options, args = parser.parse_args(args)
2761
+ client = GClient.LoadCurrentConfig(options)
2762
+ rv = client.RunOnDeps('validate', args)
2763
+ if rv == 0:
2764
+ print('validate: SUCCESS')
2765
+ else:
2766
+ print('validate: FAILURE')
2767
+ return rv
2768
+
2769
+
2770
+ @metrics.collector.collect_metrics('gclient diff')
2771
+ def CMDdiff(parser, args):
2772
+ """Displays local diff for every dependencies."""
2773
+ parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
2774
+ help='override deps for the specified (comma-separated) '
2775
+ 'platform(s); \'all\' will process all deps_os '
2776
+ 'references')
2777
+ (options, args) = parser.parse_args(args)
2778
+ client = GClient.LoadCurrentConfig(options)
2779
+ if not client:
2780
+ raise gclient_utils.Error('client not configured; see \'gclient config\'')
2781
+ if options.verbose:
2782
+ client.PrintLocationAndContents()
2783
+ return client.RunOnDeps('diff', args)
2784
+
2785
+
2786
+ @metrics.collector.collect_metrics('gclient revert')
2787
+ def CMDrevert(parser, args):
2788
+ """Reverts all modifications in every dependencies.
2789
+
2790
+ That's the nuclear option to get back to a 'clean' state. It removes anything
2791
+ that shows up in git status."""
2792
+ parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
2793
+ help='override deps for the specified (comma-separated) '
2794
+ 'platform(s); \'all\' will process all deps_os '
2795
+ 'references')
2796
+ parser.add_option('-n', '--nohooks', action='store_true',
2797
+ help='don\'t run hooks after the revert is complete')
2798
+ parser.add_option('-p', '--noprehooks', action='store_true',
2799
+ help='don\'t run pre-DEPS hooks', default=False)
2800
+ parser.add_option('--upstream', action='store_true',
2801
+ help='Make repo state match upstream branch.')
2802
+ parser.add_option('--break_repo_locks',
2803
+ action='store_true',
2804
+ help='No longer used.')
2805
+ (options, args) = parser.parse_args(args)
2806
+ if options.break_repo_locks:
2807
+ print('Warning: break_repo_locks is no longer used. Please remove its ' +
2808
+ 'usage.')
2809
+
2810
+ # --force is implied.
2811
+ options.force = True
2812
+ options.reset = False
2813
+ options.delete_unversioned_trees = False
2814
+ options.merge = False
2815
+ client = GClient.LoadCurrentConfig(options)
2816
+ if not client:
2817
+ raise gclient_utils.Error('client not configured; see \'gclient config\'')
2818
+ return client.RunOnDeps('revert', args)
2819
+
2820
+
2821
+ @metrics.collector.collect_metrics('gclient runhooks')
2822
+ def CMDrunhooks(parser, args):
2823
+ """Runs hooks for files that have been modified in the local working copy."""
2824
+ parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
2825
+ help='override deps for the specified (comma-separated) '
2826
+ 'platform(s); \'all\' will process all deps_os '
2827
+ 'references')
2828
+ parser.add_option('-f', '--force', action='store_true', default=True,
2829
+ help='Deprecated. No effect.')
2830
+ (options, args) = parser.parse_args(args)
2831
+ client = GClient.LoadCurrentConfig(options)
2832
+ if not client:
2833
+ raise gclient_utils.Error('client not configured; see \'gclient config\'')
2834
+ if options.verbose:
2835
+ client.PrintLocationAndContents()
2836
+ options.force = True
2837
+ options.nohooks = False
2838
+ return client.RunOnDeps('runhooks', args)
2839
+
2840
+
2841
+ @metrics.collector.collect_metrics('gclient revinfo')
2842
+ def CMDrevinfo(parser, args):
2843
+ """Outputs revision info mapping for the client and its dependencies.
2844
+
2845
+ This allows the capture of an overall 'revision' for the source tree that
2846
+ can be used to reproduce the same tree in the future. It is only useful for
2847
+ 'unpinned dependencies', i.e. DEPS/deps references without a git hash.
2848
+ A git branch name isn't 'pinned' since the actual commit can change.
2849
+ """
2850
+ parser.add_option('--deps', dest='deps_os', metavar='OS_LIST',
2851
+ help='override deps for the specified (comma-separated) '
2852
+ 'platform(s); \'all\' will process all deps_os '
2853
+ 'references')
2854
+ parser.add_option('-a', '--actual', action='store_true',
2855
+ help='gets the actual checked out revisions instead of the '
2856
+ 'ones specified in the DEPS and .gclient files')
2857
+ parser.add_option('-s', '--snapshot', action='store_true',
2858
+ help='creates a snapshot .gclient file of the current '
2859
+ 'version of all repositories to reproduce the tree, '
2860
+ 'implies -a')
2861
+ parser.add_option('--filter', action='append', dest='filter',
2862
+ help='Display revision information only for the specified '
2863
+ 'dependencies (filtered by URL or path).')
2864
+ parser.add_option('--output-json',
2865
+ help='Output a json document to this path containing '
2866
+ 'information about the revisions.')
2867
+ parser.add_option('--ignore-dep-type', choices=['git', 'cipd'],
2868
+ help='Specify to skip processing of a certain type of dep.')
2869
+ (options, args) = parser.parse_args(args)
2870
+ client = GClient.LoadCurrentConfig(options)
2871
+ if not client:
2872
+ raise gclient_utils.Error('client not configured; see \'gclient config\'')
2873
+ client.PrintRevInfo()
2874
+ return 0
2875
+
2876
+
2877
+ @metrics.collector.collect_metrics('gclient getdep')
2878
+ def CMDgetdep(parser, args):
2879
+ """Gets revision information and variable values from a DEPS file."""
2880
+ parser.add_option('--var', action='append',
2881
+ dest='vars', metavar='VAR', default=[],
2882
+ help='Gets the value of a given variable.')
2883
+ parser.add_option('-r', '--revision', action='append',
2884
+ dest='getdep_revisions', metavar='DEP', default=[],
2885
+ help='Gets the revision/version for the given dependency. '
2886
+ 'If it is a git dependency, dep must be a path. If it '
2887
+ 'is a CIPD dependency, dep must be of the form '
2888
+ 'path:package.')
2889
+ parser.add_option('--deps-file', default='DEPS',
2890
+ # TODO(ehmaldonado): Try to find the DEPS file pointed by
2891
+ # .gclient first.
2892
+ help='The DEPS file to be edited. Defaults to the DEPS '
2893
+ 'file in the current directory.')
2894
+ (options, args) = parser.parse_args(args)
2895
+
2896
+ if not os.path.isfile(options.deps_file):
2897
+ raise gclient_utils.Error(
2898
+ 'DEPS file %s does not exist.' % options.deps_file)
2899
+ with open(options.deps_file) as f:
2900
+ contents = f.read()
2901
+ client = GClient.LoadCurrentConfig(options)
2902
+ if client is not None:
2903
+ builtin_vars = client.get_builtin_vars()
2904
+ else:
2905
+ logging.warning(
2906
+ 'Couldn\'t find a valid gclient config. Will attempt to parse the DEPS '
2907
+ 'file without support for built-in variables.')
2908
+ builtin_vars = None
2909
+ local_scope = gclient_eval.Exec(contents, options.deps_file,
2910
+ builtin_vars=builtin_vars)
2911
+
2912
+ for var in options.vars:
2913
+ print(gclient_eval.GetVar(local_scope, var))
2914
+
2915
+ for name in options.getdep_revisions:
2916
+ if ':' in name:
2917
+ name, _, package = name.partition(':')
2918
+ if not name or not package:
2919
+ parser.error(
2920
+ 'Wrong CIPD format: %s:%s should be of the form path:pkg.'
2921
+ % (name, package))
2922
+ print(gclient_eval.GetCIPD(local_scope, name, package))
2923
+ else:
2924
+ print(gclient_eval.GetRevision(local_scope, name))
2925
+
2926
+
2927
+ @metrics.collector.collect_metrics('gclient setdep')
2928
+ def CMDsetdep(parser, args):
2929
+ """Modifies dependency revisions and variable values in a DEPS file"""
2930
+ parser.add_option('--var', action='append',
2931
+ dest='vars', metavar='VAR=VAL', default=[],
2932
+ help='Sets a variable to the given value with the format '
2933
+ 'name=value.')
2934
+ parser.add_option('-r', '--revision', action='append',
2935
+ dest='setdep_revisions', metavar='DEP@REV', default=[],
2936
+ help='Sets the revision/version for the dependency with '
2937
+ 'the format dep@rev. If it is a git dependency, dep '
2938
+ 'must be a path and rev must be a git hash or '
2939
+ 'reference (e.g. src/dep@deadbeef). If it is a CIPD '
2940
+ 'dependency, dep must be of the form path:package and '
2941
+ 'rev must be the package version '
2942
+ '(e.g. src/pkg:chromium/pkg@2.1-cr0).')
2943
+ parser.add_option('--deps-file', default='DEPS',
2944
+ # TODO(ehmaldonado): Try to find the DEPS file pointed by
2945
+ # .gclient first.
2946
+ help='The DEPS file to be edited. Defaults to the DEPS '
2947
+ 'file in the current directory.')
2948
+ (options, args) = parser.parse_args(args)
2949
+ if args:
2950
+ parser.error('Unused arguments: "%s"' % '" "'.join(args))
2951
+ if not options.setdep_revisions and not options.vars:
2952
+ parser.error(
2953
+ 'You must specify at least one variable or revision to modify.')
2954
+
2955
+ if not os.path.isfile(options.deps_file):
2956
+ raise gclient_utils.Error(
2957
+ 'DEPS file %s does not exist.' % options.deps_file)
2958
+ with open(options.deps_file) as f:
2959
+ contents = f.read()
2960
+
2961
+ client = GClient.LoadCurrentConfig(options)
2962
+ if client is not None:
2963
+ builtin_vars = client.get_builtin_vars()
2964
+ else:
2965
+ logging.warning(
2966
+ 'Couldn\'t find a valid gclient config. Will attempt to parse the DEPS '
2967
+ 'file without support for built-in variables.')
2968
+ builtin_vars = None
2969
+
2970
+ local_scope = gclient_eval.Exec(contents, options.deps_file,
2971
+ builtin_vars=builtin_vars)
2972
+
2973
+ for var in options.vars:
2974
+ name, _, value = var.partition('=')
2975
+ if not name or not value:
2976
+ parser.error(
2977
+ 'Wrong var format: %s should be of the form name=value.' % var)
2978
+ if name in local_scope['vars']:
2979
+ gclient_eval.SetVar(local_scope, name, value)
2980
+ else:
2981
+ gclient_eval.AddVar(local_scope, name, value)
2982
+
2983
+ for revision in options.setdep_revisions:
2984
+ name, _, value = revision.partition('@')
2985
+ if not name or not value:
2986
+ parser.error(
2987
+ 'Wrong dep format: %s should be of the form dep@rev.' % revision)
2988
+ if ':' in name:
2989
+ name, _, package = name.partition(':')
2990
+ if not name or not package:
2991
+ parser.error(
2992
+ 'Wrong CIPD format: %s:%s should be of the form path:pkg@version.'
2993
+ % (name, package))
2994
+ gclient_eval.SetCIPD(local_scope, name, package, value)
2995
+ else:
2996
+ gclient_eval.SetRevision(local_scope, name, value)
2997
+
2998
+ with open(options.deps_file, 'wb') as f:
2999
+ f.write(gclient_eval.RenderDEPSFile(local_scope).encode('utf-8'))
3000
+
3001
+
3002
+ @metrics.collector.collect_metrics('gclient verify')
3003
+ def CMDverify(parser, args):
3004
+ """Verifies the DEPS file deps are only from allowed_hosts."""
3005
+ (options, args) = parser.parse_args(args)
3006
+ client = GClient.LoadCurrentConfig(options)
3007
+ if not client:
3008
+ raise gclient_utils.Error('client not configured; see \'gclient config\'')
3009
+ client.RunOnDeps(None, [])
3010
+ # Look at each first-level dependency of this gclient only.
3011
+ for dep in client.dependencies:
3012
+ bad_deps = dep.findDepsFromNotAllowedHosts()
3013
+ if not bad_deps:
3014
+ continue
3015
+ print("There are deps from not allowed hosts in file %s" % dep.deps_file)
3016
+ for bad_dep in bad_deps:
3017
+ print("\t%s at %s" % (bad_dep.name, bad_dep.url))
3018
+ print("allowed_hosts:", ', '.join(dep.allowed_hosts))
3019
+ sys.stdout.flush()
3020
+ raise gclient_utils.Error(
3021
+ 'dependencies from disallowed hosts; check your DEPS file.')
3022
+ return 0
3023
+
3024
+
3025
+ @subcommand.epilog("""For more information on what metrics are we collecting and
3026
+ why, please read metrics.README.md or visit https://bit.ly/2ufRS4p""")
3027
+ @metrics.collector.collect_metrics('gclient metrics')
3028
+ def CMDmetrics(parser, args):
3029
+ """Reports, and optionally modifies, the status of metric collection."""
3030
+ parser.add_option('--opt-in', action='store_true', dest='enable_metrics',
3031
+ help='Opt-in to metrics collection.',
3032
+ default=None)
3033
+ parser.add_option('--opt-out', action='store_false', dest='enable_metrics',
3034
+ help='Opt-out of metrics collection.')
3035
+ options, args = parser.parse_args(args)
3036
+ if args:
3037
+ parser.error('Unused arguments: "%s"' % '" "'.join(args))
3038
+ if not metrics.collector.config.is_googler:
3039
+ print("You're not a Googler. Metrics collection is disabled for you.")
3040
+ return 0
3041
+
3042
+ if options.enable_metrics is not None:
3043
+ metrics.collector.config.opted_in = options.enable_metrics
3044
+
3045
+ if metrics.collector.config.opted_in is None:
3046
+ print("You haven't opted in or out of metrics collection.")
3047
+ elif metrics.collector.config.opted_in:
3048
+ print("You have opted in. Thanks!")
3049
+ else:
3050
+ print("You have opted out. Please consider opting in.")
3051
+ return 0
3052
+
3053
+
3054
+ class OptionParser(optparse.OptionParser):
3055
+ gclientfile_default = os.environ.get('GCLIENT_FILE', '.gclient')
3056
+
3057
+ def __init__(self, **kwargs):
3058
+ optparse.OptionParser.__init__(
3059
+ self, version='%prog ' + __version__, **kwargs)
3060
+
3061
+ # Some arm boards have issues with parallel sync.
3062
+ if platform.machine().startswith('arm'):
3063
+ jobs = 1
3064
+ else:
3065
+ jobs = max(8, gclient_utils.NumLocalCpus())
3066
+
3067
+ self.add_option(
3068
+ '-j', '--jobs', default=jobs, type='int',
3069
+ help='Specify how many SCM commands can run in parallel; defaults to '
3070
+ '%default on this machine')
3071
+ self.add_option(
3072
+ '-v', '--verbose', action='count', default=0,
3073
+ help='Produces additional output for diagnostics. Can be used up to '
3074
+ 'three times for more logging info.')
3075
+ self.add_option(
3076
+ '--gclientfile', dest='config_filename',
3077
+ help='Specify an alternate %s file' % self.gclientfile_default)
3078
+ self.add_option(
3079
+ '--spec',
3080
+ help='create a gclient file containing the provided string. Due to '
3081
+ 'Cygwin/Python brokenness, it can\'t contain any newlines.')
3082
+ self.add_option(
3083
+ '--no-nag-max', default=False, action='store_true',
3084
+ help='Ignored for backwards compatibility.')
3085
+
3086
+ def parse_args(self, args=None, _values=None):
3087
+ """Integrates standard options processing."""
3088
+ # Create an optparse.Values object that will store only the actual passed
3089
+ # options, without the defaults.
3090
+ actual_options = optparse.Values()
3091
+ _, args = optparse.OptionParser.parse_args(self, args, actual_options)
3092
+ # Create an optparse.Values object with the default options.
3093
+ options = optparse.Values(self.get_default_values().__dict__)
3094
+ # Update it with the options passed by the user.
3095
+ options._update_careful(actual_options.__dict__)
3096
+ # Store the options passed by the user in an _actual_options attribute.
3097
+ # We store only the keys, and not the values, since the values can contain
3098
+ # arbitrary information, which might be PII.
3099
+ metrics.collector.add('arguments', list(actual_options.__dict__))
3100
+
3101
+ levels = [logging.ERROR, logging.WARNING, logging.INFO, logging.DEBUG]
3102
+ logging.basicConfig(
3103
+ level=levels[min(options.verbose, len(levels) - 1)],
3104
+ format='%(module)s(%(lineno)d) %(funcName)s:%(message)s')
3105
+ if options.config_filename and options.spec:
3106
+ self.error('Cannot specify both --gclientfile and --spec')
3107
+ if (options.config_filename and
3108
+ options.config_filename != os.path.basename(options.config_filename)):
3109
+ self.error('--gclientfile target must be a filename, not a path')
3110
+ if not options.config_filename:
3111
+ options.config_filename = self.gclientfile_default
3112
+ options.entries_filename = options.config_filename + '_entries'
3113
+ if options.jobs < 1:
3114
+ self.error('--jobs must be 1 or higher')
3115
+
3116
+ # These hacks need to die.
3117
+ if not hasattr(options, 'revisions'):
3118
+ # GClient.RunOnDeps expects it even if not applicable.
3119
+ options.revisions = []
3120
+ if not hasattr(options, 'head'):
3121
+ options.head = None
3122
+ if not hasattr(options, 'nohooks'):
3123
+ options.nohooks = True
3124
+ if not hasattr(options, 'noprehooks'):
3125
+ options.noprehooks = True
3126
+ if not hasattr(options, 'deps_os'):
3127
+ options.deps_os = None
3128
+ if not hasattr(options, 'force'):
3129
+ options.force = None
3130
+ return (options, args)
3131
+
3132
+
3133
+ def disable_buffering():
3134
+ # Make stdout auto-flush so buildbot doesn't kill us during lengthy
3135
+ # operations. Python as a strong tendency to buffer sys.stdout.
3136
+ sys.stdout = gclient_utils.MakeFileAutoFlush(sys.stdout)
3137
+ # Make stdout annotated with the thread ids.
3138
+ sys.stdout = gclient_utils.MakeFileAnnotated(sys.stdout)
3139
+
3140
+
3141
+ def path_contains_tilde():
3142
+ for element in os.environ['PATH'].split(os.pathsep):
3143
+ if element.startswith('~') and os.path.abspath(
3144
+ os.path.realpath(os.path.expanduser(element))) == DEPOT_TOOLS_DIR:
3145
+ return True
3146
+ return False
3147
+
3148
+
3149
+ def can_run_gclient_and_helpers():
3150
+ if sys.hexversion < 0x02060000:
3151
+ print(
3152
+ '\nYour python version %s is unsupported, please upgrade.\n' %
3153
+ sys.version.split(' ', 1)[0],
3154
+ file=sys.stderr)
3155
+ return False
3156
+ if not sys.executable:
3157
+ print(
3158
+ '\nPython cannot find the location of it\'s own executable.\n',
3159
+ file=sys.stderr)
3160
+ return False
3161
+ if path_contains_tilde():
3162
+ print(
3163
+ '\nYour PATH contains a literal "~", which works in some shells ' +
3164
+ 'but will break when python tries to run subprocesses. ' +
3165
+ 'Replace the "~" with $HOME.\n' +
3166
+ 'See https://crbug.com/952865.\n',
3167
+ file=sys.stderr)
3168
+ return False
3169
+ return True
3170
+
3171
+
3172
+ def main(argv):
3173
+ """Doesn't parse the arguments here, just find the right subcommand to
3174
+ execute."""
3175
+ if not can_run_gclient_and_helpers():
3176
+ return 2
3177
+ fix_encoding.fix_encoding()
3178
+ disable_buffering()
3179
+ setup_color.init()
3180
+ dispatcher = subcommand.CommandDispatcher(__name__)
3181
+ try:
3182
+ return dispatcher.execute(OptionParser(), argv)
3183
+ except KeyboardInterrupt:
3184
+ gclient_utils.GClientChildren.KillAllRemainingChildren()
3185
+ raise
3186
+ except (gclient_utils.Error, subprocess2.CalledProcessError) as e:
3187
+ print('Error: %s' % str(e), file=sys.stderr)
3188
+ return 1
3189
+ finally:
3190
+ gclient_utils.PrintWarnings()
3191
+ return 0
3192
+
3193
+
3194
+ if '__main__' == __name__:
3195
+ with metrics.collector.print_notice_and_exit():
3196
+ sys.exit(main(sys.argv[1:]))
3197
+
3198
+ # vim: ts=2:sw=2:tw=80:et: