libv8 7.3.492.27.0 → 8.4.255.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +11 -14
- data/CHANGELOG.md +10 -0
- data/README.md +10 -11
- data/Rakefile +30 -36
- data/ext/libv8/builder.rb +1 -1
- data/lib/libv8/version.rb +1 -1
- data/libv8.gemspec +1 -3
- data/vendor/depot_tools/{cipd.ps1 → .cipd_impl.ps1} +0 -0
- data/vendor/depot_tools/.gitattributes +1 -1
- data/vendor/depot_tools/.gitignore +7 -2
- data/vendor/depot_tools/.style.yapf +3 -1
- data/vendor/depot_tools/.vpython +55 -0
- data/vendor/depot_tools/.vpython3 +23 -0
- data/vendor/depot_tools/CROS_OWNERS +3 -1
- data/vendor/depot_tools/GOMA_OWNERS +9 -0
- data/vendor/depot_tools/LUCI_OWNERS +5 -0
- data/vendor/depot_tools/OWNERS +21 -6
- data/vendor/depot_tools/PRESUBMIT.py +35 -18
- data/vendor/depot_tools/README.git-cl.md +0 -14
- data/vendor/depot_tools/README.md +1 -1
- data/vendor/depot_tools/WATCHLISTS +2 -2
- data/vendor/depot_tools/auth.py +60 -772
- data/vendor/depot_tools/autoninja +12 -6
- data/vendor/depot_tools/autoninja.bat +14 -6
- data/vendor/depot_tools/autoninja.py +64 -27
- data/vendor/depot_tools/bb +1 -1
- data/vendor/depot_tools/bootstrap/{win/README.md → README.md} +28 -14
- data/vendor/depot_tools/bootstrap/{win/win_tools.py → bootstrap.py} +60 -43
- data/vendor/depot_tools/bootstrap/{win/git-bash.template.sh → git-bash.template.sh} +1 -1
- data/vendor/depot_tools/bootstrap/{win/git.template.bat → git.template.bat} +0 -0
- data/vendor/depot_tools/bootstrap/manifest.txt +27 -0
- data/vendor/depot_tools/bootstrap/manifest_bleeding_edge.txt +27 -0
- data/vendor/depot_tools/bootstrap/{win/profile.d.python.sh → profile.d.python.sh} +0 -0
- data/vendor/depot_tools/bootstrap/{win/python27.bleeding_edge.bat → python27.bat} +0 -0
- data/vendor/depot_tools/bootstrap/{win/python27.new.bat → python3.bat} +3 -3
- data/vendor/depot_tools/bootstrap/{win/win_tools.bat → win_tools.bat} +21 -16
- data/vendor/depot_tools/bootstrap_python3 +35 -0
- data/vendor/depot_tools/cbuildbot +1 -1
- data/vendor/depot_tools/chrome_set_ver +1 -1
- data/vendor/depot_tools/cipd +43 -39
- data/vendor/depot_tools/cipd.bat +2 -2
- data/vendor/depot_tools/cipd_client_version +1 -1
- data/vendor/depot_tools/cipd_client_version.digests +15 -14
- data/vendor/depot_tools/cipd_manifest.txt +31 -8
- data/vendor/depot_tools/cipd_manifest.versions +278 -158
- data/vendor/depot_tools/cit.py +9 -7
- data/vendor/depot_tools/clang_format.py +4 -1
- data/vendor/depot_tools/clang_format_merge_driver.py +10 -8
- data/vendor/depot_tools/compile_single_file.py +7 -2
- data/vendor/depot_tools/cpplint.py +51 -45
- data/vendor/depot_tools/cros +87 -0
- data/vendor/depot_tools/cros_sdk +1 -1
- data/vendor/depot_tools/crosjobs +13 -0
- data/vendor/depot_tools/detect_host_arch.py +0 -1
- data/vendor/depot_tools/dirmd +12 -0
- data/vendor/depot_tools/dirmd.bat +7 -0
- data/vendor/depot_tools/download_from_google_storage.py +47 -27
- data/vendor/depot_tools/ensure_bootstrap +14 -0
- data/vendor/depot_tools/fetch +14 -1
- data/vendor/depot_tools/fetch.bat +14 -1
- data/vendor/depot_tools/fetch.py +5 -7
- data/vendor/depot_tools/fetch_configs/chromium.py +6 -4
- data/vendor/depot_tools/fetch_configs/devtools-frontend.py +44 -0
- data/vendor/depot_tools/fetch_configs/ios_internal.py +10 -19
- data/vendor/depot_tools/fix_encoding.py +19 -5
- data/vendor/depot_tools/gclient +28 -12
- data/vendor/depot_tools/gclient-new-workdir.py +2 -0
- data/vendor/depot_tools/gclient.bat +18 -1
- data/vendor/depot_tools/gclient.py +160 -119
- data/vendor/depot_tools/gclient_eval.py +119 -107
- data/vendor/depot_tools/gclient_paths.py +67 -57
- data/vendor/depot_tools/gclient_scm.py +181 -159
- data/vendor/depot_tools/gclient_utils.py +177 -124
- data/vendor/depot_tools/gerrit_client.py +21 -13
- data/vendor/depot_tools/gerrit_util.py +188 -228
- data/vendor/depot_tools/git-cache +1 -1
- data/vendor/depot_tools/git-cl +1 -1
- data/vendor/depot_tools/git-drover +1 -1
- data/vendor/depot_tools/git-find-releases +1 -1
- data/vendor/depot_tools/git-footers +1 -1
- data/vendor/depot_tools/git-freeze +1 -1
- data/vendor/depot_tools/git-hyper-blame +1 -1
- data/vendor/depot_tools/git-map +1 -1
- data/vendor/depot_tools/git-map-branches +1 -1
- data/vendor/depot_tools/git-mark-merge-base +1 -1
- data/vendor/depot_tools/git-nav-downstream +1 -1
- data/vendor/depot_tools/git-new-branch +1 -1
- data/vendor/depot_tools/git-number +1 -1
- data/vendor/depot_tools/git-rebase-update +1 -1
- data/vendor/depot_tools/git-rename-branch +1 -1
- data/vendor/depot_tools/git-reparent-branch +1 -1
- data/vendor/depot_tools/git-retry +1 -1
- data/vendor/depot_tools/git-squash-branch +1 -1
- data/vendor/depot_tools/git-thaw +1 -1
- data/vendor/depot_tools/git-upstream-diff +1 -1
- data/vendor/depot_tools/git_cache.py +255 -360
- data/vendor/depot_tools/git_cl.py +1562 -2059
- data/vendor/depot_tools/git_cl_completion.sh +16 -2
- data/vendor/depot_tools/git_common.py +77 -32
- data/vendor/depot_tools/git_drover.py +17 -8
- data/vendor/depot_tools/git_find_releases.py +11 -9
- data/vendor/depot_tools/git_footers.py +13 -9
- data/vendor/depot_tools/git_freezer.py +3 -1
- data/vendor/depot_tools/git_hyper_blame.py +25 -32
- data/vendor/depot_tools/git_map.py +115 -93
- data/vendor/depot_tools/git_map_branches.py +11 -10
- data/vendor/depot_tools/git_mark_merge_base.py +8 -6
- data/vendor/depot_tools/git_nav_downstream.py +9 -6
- data/vendor/depot_tools/git_new_branch.py +39 -33
- data/vendor/depot_tools/git_number.py +28 -17
- data/vendor/depot_tools/git_rebase_update.py +50 -49
- data/vendor/depot_tools/git_rename_branch.py +2 -2
- data/vendor/depot_tools/git_reparent_branch.py +8 -6
- data/vendor/depot_tools/git_upstream_diff.py +4 -2
- data/vendor/depot_tools/gn.py +6 -4
- data/vendor/depot_tools/goma_auth +12 -0
- data/vendor/depot_tools/goma_auth.bat +8 -0
- data/vendor/depot_tools/goma_ctl +12 -0
- data/vendor/depot_tools/goma_ctl.bat +8 -0
- data/vendor/depot_tools/gsutil.py +5 -2
- data/vendor/depot_tools/gsutil.py.bat +8 -0
- data/vendor/depot_tools/gsutil.vpython +3 -1
- data/vendor/depot_tools/infra/config/OWNERS +2 -2
- data/vendor/depot_tools/infra/config/recipes.cfg +3 -2
- data/vendor/depot_tools/led +1 -1
- data/vendor/depot_tools/lockfile.py +116 -0
- data/vendor/depot_tools/luci-auth +1 -1
- data/vendor/depot_tools/lucicfg +1 -1
- data/vendor/depot_tools/mac_toolchain +1 -1
- data/vendor/depot_tools/man/html/depot_tools.html +1 -1
- data/vendor/depot_tools/man/html/depot_tools_tutorial.html +31 -25
- data/vendor/depot_tools/man/html/git-cl.html +1 -1
- data/vendor/depot_tools/man/html/git-drover.html +18 -18
- data/vendor/depot_tools/man/html/git-footers.html +1 -1
- data/vendor/depot_tools/man/html/git-freeze.html +3 -3
- data/vendor/depot_tools/man/html/git-hyper-blame.html +1 -1
- data/vendor/depot_tools/man/html/git-map-branches.html +2 -2
- data/vendor/depot_tools/man/html/git-map.html +1 -1
- data/vendor/depot_tools/man/html/git-mark-merge-base.html +1 -1
- data/vendor/depot_tools/man/html/git-nav-downstream.html +3 -3
- data/vendor/depot_tools/man/html/git-nav-upstream.html +12 -6
- data/vendor/depot_tools/man/html/git-new-branch.html +1 -1
- data/vendor/depot_tools/man/html/git-rebase-update.html +20 -1
- data/vendor/depot_tools/man/html/git-rename-branch.html +1 -1
- data/vendor/depot_tools/man/html/git-reparent-branch.html +1 -1
- data/vendor/depot_tools/man/html/git-retry.html +1 -1
- data/vendor/depot_tools/man/html/git-squash-branch.html +1 -1
- data/vendor/depot_tools/man/html/git-thaw.html +1 -1
- data/vendor/depot_tools/man/html/git-upstream-diff.html +10 -6
- data/vendor/depot_tools/man/man1/git-cl.1 +4 -4
- data/vendor/depot_tools/man/man1/git-drover.1 +21 -21
- data/vendor/depot_tools/man/man1/git-footers.1 +4 -4
- data/vendor/depot_tools/man/man1/git-freeze.1 +6 -6
- data/vendor/depot_tools/man/man1/git-hyper-blame.1 +4 -4
- data/vendor/depot_tools/man/man1/git-map-branches.1 +4 -4
- data/vendor/depot_tools/man/man1/git-map.1 +4 -4
- data/vendor/depot_tools/man/man1/git-mark-merge-base.1 +4 -4
- data/vendor/depot_tools/man/man1/git-nav-downstream.1 +6 -6
- data/vendor/depot_tools/man/man1/git-nav-upstream.1 +15 -9
- data/vendor/depot_tools/man/man1/git-new-branch.1 +3 -3
- data/vendor/depot_tools/man/man1/git-rebase-update.1 +14 -4
- data/vendor/depot_tools/man/man1/git-rename-branch.1 +4 -4
- data/vendor/depot_tools/man/man1/git-reparent-branch.1 +4 -4
- data/vendor/depot_tools/man/man1/git-retry.1 +4 -4
- data/vendor/depot_tools/man/man1/git-squash-branch.1 +4 -4
- data/vendor/depot_tools/man/man1/git-thaw.1 +4 -4
- data/vendor/depot_tools/man/man1/git-upstream-diff.1 +7 -13
- data/vendor/depot_tools/man/man7/depot_tools.7 +4 -4
- data/vendor/depot_tools/man/man7/depot_tools_tutorial.7 +31 -25
- data/vendor/depot_tools/man/src/common_demo_functions.sh +2 -2
- data/vendor/depot_tools/man/src/depot_tools_tutorial.txt +3 -3
- data/vendor/depot_tools/man/src/filter_demo_output.py +4 -2
- data/vendor/depot_tools/man/src/git-new-branch.txt +2 -1
- data/vendor/depot_tools/man/src/git-rebase-update.txt +8 -1
- data/vendor/depot_tools/metrics.README.md +8 -5
- data/vendor/depot_tools/metrics.py +7 -6
- data/vendor/depot_tools/metrics_utils.py +4 -14
- data/vendor/depot_tools/my_activity.py +85 -251
- data/vendor/depot_tools/ninja +1 -0
- data/vendor/depot_tools/ninja-mac +0 -0
- data/vendor/depot_tools/ninjalog_uploader.py +146 -145
- data/vendor/depot_tools/ninjalog_uploader_wrapper.py +69 -60
- data/vendor/depot_tools/owners.py +156 -43
- data/vendor/depot_tools/owners_finder.py +28 -14
- data/vendor/depot_tools/post_build_ninja_summary.py +76 -48
- data/vendor/depot_tools/presubmit_canned_checks.py +293 -106
- data/vendor/depot_tools/presubmit_support.py +527 -333
- data/vendor/depot_tools/prpc +1 -1
- data/vendor/depot_tools/pylint +2 -12
- data/vendor/depot_tools/pylint-1.5 +78 -0
- data/vendor/depot_tools/pylint-1.6 +78 -0
- data/vendor/depot_tools/pylint-1.7 +78 -0
- data/vendor/depot_tools/pylint-1.8 +78 -0
- data/vendor/depot_tools/pylint-1.9 +78 -0
- data/vendor/depot_tools/{depot-tools-auth.bat → pylint.bat} +2 -2
- data/vendor/depot_tools/pylint_main.py +45 -0
- data/vendor/depot_tools/pylintrc +14 -1
- data/vendor/depot_tools/python-bin/python3 +7 -0
- data/vendor/depot_tools/python_runner.sh +13 -8
- data/vendor/depot_tools/rdb +12 -0
- data/vendor/depot_tools/rdb.bat +7 -0
- data/vendor/depot_tools/recipes/OWNERS +0 -1
- data/vendor/depot_tools/recipes/README.recipes.md +218 -151
- data/vendor/depot_tools/recipes/recipe_modules/OWNERS +1 -1
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/__init__.py +17 -16
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/api.py +127 -78
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic.json +19 -4
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic_luci.json +18 -3
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/basic_with_branch_heads.json +19 -4
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/clobber.json +29 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/deprecated_got_revision_mapping.json +28 -10
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/gerrit_no_rebase_patch_ref.json +29 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/gerrit_no_reset.json +29 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/input_commit_with_id_without_repo.json +29 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/multiple_patch_refs.json +29 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_apply_patch_on_gclient.json +35 -10
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/{with_manifest_name.json → no_cp_checkout_HEAD.json} +25 -15
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_cp_checkout_a_branch_head.json +65 -0
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_cp_checkout_a_specific_commit.json +65 -0
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/no_cp_checkout_master.json +65 -0
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/refs.json +29 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/reset_root_solution_revision.json +29 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/resolve_chromium_fixed_version.json +117 -0
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail.json +17 -11
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch.json +41 -10
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch_download.json +24 -11
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_angle.json +35 -10
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_branch_heads.json +35 -10
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_feature_branch.json +38 -11
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_v8_feature_branch.json +36 -11
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_webrtc.json +35 -10
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8.json +35 -10
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8_head_by_default.json +35 -10
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/unrecognized_commit_repo.json +0 -5
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/with_tags.json +29 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.py +95 -22
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/resources/bot_update.py +187 -114
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/test_api.py +2 -2
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/tests/do_not_retry_patch_failures_in_cq.py +42 -0
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/tests/ensure_checkout.py +1 -0
- data/vendor/depot_tools/recipes/recipe_modules/cipd/__init__.py +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/api.py +2 -2
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/basic.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/basic_pkg.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/describe-failed.json +2 -4
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/describe-many-instances.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/mac64.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/pkg_bad_file.json +26 -6
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/pkg_bad_mode.json +23 -5
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/pkg_bad_verfile.json +23 -5
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/full.expected/win64.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/junk arch.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/junk bits.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_arm_32.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_arm_64.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_intel_32.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_intel_64.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/linux_mips_64.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/mac_intel_64.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/win_intel_32.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/examples/platform_suffix.expected/win_intel_64.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/cipd/test_api.py +1 -1
- data/vendor/depot_tools/recipes/recipe_modules/depot_tools/api.py +4 -1
- data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.expected/basic.json +4 -2
- data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.expected/basic_luci.json +3 -1
- data/vendor/depot_tools/recipes/recipe_modules/depot_tools/examples/full.expected/win.json +4 -2
- data/vendor/depot_tools/recipes/recipe_modules/gclient/__init__.py +2 -1
- data/vendor/depot_tools/recipes/recipe_modules/gclient/api.py +82 -13
- data/vendor/depot_tools/recipes/recipe_modules/gclient/config.py +23 -11
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/basic.json +3 -4
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/revision.json +3 -6
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/tryserver.json +3 -4
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.py +7 -7
- data/vendor/depot_tools/recipes/recipe_modules/gclient/resources/diff_deps.py +16 -0
- data/vendor/depot_tools/recipes/recipe_modules/gclient/test_api.py +4 -0
- data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.expected/basic.json +55 -0
- data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.expected/dont have revision yet.json +84 -0
- data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.expected/no change, exception.json +83 -0
- data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.expected/windows.json +55 -0
- data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/diff_deps.py +88 -0
- data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/patch_project.py +9 -21
- data/vendor/depot_tools/recipes/recipe_modules/gclient/tests/sync_failure.py +24 -0
- data/vendor/depot_tools/recipes/recipe_modules/gerrit/api.py +2 -1
- data/vendor/depot_tools/recipes/recipe_modules/gerrit/examples/full.expected/basic.json +7 -12
- data/vendor/depot_tools/recipes/recipe_modules/git/__init__.py +0 -2
- data/vendor/depot_tools/recipes/recipe_modules/git/api.py +9 -17
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic.json +2 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_branch.json +2 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_file_name.json +2 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_hash.json +2 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_ref.json +2 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_submodule_update_force.json +2 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_tags.json +2 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/can_fail_build.json +3 -13
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/cannot_fail_build.json +2 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/cat-file_test.json +4 -12
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_delta.json +2 -10
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_failed.json +1 -7
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_with_bad_output.json +1 -7
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/count-objects_with_bad_output_fails_build.json +0 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/curl_trace_file.json +3 -10
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/git-cache-checkout.json +3 -11
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/platform_win.json +2 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/rebase_failed.json +3 -13
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/remote_not_origin.json +2 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/set_got_revision.json +2 -8
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.py +0 -5
- data/vendor/depot_tools/recipes/recipe_modules/git_cl/__init__.py +1 -1
- data/vendor/depot_tools/recipes/recipe_modules/git_cl/api.py +7 -13
- data/vendor/depot_tools/recipes/recipe_modules/git_cl/examples/full.expected/basic.json +21 -16
- data/vendor/depot_tools/recipes/recipe_modules/git_cl/examples/full.py +1 -2
- data/vendor/depot_tools/recipes/recipe_modules/gitiles/api.py +1 -1
- data/vendor/depot_tools/recipes/recipe_modules/gitiles/examples/full.expected/basic.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/gitiles/resources/gerrit_client.py +2 -2
- data/vendor/depot_tools/recipes/recipe_modules/gitiles/tests/parse_repo_url.expected/basic.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/gsutil/api.py +23 -8
- data/vendor/depot_tools/recipes/recipe_modules/gsutil/examples/full.expected/basic.json +52 -1
- data/vendor/depot_tools/recipes/recipe_modules/gsutil/examples/full.py +15 -0
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/__init__.py +1 -0
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/api.py +32 -8
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/ancient_version.json +83 -0
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/automatic_version.json +83 -0
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/explicit_version.json +83 -0
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/linux.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/mac.json +5 -4
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.expected/win.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/osx_sdk/examples/full.py +21 -2
- data/vendor/depot_tools/recipes/recipe_modules/presubmit/__init__.py +20 -0
- data/vendor/depot_tools/recipes/recipe_modules/presubmit/api.py +235 -3
- data/vendor/depot_tools/recipes/recipe_modules/presubmit/examples/full.expected/basic.json +13 -5
- data/vendor/depot_tools/recipes/recipe_modules/presubmit/examples/full.py +5 -1
- data/vendor/depot_tools/recipes/recipe_modules/presubmit/properties.proto +14 -0
- data/vendor/depot_tools/recipes/recipe_modules/presubmit/test_api.py +19 -0
- data/vendor/depot_tools/recipes/recipe_modules/presubmit/tests/execute.py +247 -0
- data/vendor/depot_tools/recipes/recipe_modules/presubmit/tests/prepare.py +49 -0
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/api.py +33 -45
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/basic_tags.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_gerrit_patch.json +64 -21
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_gerrit_patch_and_target_ref.json +64 -21
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_wrong_patch.json +1 -22
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_wrong_patch_new.json +1 -22
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.py +5 -32
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/tests/gerrit_change_fetch_ref_timeout.py +29 -0
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/tests/gerrit_change_owner.expected/basic.json +5 -0
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/tests/gerrit_change_owner.py +22 -0
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/tests/gerrit_change_target_ref.py +32 -0
- data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.expected/linux.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.expected/mac.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.expected/win.json +2 -1
- data/vendor/depot_tools/recipes/recipe_modules/windows_sdk/examples/full.py +1 -6
- data/vendor/depot_tools/recipes/recipes.py +49 -28
- data/vendor/depot_tools/recipes/recipes/fetch_end_to_end_test.expected/basic.json +11 -6
- data/vendor/depot_tools/repo +698 -540
- data/vendor/depot_tools/roll-dep +14 -1
- data/vendor/depot_tools/roll-dep.bat +10 -1
- data/vendor/depot_tools/roll_dep.py +15 -10
- data/vendor/depot_tools/scm.py +95 -75
- data/vendor/depot_tools/setup_color.py +36 -2
- data/vendor/depot_tools/split_cl.py +44 -32
- data/vendor/depot_tools/subcommand.py +6 -6
- data/vendor/depot_tools/subprocess2.py +38 -322
- data/vendor/depot_tools/third_party/colorama/LICENSE.txt +0 -1
- data/vendor/depot_tools/third_party/colorama/README.chromium +4 -5
- data/vendor/depot_tools/third_party/colorama/README.rst +346 -0
- data/vendor/depot_tools/third_party/colorama/__init__.py +3 -4
- data/vendor/depot_tools/third_party/colorama/ansi.py +82 -30
- data/vendor/depot_tools/third_party/colorama/ansitowin32.py +105 -37
- data/vendor/depot_tools/third_party/colorama/initialise.py +39 -15
- data/vendor/depot_tools/third_party/colorama/win32.py +46 -28
- data/vendor/depot_tools/third_party/colorama/winterm.py +80 -31
- data/vendor/depot_tools/update_depot_tools +18 -8
- data/vendor/depot_tools/update_depot_tools.bat +19 -15
- data/vendor/depot_tools/upload_metrics.py +7 -6
- data/vendor/depot_tools/upload_to_google_storage.py +23 -16
- data/vendor/depot_tools/vpython +4 -4
- data/vendor/depot_tools/vpython.bat +1 -1
- data/vendor/depot_tools/vpython3 +55 -0
- data/vendor/depot_tools/vpython3.bat +12 -0
- data/vendor/depot_tools/watchlists.py +14 -11
- data/vendor/depot_tools/weekly +4 -2
- data/vendor/depot_tools/win32imports.py +61 -0
- data/vendor/depot_tools/win_toolchain/get_toolchain_if_necessary.py +49 -41
- data/vendor/depot_tools/win_toolchain/package_from_installed.py +142 -149
- data/vendor/depot_tools/wtf +5 -3
- data/vendor/depot_tools/yapf +5 -1
- metadata +68 -343
- data/vendor/depot_tools/README.testing +0 -23
- data/vendor/depot_tools/annotated_gclient.py +0 -89
- data/vendor/depot_tools/appengine_mapper.py +0 -23
- data/vendor/depot_tools/bootstrap/win/manifest.txt +0 -20
- data/vendor/depot_tools/bootstrap/win/manifest_bleeding_edge.txt +0 -20
- data/vendor/depot_tools/bootstrap/win/pylint.new.bat +0 -7
- data/vendor/depot_tools/buildbucket.py +0 -186
- data/vendor/depot_tools/checkout.py +0 -431
- data/vendor/depot_tools/cros +0 -1
- data/vendor/depot_tools/dart_format.py +0 -58
- data/vendor/depot_tools/depot-tools-auth +0 -8
- data/vendor/depot_tools/depot-tools-auth.py +0 -102
- data/vendor/depot_tools/my_reviews.py +0 -396
- data/vendor/depot_tools/patch.py +0 -548
- data/vendor/depot_tools/pylint.py +0 -30
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/buildbot.json +0 -239
- data/vendor/depot_tools/recipes/recipe_modules/git/examples/full.expected/basic_luci.json +0 -222
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/__init__.py +0 -4
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/api.py +0 -29
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/basic.json +0 -15
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_buildbot_linux.json +0 -15
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_buildbot_mac.json +0 -15
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_buildbot_win.json +0 -15
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_generic_linux.json +0 -15
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_generic_mac.json +0 -15
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_generic_win.json +0 -15
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_kitchen_linux.json +0 -15
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_kitchen_mac.json +0 -15
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.expected/paths_kitchen_win.json +0 -15
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/examples/full.py +0 -33
- data/vendor/depot_tools/recipes/recipe_modules/infra_paths/path_config.py +0 -66
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/set_failure_hash_with_no_steps.json +0 -11
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_git_patch.json +0 -45
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_git_patch_luci.json +0 -45
- data/vendor/depot_tools/rietveld.py +0 -779
- data/vendor/depot_tools/roll-dep-svn +0 -8
- data/vendor/depot_tools/roll-dep-svn.bat +0 -12
- data/vendor/depot_tools/roll_dep_svn.py +0 -430
- data/vendor/depot_tools/support/chromite_wrapper +0 -96
- data/vendor/depot_tools/third_party/boto/LICENSE +0 -18
- data/vendor/depot_tools/third_party/boto/README.chromium +0 -43
- data/vendor/depot_tools/third_party/boto/README.rst +0 -163
- data/vendor/depot_tools/third_party/boto/__init__.py +0 -793
- data/vendor/depot_tools/third_party/boto/auth.py +0 -682
- data/vendor/depot_tools/third_party/boto/auth_handler.py +0 -58
- data/vendor/depot_tools/third_party/boto/cacerts/__init__.py +0 -22
- data/vendor/depot_tools/third_party/boto/cacerts/cacerts.txt +0 -2183
- data/vendor/depot_tools/third_party/boto/compat.py +0 -28
- data/vendor/depot_tools/third_party/boto/connection.py +0 -1081
- data/vendor/depot_tools/third_party/boto/contrib/__init__.py +0 -22
- data/vendor/depot_tools/third_party/boto/contrib/ymlmessage.py +0 -52
- data/vendor/depot_tools/third_party/boto/core/README +0 -58
- data/vendor/depot_tools/third_party/boto/core/__init__.py +0 -23
- data/vendor/depot_tools/third_party/boto/core/auth.py +0 -78
- data/vendor/depot_tools/third_party/boto/core/credentials.py +0 -154
- data/vendor/depot_tools/third_party/boto/core/dictresponse.py +0 -178
- data/vendor/depot_tools/third_party/boto/core/service.py +0 -67
- data/vendor/depot_tools/third_party/boto/datapipeline/__init__.py +0 -0
- data/vendor/depot_tools/third_party/boto/datapipeline/exceptions.py +0 -42
- data/vendor/depot_tools/third_party/boto/datapipeline/layer1.py +0 -546
- data/vendor/depot_tools/third_party/boto/ecs/__init__.py +0 -90
- data/vendor/depot_tools/third_party/boto/ecs/item.py +0 -153
- data/vendor/depot_tools/third_party/boto/exception.py +0 -476
- data/vendor/depot_tools/third_party/boto/file/README +0 -49
- data/vendor/depot_tools/third_party/boto/file/__init__.py +0 -28
- data/vendor/depot_tools/third_party/boto/file/bucket.py +0 -112
- data/vendor/depot_tools/third_party/boto/file/connection.py +0 -33
- data/vendor/depot_tools/third_party/boto/file/key.py +0 -199
- data/vendor/depot_tools/third_party/boto/file/simpleresultset.py +0 -30
- data/vendor/depot_tools/third_party/boto/fps/__init__.py +0 -21
- data/vendor/depot_tools/third_party/boto/fps/connection.py +0 -369
- data/vendor/depot_tools/third_party/boto/fps/exception.py +0 -344
- data/vendor/depot_tools/third_party/boto/fps/response.py +0 -175
- data/vendor/depot_tools/third_party/boto/gs/__init__.py +0 -22
- data/vendor/depot_tools/third_party/boto/gs/acl.py +0 -304
- data/vendor/depot_tools/third_party/boto/gs/bucket.py +0 -870
- data/vendor/depot_tools/third_party/boto/gs/bucketlistresultset.py +0 -64
- data/vendor/depot_tools/third_party/boto/gs/connection.py +0 -103
- data/vendor/depot_tools/third_party/boto/gs/cors.py +0 -169
- data/vendor/depot_tools/third_party/boto/gs/key.py +0 -704
- data/vendor/depot_tools/third_party/boto/gs/resumable_upload_handler.py +0 -659
- data/vendor/depot_tools/third_party/boto/gs/user.py +0 -54
- data/vendor/depot_tools/third_party/boto/handler.py +0 -44
- data/vendor/depot_tools/third_party/boto/https_connection.py +0 -124
- data/vendor/depot_tools/third_party/boto/jsonresponse.py +0 -163
- data/vendor/depot_tools/third_party/boto/manage/__init__.py +0 -23
- data/vendor/depot_tools/third_party/boto/manage/cmdshell.py +0 -241
- data/vendor/depot_tools/third_party/boto/manage/propget.py +0 -64
- data/vendor/depot_tools/third_party/boto/manage/server.py +0 -556
- data/vendor/depot_tools/third_party/boto/manage/task.py +0 -175
- data/vendor/depot_tools/third_party/boto/manage/test_manage.py +0 -34
- data/vendor/depot_tools/third_party/boto/manage/volume.py +0 -420
- data/vendor/depot_tools/third_party/boto/mashups/__init__.py +0 -23
- data/vendor/depot_tools/third_party/boto/mashups/interactive.py +0 -97
- data/vendor/depot_tools/third_party/boto/mashups/iobject.py +0 -115
- data/vendor/depot_tools/third_party/boto/mashups/order.py +0 -211
- data/vendor/depot_tools/third_party/boto/mashups/server.py +0 -395
- data/vendor/depot_tools/third_party/boto/plugin.py +0 -90
- data/vendor/depot_tools/third_party/boto/provider.py +0 -337
- data/vendor/depot_tools/third_party/boto/pyami/__init__.py +0 -22
- data/vendor/depot_tools/third_party/boto/pyami/bootstrap.py +0 -134
- data/vendor/depot_tools/third_party/boto/pyami/config.py +0 -229
- data/vendor/depot_tools/third_party/boto/pyami/copybot.cfg +0 -60
- data/vendor/depot_tools/third_party/boto/pyami/copybot.py +0 -97
- data/vendor/depot_tools/third_party/boto/pyami/helloworld.py +0 -28
- data/vendor/depot_tools/third_party/boto/pyami/launch_ami.py +0 -178
- data/vendor/depot_tools/third_party/boto/pyami/scriptbase.py +0 -44
- data/vendor/depot_tools/third_party/boto/pyami/startup.py +0 -60
- data/vendor/depot_tools/third_party/boto/regioninfo.py +0 -63
- data/vendor/depot_tools/third_party/boto/resultset.py +0 -169
- data/vendor/depot_tools/third_party/boto/roboto/__init__.py +0 -1
- data/vendor/depot_tools/third_party/boto/roboto/awsqueryrequest.py +0 -504
- data/vendor/depot_tools/third_party/boto/roboto/awsqueryservice.py +0 -121
- data/vendor/depot_tools/third_party/boto/roboto/param.py +0 -147
- data/vendor/depot_tools/third_party/boto/s3/__init__.py +0 -84
- data/vendor/depot_tools/third_party/boto/s3/acl.py +0 -164
- data/vendor/depot_tools/third_party/boto/s3/bucket.py +0 -1634
- data/vendor/depot_tools/third_party/boto/s3/bucketlistresultset.py +0 -139
- data/vendor/depot_tools/third_party/boto/s3/bucketlogging.py +0 -83
- data/vendor/depot_tools/third_party/boto/s3/connection.py +0 -540
- data/vendor/depot_tools/third_party/boto/s3/cors.py +0 -210
- data/vendor/depot_tools/third_party/boto/s3/deletemarker.py +0 -55
- data/vendor/depot_tools/third_party/boto/s3/key.py +0 -1712
- data/vendor/depot_tools/third_party/boto/s3/keyfile.py +0 -134
- data/vendor/depot_tools/third_party/boto/s3/lifecycle.py +0 -231
- data/vendor/depot_tools/third_party/boto/s3/multidelete.py +0 -138
- data/vendor/depot_tools/third_party/boto/s3/multipart.py +0 -315
- data/vendor/depot_tools/third_party/boto/s3/prefix.py +0 -42
- data/vendor/depot_tools/third_party/boto/s3/resumable_download_handler.py +0 -339
- data/vendor/depot_tools/third_party/boto/s3/tagging.py +0 -71
- data/vendor/depot_tools/third_party/boto/s3/user.py +0 -49
- data/vendor/depot_tools/third_party/boto/s3/website.py +0 -237
- data/vendor/depot_tools/third_party/boto/services/__init__.py +0 -23
- data/vendor/depot_tools/third_party/boto/services/bs.py +0 -179
- data/vendor/depot_tools/third_party/boto/services/message.py +0 -58
- data/vendor/depot_tools/third_party/boto/services/result.py +0 -136
- data/vendor/depot_tools/third_party/boto/services/service.py +0 -161
- data/vendor/depot_tools/third_party/boto/services/servicedef.py +0 -91
- data/vendor/depot_tools/third_party/boto/services/sonofmmm.cfg +0 -43
- data/vendor/depot_tools/third_party/boto/services/sonofmmm.py +0 -81
- data/vendor/depot_tools/third_party/boto/services/submit.py +0 -88
- data/vendor/depot_tools/third_party/boto/ses/__init__.py +0 -54
- data/vendor/depot_tools/third_party/boto/ses/connection.py +0 -521
- data/vendor/depot_tools/third_party/boto/ses/exceptions.py +0 -77
- data/vendor/depot_tools/third_party/boto/storage_uri.py +0 -835
- data/vendor/depot_tools/third_party/boto/sts/__init__.py +0 -55
- data/vendor/depot_tools/third_party/boto/sts/connection.py +0 -207
- data/vendor/depot_tools/third_party/boto/sts/credentials.py +0 -215
- data/vendor/depot_tools/third_party/boto/utils.py +0 -927
- data/vendor/depot_tools/third_party/colorama/README.txt +0 -304
- data/vendor/depot_tools/third_party/fancy_urllib/README +0 -22
- data/vendor/depot_tools/third_party/fancy_urllib/__init__.py +0 -460
- data/vendor/depot_tools/third_party/logilab/README.chromium +0 -6
- data/vendor/depot_tools/third_party/logilab/__init__.py +0 -0
- data/vendor/depot_tools/third_party/logilab/astroid/LICENSE.txt +0 -340
- data/vendor/depot_tools/third_party/logilab/astroid/README.chromium +0 -11
- data/vendor/depot_tools/third_party/logilab/astroid/__init__.py +0 -136
- data/vendor/depot_tools/third_party/logilab/astroid/__pkginfo__.py +0 -42
- data/vendor/depot_tools/third_party/logilab/astroid/arguments.py +0 -233
- data/vendor/depot_tools/third_party/logilab/astroid/as_string.py +0 -548
- data/vendor/depot_tools/third_party/logilab/astroid/astpeephole.py +0 -86
- data/vendor/depot_tools/third_party/logilab/astroid/bases.py +0 -636
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_builtin_inference.py +0 -336
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_dateutil.py +0 -15
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_gi.py +0 -195
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_mechanize.py +0 -18
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_nose.py +0 -82
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_numpy.py +0 -62
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_pytest.py +0 -76
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_qt.py +0 -44
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_six.py +0 -288
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_ssl.py +0 -65
- data/vendor/depot_tools/third_party/logilab/astroid/brain/brain_stdlib.py +0 -473
- data/vendor/depot_tools/third_party/logilab/astroid/builder.py +0 -263
- data/vendor/depot_tools/third_party/logilab/astroid/context.py +0 -81
- data/vendor/depot_tools/third_party/logilab/astroid/decorators.py +0 -75
- data/vendor/depot_tools/third_party/logilab/astroid/exceptions.py +0 -71
- data/vendor/depot_tools/third_party/logilab/astroid/inference.py +0 -359
- data/vendor/depot_tools/third_party/logilab/astroid/manager.py +0 -267
- data/vendor/depot_tools/third_party/logilab/astroid/mixins.py +0 -147
- data/vendor/depot_tools/third_party/logilab/astroid/modutils.py +0 -741
- data/vendor/depot_tools/third_party/logilab/astroid/node_classes.py +0 -1053
- data/vendor/depot_tools/third_party/logilab/astroid/nodes.py +0 -87
- data/vendor/depot_tools/third_party/logilab/astroid/objects.py +0 -186
- data/vendor/depot_tools/third_party/logilab/astroid/protocols.py +0 -470
- data/vendor/depot_tools/third_party/logilab/astroid/raw_building.py +0 -390
- data/vendor/depot_tools/third_party/logilab/astroid/rebuilder.py +0 -989
- data/vendor/depot_tools/third_party/logilab/astroid/scoped_nodes.py +0 -1716
- data/vendor/depot_tools/third_party/logilab/astroid/test_utils.py +0 -201
- data/vendor/depot_tools/third_party/logilab/astroid/transforms.py +0 -96
- data/vendor/depot_tools/third_party/logilab/astroid/util.py +0 -89
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/LICENSE +0 -19
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/README.chromium +0 -11
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/__init__.py +0 -20
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/cext.c +0 -1421
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/compat.py +0 -9
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/simple.py +0 -246
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/slots.py +0 -414
- data/vendor/depot_tools/third_party/logilab/lazy_object_proxy/utils.py +0 -13
- data/vendor/depot_tools/third_party/logilab/wrapt/LICENSE +0 -24
- data/vendor/depot_tools/third_party/logilab/wrapt/README.chromium +0 -11
- data/vendor/depot_tools/third_party/logilab/wrapt/__init__.py +0 -19
- data/vendor/depot_tools/third_party/logilab/wrapt/_wrappers.c +0 -2729
- data/vendor/depot_tools/third_party/logilab/wrapt/arguments.py +0 -96
- data/vendor/depot_tools/third_party/logilab/wrapt/decorators.py +0 -512
- data/vendor/depot_tools/third_party/logilab/wrapt/importer.py +0 -228
- data/vendor/depot_tools/third_party/logilab/wrapt/wrappers.py +0 -901
- data/vendor/depot_tools/third_party/mock/LICENSE.txt +0 -26
- data/vendor/depot_tools/third_party/mock/README.chromium +0 -24
- data/vendor/depot_tools/third_party/mock/__init__.py +0 -2366
- data/vendor/depot_tools/third_party/oauth2client/LICENSE +0 -202
- data/vendor/depot_tools/third_party/oauth2client/MODIFICATIONS.diff +0 -66
- data/vendor/depot_tools/third_party/oauth2client/README.chromium +0 -15
- data/vendor/depot_tools/third_party/oauth2client/__init__.py +0 -5
- data/vendor/depot_tools/third_party/oauth2client/anyjson.py +0 -32
- data/vendor/depot_tools/third_party/oauth2client/appengine.py +0 -963
- data/vendor/depot_tools/third_party/oauth2client/client.py +0 -1363
- data/vendor/depot_tools/third_party/oauth2client/clientsecrets.py +0 -153
- data/vendor/depot_tools/third_party/oauth2client/crypt.py +0 -377
- data/vendor/depot_tools/third_party/oauth2client/django_orm.py +0 -134
- data/vendor/depot_tools/third_party/oauth2client/file.py +0 -124
- data/vendor/depot_tools/third_party/oauth2client/gce.py +0 -90
- data/vendor/depot_tools/third_party/oauth2client/keyring_storage.py +0 -109
- data/vendor/depot_tools/third_party/oauth2client/locked_file.py +0 -373
- data/vendor/depot_tools/third_party/oauth2client/multistore_file.py +0 -465
- data/vendor/depot_tools/third_party/oauth2client/old_run.py +0 -160
- data/vendor/depot_tools/third_party/oauth2client/tools.py +0 -243
- data/vendor/depot_tools/third_party/oauth2client/util.py +0 -196
- data/vendor/depot_tools/third_party/oauth2client/xsrfutil.py +0 -113
- data/vendor/depot_tools/third_party/protobuf26/README.chromium +0 -23
- data/vendor/depot_tools/third_party/protobuf26/__init__.py +0 -0
- data/vendor/depot_tools/third_party/protobuf26/compiler/__init__.py +0 -0
- data/vendor/depot_tools/third_party/protobuf26/compiler/plugin_pb2.py +0 -184
- data/vendor/depot_tools/third_party/protobuf26/descriptor.py +0 -849
- data/vendor/depot_tools/third_party/protobuf26/descriptor_database.py +0 -137
- data/vendor/depot_tools/third_party/protobuf26/descriptor_pb2.py +0 -1522
- data/vendor/depot_tools/third_party/protobuf26/descriptor_pool.py +0 -643
- data/vendor/depot_tools/third_party/protobuf26/internal/__init__.py +0 -0
- data/vendor/depot_tools/third_party/protobuf26/internal/api_implementation.py +0 -89
- data/vendor/depot_tools/third_party/protobuf26/internal/containers.py +0 -269
- data/vendor/depot_tools/third_party/protobuf26/internal/cpp_message.py +0 -663
- data/vendor/depot_tools/third_party/protobuf26/internal/decoder.py +0 -831
- data/vendor/depot_tools/third_party/protobuf26/internal/encoder.py +0 -788
- data/vendor/depot_tools/third_party/protobuf26/internal/enum_type_wrapper.py +0 -89
- data/vendor/depot_tools/third_party/protobuf26/internal/message_listener.py +0 -78
- data/vendor/depot_tools/third_party/protobuf26/internal/python_message.py +0 -1247
- data/vendor/depot_tools/third_party/protobuf26/internal/type_checkers.py +0 -328
- data/vendor/depot_tools/third_party/protobuf26/internal/wire_format.py +0 -268
- data/vendor/depot_tools/third_party/protobuf26/message.py +0 -284
- data/vendor/depot_tools/third_party/protobuf26/message_factory.py +0 -155
- data/vendor/depot_tools/third_party/protobuf26/reflection.py +0 -205
- data/vendor/depot_tools/third_party/protobuf26/service.py +0 -226
- data/vendor/depot_tools/third_party/protobuf26/service_reflection.py +0 -284
- data/vendor/depot_tools/third_party/protobuf26/symbol_database.py +0 -185
- data/vendor/depot_tools/third_party/protobuf26/text_encoding.py +0 -110
- data/vendor/depot_tools/third_party/protobuf26/text_format.py +0 -873
- data/vendor/depot_tools/third_party/pylint.py +0 -37
- data/vendor/depot_tools/third_party/pylint/LICENSE.txt +0 -340
- data/vendor/depot_tools/third_party/pylint/README.chromium +0 -30
- data/vendor/depot_tools/third_party/pylint/__init__.py +0 -46
- data/vendor/depot_tools/third_party/pylint/__main__.py +0 -3
- data/vendor/depot_tools/third_party/pylint/__pkginfo__.py +0 -80
- data/vendor/depot_tools/third_party/pylint/checkers/__init__.py +0 -123
- data/vendor/depot_tools/third_party/pylint/checkers/async.py +0 -82
- data/vendor/depot_tools/third_party/pylint/checkers/base.py +0 -2010
- data/vendor/depot_tools/third_party/pylint/checkers/classes.py +0 -1120
- data/vendor/depot_tools/third_party/pylint/checkers/design_analysis.py +0 -348
- data/vendor/depot_tools/third_party/pylint/checkers/exceptions.py +0 -369
- data/vendor/depot_tools/third_party/pylint/checkers/format.py +0 -993
- data/vendor/depot_tools/third_party/pylint/checkers/imports.py +0 -654
- data/vendor/depot_tools/third_party/pylint/checkers/logging.py +0 -258
- data/vendor/depot_tools/third_party/pylint/checkers/misc.py +0 -105
- data/vendor/depot_tools/third_party/pylint/checkers/newstyle.py +0 -169
- data/vendor/depot_tools/third_party/pylint/checkers/python3.py +0 -591
- data/vendor/depot_tools/third_party/pylint/checkers/raw_metrics.py +0 -129
- data/vendor/depot_tools/third_party/pylint/checkers/similar.py +0 -371
- data/vendor/depot_tools/third_party/pylint/checkers/spelling.py +0 -264
- data/vendor/depot_tools/third_party/pylint/checkers/stdlib.py +0 -280
- data/vendor/depot_tools/third_party/pylint/checkers/strings.py +0 -618
- data/vendor/depot_tools/third_party/pylint/checkers/typecheck.py +0 -974
- data/vendor/depot_tools/third_party/pylint/checkers/utils.py +0 -741
- data/vendor/depot_tools/third_party/pylint/checkers/variables.py +0 -1191
- data/vendor/depot_tools/third_party/pylint/config.py +0 -820
- data/vendor/depot_tools/third_party/pylint/epylint.py +0 -181
- data/vendor/depot_tools/third_party/pylint/extensions/__init__.py +0 -0
- data/vendor/depot_tools/third_party/pylint/extensions/check_docs.py +0 -311
- data/vendor/depot_tools/third_party/pylint/extensions/check_elif.py +0 -62
- data/vendor/depot_tools/third_party/pylint/graph.py +0 -179
- data/vendor/depot_tools/third_party/pylint/gui.py +0 -531
- data/vendor/depot_tools/third_party/pylint/interfaces.py +0 -102
- data/vendor/depot_tools/third_party/pylint/lint.py +0 -1381
- data/vendor/depot_tools/third_party/pylint/pyreverse/__init__.py +0 -5
- data/vendor/depot_tools/third_party/pylint/pyreverse/diadefslib.py +0 -230
- data/vendor/depot_tools/third_party/pylint/pyreverse/diagrams.py +0 -258
- data/vendor/depot_tools/third_party/pylint/pyreverse/inspector.py +0 -372
- data/vendor/depot_tools/third_party/pylint/pyreverse/main.py +0 -147
- data/vendor/depot_tools/third_party/pylint/pyreverse/utils.py +0 -210
- data/vendor/depot_tools/third_party/pylint/pyreverse/vcgutils.py +0 -198
- data/vendor/depot_tools/third_party/pylint/pyreverse/writer.py +0 -198
- data/vendor/depot_tools/third_party/pylint/reporters/__init__.py +0 -149
- data/vendor/depot_tools/third_party/pylint/reporters/guireporter.py +0 -27
- data/vendor/depot_tools/third_party/pylint/reporters/html.py +0 -108
- data/vendor/depot_tools/third_party/pylint/reporters/json.py +0 -64
- data/vendor/depot_tools/third_party/pylint/reporters/text.py +0 -237
- data/vendor/depot_tools/third_party/pylint/reporters/ureports/__init__.py +0 -106
- data/vendor/depot_tools/third_party/pylint/reporters/ureports/html_writer.py +0 -93
- data/vendor/depot_tools/third_party/pylint/reporters/ureports/nodes.py +0 -181
- data/vendor/depot_tools/third_party/pylint/reporters/ureports/text_writer.py +0 -99
- data/vendor/depot_tools/third_party/pylint/testutils.py +0 -414
- data/vendor/depot_tools/third_party/pylint/utils.py +0 -1148
- data/vendor/depot_tools/third_party/pymox/COPYING +0 -202
- data/vendor/depot_tools/third_party/pymox/MANIFEST.in +0 -5
- data/vendor/depot_tools/third_party/pymox/README +0 -56
- data/vendor/depot_tools/third_party/pymox/__init__.py +0 -0
- data/vendor/depot_tools/third_party/pymox/mox.py +0 -1643
- data/vendor/depot_tools/third_party/pymox/mox_test.py +0 -1708
- data/vendor/depot_tools/third_party/pymox/mox_test_helper.py +0 -76
- data/vendor/depot_tools/third_party/pymox/setup.py +0 -14
- data/vendor/depot_tools/third_party/pymox/stubout.py +0 -142
- data/vendor/depot_tools/third_party/pymox/stubout_test.py +0 -47
- data/vendor/depot_tools/third_party/pymox/stubout_testee.py +0 -2
- data/vendor/depot_tools/third_party/simplejson/LICENSE.txt +0 -19
- data/vendor/depot_tools/third_party/simplejson/PKG-INFO +0 -29
- data/vendor/depot_tools/third_party/simplejson/__init__.py +0 -437
- data/vendor/depot_tools/third_party/simplejson/decoder.py +0 -421
- data/vendor/depot_tools/third_party/simplejson/encoder.py +0 -501
- data/vendor/depot_tools/third_party/simplejson/ordered_dict.py +0 -119
- data/vendor/depot_tools/third_party/simplejson/scanner.py +0 -77
- data/vendor/depot_tools/third_party/simplejson/tool.py +0 -39
- data/vendor/depot_tools/third_party/upload.py +0 -2565
|
@@ -10,6 +10,7 @@ details on the presubmit API built into depot_tools.
|
|
|
10
10
|
|
|
11
11
|
import fnmatch
|
|
12
12
|
import os
|
|
13
|
+
import sys
|
|
13
14
|
|
|
14
15
|
|
|
15
16
|
# CIPD ensure manifest for checking CIPD client itself.
|
|
@@ -24,25 +25,29 @@ $VerifiedPlatform linux-mips64 linux-mips64le linux-mipsle
|
|
|
24
25
|
%s %s
|
|
25
26
|
'''
|
|
26
27
|
|
|
28
|
+
# Timeout for a test to be executed.
|
|
29
|
+
TEST_TIMEOUT_S = 330 # 5m 30s
|
|
30
|
+
|
|
31
|
+
|
|
27
32
|
|
|
28
33
|
def DepotToolsPylint(input_api, output_api):
|
|
29
34
|
"""Gather all the pylint logic into one place to make it self-contained."""
|
|
30
|
-
|
|
35
|
+
files_to_check = [
|
|
31
36
|
r'^[^/]*\.py$',
|
|
32
37
|
r'^testing_support/[^/]*\.py$',
|
|
33
38
|
r'^tests/[^/]*\.py$',
|
|
34
39
|
r'^recipe_modules/.*\.py$', # Allow recursive search in recipe modules.
|
|
35
40
|
]
|
|
36
|
-
|
|
41
|
+
files_to_skip = list(input_api.DEFAULT_FILES_TO_SKIP)
|
|
37
42
|
if os.path.exists('.gitignore'):
|
|
38
43
|
with open('.gitignore') as fh:
|
|
39
44
|
lines = [l.strip() for l in fh.readlines()]
|
|
40
|
-
|
|
45
|
+
files_to_skip.extend([fnmatch.translate(l) for l in lines if
|
|
41
46
|
l and not l.startswith('#')])
|
|
42
47
|
if os.path.exists('.git/info/exclude'):
|
|
43
48
|
with open('.git/info/exclude') as fh:
|
|
44
49
|
lines = [l.strip() for l in fh.readlines()]
|
|
45
|
-
|
|
50
|
+
files_to_skip.extend([fnmatch.translate(l) for l in lines if
|
|
46
51
|
l and not l.startswith('#')])
|
|
47
52
|
disabled_warnings = [
|
|
48
53
|
'R0401', # Cyclic import
|
|
@@ -51,22 +56,33 @@ def DepotToolsPylint(input_api, output_api):
|
|
|
51
56
|
return input_api.canned_checks.GetPylint(
|
|
52
57
|
input_api,
|
|
53
58
|
output_api,
|
|
54
|
-
|
|
55
|
-
|
|
59
|
+
files_to_check=files_to_check,
|
|
60
|
+
files_to_skip=files_to_skip,
|
|
56
61
|
disabled_warnings=disabled_warnings)
|
|
57
62
|
|
|
58
63
|
|
|
59
|
-
def CommonChecks(input_api, output_api,
|
|
64
|
+
def CommonChecks(input_api, output_api, tests_to_skip_list, run_on_python3):
|
|
65
|
+
input_api.SetTimeout(TEST_TIMEOUT_S)
|
|
66
|
+
|
|
60
67
|
results = []
|
|
61
68
|
results.extend(input_api.canned_checks.CheckOwners(input_api, output_api))
|
|
62
69
|
results.extend(input_api.canned_checks.CheckOwnersFormat(
|
|
63
70
|
input_api, output_api))
|
|
71
|
+
results.extend(input_api.canned_checks.CheckJsonParses(
|
|
72
|
+
input_api, output_api))
|
|
64
73
|
|
|
65
74
|
# Run only selected tests on Windows.
|
|
66
|
-
|
|
75
|
+
test_to_run_list = [r'.*test\.py$']
|
|
67
76
|
if input_api.platform.startswith(('cygwin', 'win32')):
|
|
68
77
|
print('Warning: skipping most unit tests on Windows')
|
|
69
|
-
|
|
78
|
+
tests_to_skip_list = [
|
|
79
|
+
r'.*auth_test\.py$',
|
|
80
|
+
r'.*git_common_test\.py$',
|
|
81
|
+
r'.*git_hyper_blame_test\.py$',
|
|
82
|
+
r'.*git_map_test\.py$',
|
|
83
|
+
r'.*ninjalog_uploader_test\.py$',
|
|
84
|
+
r'.*recipes_test\.py$',
|
|
85
|
+
]
|
|
70
86
|
|
|
71
87
|
# TODO(maruel): Make sure at least one file is modified first.
|
|
72
88
|
# TODO(maruel): If only tests are modified, only run them.
|
|
@@ -75,8 +91,9 @@ def CommonChecks(input_api, output_api, tests_to_black_list):
|
|
|
75
91
|
input_api,
|
|
76
92
|
output_api,
|
|
77
93
|
'tests',
|
|
78
|
-
|
|
79
|
-
|
|
94
|
+
allowlist=test_to_run_list,
|
|
95
|
+
blocklist=tests_to_skip_list,
|
|
96
|
+
run_on_python3=run_on_python3))
|
|
80
97
|
|
|
81
98
|
# Validate CIPD manifests.
|
|
82
99
|
root = input_api.os_path.normpath(
|
|
@@ -84,8 +101,8 @@ def CommonChecks(input_api, output_api, tests_to_black_list):
|
|
|
84
101
|
rel_file = lambda rel: input_api.os_path.join(root, rel)
|
|
85
102
|
cipd_manifests = set(rel_file(input_api.os_path.join(*x)) for x in (
|
|
86
103
|
('cipd_manifest.txt',),
|
|
87
|
-
('bootstrap', '
|
|
88
|
-
('bootstrap', '
|
|
104
|
+
('bootstrap', 'manifest.txt'),
|
|
105
|
+
('bootstrap', 'manifest_bleeding_edge.txt'),
|
|
89
106
|
|
|
90
107
|
# Also generate a file for the cipd client itself.
|
|
91
108
|
('cipd_client_version',),
|
|
@@ -114,19 +131,19 @@ def CommonChecks(input_api, output_api, tests_to_black_list):
|
|
|
114
131
|
|
|
115
132
|
def CheckChangeOnUpload(input_api, output_api):
|
|
116
133
|
# Do not run integration tests on upload since they are way too slow.
|
|
117
|
-
|
|
134
|
+
tests_to_skip_list = [
|
|
118
135
|
r'^checkout_test\.py$',
|
|
119
136
|
r'^cipd_bootstrap_test\.py$',
|
|
120
137
|
r'^gclient_smoketest\.py$',
|
|
121
|
-
r'^scm_unittest\.py$',
|
|
122
|
-
r'^subprocess2_test\.py$',
|
|
123
138
|
]
|
|
124
|
-
|
|
139
|
+
# TODO(ehmaldonado): Run Python 3 tests on upload once Python 3 is
|
|
140
|
+
# bootstrapped on Linux and Mac.
|
|
141
|
+
return CommonChecks(input_api, output_api, tests_to_skip_list, False)
|
|
125
142
|
|
|
126
143
|
|
|
127
144
|
def CheckChangeOnCommit(input_api, output_api):
|
|
128
145
|
output = []
|
|
129
|
-
output.extend(CommonChecks(input_api, output_api, []))
|
|
146
|
+
output.extend(CommonChecks(input_api, output_api, [], True))
|
|
130
147
|
output.extend(input_api.canned_checks.CheckDoNotSubmit(
|
|
131
148
|
input_api,
|
|
132
149
|
output_api))
|
|
@@ -6,20 +6,6 @@ git but unfamiliar with the code review process supported by Rietveld and
|
|
|
6
6
|
Gerrit.
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
## Rietveld concepts and terms
|
|
10
|
-
|
|
11
|
-
A Rietveld review is for discussion of a single change or patch. You upload a
|
|
12
|
-
proposed change, the reviewer comments on your change, and then you can upload a
|
|
13
|
-
revised version of your change. Rietveld stores the history of uploaded patches
|
|
14
|
-
as well as the comments, and can compute diffs in between these patches. The
|
|
15
|
-
history of a patch is very much like a small branch in git, but since Rietveld
|
|
16
|
-
is VCS-agnostic, the concepts don't map perfectly. The identifier for a single
|
|
17
|
-
review thread including patches and comments in Rietveld is called an **issue**.
|
|
18
|
-
|
|
19
|
-
Rietveld provides a basic uploader that understands git. This program is used by
|
|
20
|
-
git-cl, and is included in the git-cl repo as upload.py.
|
|
21
|
-
|
|
22
|
-
|
|
23
9
|
## Basic interaction with git
|
|
24
10
|
|
|
25
11
|
The fundamental problem you encounter when you try to mix git and code review is
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# Copyright (c)
|
|
1
|
+
# Copyright (c) 2019 The Chromium Authors. All rights reserved.
|
|
2
2
|
# Use of this source code is governed by a BSD-style license that can be
|
|
3
3
|
# found in the LICENSE file.
|
|
4
4
|
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
'WATCHLISTS': {
|
|
20
20
|
'this_file': [],
|
|
21
21
|
'depot_tools': [
|
|
22
|
-
'
|
|
22
|
+
'chops-source-team+depot_tools@google.com',
|
|
23
23
|
],
|
|
24
24
|
},
|
|
25
25
|
|
data/vendor/depot_tools/auth.py
CHANGED
|
@@ -4,46 +4,18 @@
|
|
|
4
4
|
|
|
5
5
|
"""Google OAuth2 related functions."""
|
|
6
6
|
|
|
7
|
-
import
|
|
7
|
+
from __future__ import print_function
|
|
8
|
+
|
|
8
9
|
import collections
|
|
9
10
|
import datetime
|
|
10
11
|
import functools
|
|
11
|
-
import
|
|
12
|
+
import httplib2
|
|
12
13
|
import json
|
|
13
14
|
import logging
|
|
14
|
-
import optparse
|
|
15
15
|
import os
|
|
16
|
-
|
|
17
|
-
import
|
|
18
|
-
|
|
19
|
-
import time
|
|
20
|
-
import urllib
|
|
21
|
-
import urlparse
|
|
22
|
-
import webbrowser
|
|
23
|
-
|
|
24
|
-
from third_party import httplib2
|
|
25
|
-
from third_party.oauth2client import client
|
|
26
|
-
from third_party.oauth2client import multistore_file
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
# depot_tools/.
|
|
30
|
-
DEPOT_TOOLS_DIR = os.path.dirname(os.path.abspath(__file__))
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
# Google OAuth2 clients always have a secret, even if the client is an installed
|
|
34
|
-
# application/utility such as this. Of course, in such cases the "secret" is
|
|
35
|
-
# actually publicly known; security depends entirely on the secrecy of refresh
|
|
36
|
-
# tokens, which effectively become bearer tokens. An attacker can impersonate
|
|
37
|
-
# service's identity in OAuth2 flow. But that's generally fine as long as a list
|
|
38
|
-
# of allowed redirect_uri's associated with client_id is limited to 'localhost'
|
|
39
|
-
# or 'urn:ietf:wg:oauth:2.0:oob'. In that case attacker needs some process
|
|
40
|
-
# running on user's machine to successfully complete the flow and grab refresh
|
|
41
|
-
# token. When you have a malicious code running on your machine, you're screwed
|
|
42
|
-
# anyway.
|
|
43
|
-
# This particular set is managed by API Console project "chrome-infra-auth".
|
|
44
|
-
OAUTH_CLIENT_ID = (
|
|
45
|
-
'446450136466-2hr92jrq8e6i4tnsa56b52vacp7t3936.apps.googleusercontent.com')
|
|
46
|
-
OAUTH_CLIENT_SECRET = 'uBfbay2KCy9t4QveJ-dOqHtp'
|
|
16
|
+
|
|
17
|
+
import subprocess2
|
|
18
|
+
|
|
47
19
|
|
|
48
20
|
# This is what most GAE apps require for authentication.
|
|
49
21
|
OAUTH_SCOPE_EMAIL = 'https://www.googleapis.com/auth/userinfo.email'
|
|
@@ -52,23 +24,10 @@ OAUTH_SCOPE_GERRIT = 'https://www.googleapis.com/auth/gerritcodereview'
|
|
|
52
24
|
# Deprecated. Use OAUTH_SCOPE_EMAIL instead.
|
|
53
25
|
OAUTH_SCOPES = OAUTH_SCOPE_EMAIL
|
|
54
26
|
|
|
55
|
-
# Path to a file with cached OAuth2 credentials used by default relative to the
|
|
56
|
-
# home dir (see _get_token_cache_path). It should be a safe location accessible
|
|
57
|
-
# only to a current user: knowing content of this file is roughly equivalent to
|
|
58
|
-
# knowing account password. Single file can hold multiple independent tokens
|
|
59
|
-
# identified by token_cache_key (see Authenticator).
|
|
60
|
-
OAUTH_TOKENS_CACHE = '.depot_tools_oauth2_tokens'
|
|
61
27
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
AuthConfig = collections.namedtuple('AuthConfig', [
|
|
66
|
-
'use_oauth2', # deprecated, will be always True
|
|
67
|
-
'save_cookies', # deprecated, will be removed
|
|
68
|
-
'use_local_webserver',
|
|
69
|
-
'webserver_port',
|
|
70
|
-
'refresh_token_json',
|
|
71
|
-
])
|
|
28
|
+
# Mockable datetime.datetime.utcnow for testing.
|
|
29
|
+
def datetime_now():
|
|
30
|
+
return datetime.datetime.utcnow()
|
|
72
31
|
|
|
73
32
|
|
|
74
33
|
# OAuth access token with its expiration time (UTC datetime or None if unknown).
|
|
@@ -77,479 +36,82 @@ class AccessToken(collections.namedtuple('AccessToken', [
|
|
|
77
36
|
'expires_at',
|
|
78
37
|
])):
|
|
79
38
|
|
|
80
|
-
def needs_refresh(self
|
|
39
|
+
def needs_refresh(self):
|
|
81
40
|
"""True if this AccessToken should be refreshed."""
|
|
82
41
|
if self.expires_at is not None:
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
now += datetime.timedelta(seconds=180)
|
|
86
|
-
return now >= self.expires_at
|
|
42
|
+
# Allow 30s of clock skew between client and backend.
|
|
43
|
+
return datetime_now() + datetime.timedelta(seconds=30) >= self.expires_at
|
|
87
44
|
# Token without expiration time never expires.
|
|
88
45
|
return False
|
|
89
46
|
|
|
90
47
|
|
|
91
|
-
|
|
92
|
-
RefreshToken = collections.namedtuple('RefreshToken', [
|
|
93
|
-
'client_id',
|
|
94
|
-
'client_secret',
|
|
95
|
-
'refresh_token',
|
|
96
|
-
])
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
class AuthenticationError(Exception):
|
|
100
|
-
"""Raised on errors related to authentication."""
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
class LoginRequiredError(AuthenticationError):
|
|
48
|
+
class LoginRequiredError(Exception):
|
|
104
49
|
"""Interaction with the user is required to authenticate."""
|
|
105
50
|
|
|
106
|
-
def __init__(self,
|
|
107
|
-
# HACK(vadimsh): It is assumed here that the token cache key is a hostname.
|
|
51
|
+
def __init__(self, scopes=OAUTH_SCOPE_EMAIL):
|
|
108
52
|
msg = (
|
|
109
53
|
'You are not logged in. Please login first by running:\n'
|
|
110
|
-
'
|
|
54
|
+
' luci-auth login -scopes %s' % scopes)
|
|
111
55
|
super(LoginRequiredError, self).__init__(msg)
|
|
112
56
|
|
|
113
57
|
|
|
114
|
-
class LuciContextAuthError(Exception):
|
|
115
|
-
"""Raised on errors related to unsuccessful attempts to load LUCI_CONTEXT"""
|
|
116
|
-
|
|
117
|
-
def __init__(self, msg, exc=None):
|
|
118
|
-
if exc is None:
|
|
119
|
-
logging.error(msg)
|
|
120
|
-
else:
|
|
121
|
-
logging.exception(msg)
|
|
122
|
-
msg = '%s: %s' % (msg, exc)
|
|
123
|
-
super(LuciContextAuthError, self).__init__(msg)
|
|
124
|
-
|
|
125
|
-
|
|
126
58
|
def has_luci_context_local_auth():
|
|
127
|
-
"""Returns whether LUCI_CONTEXT should be used for ambient authentication.
|
|
128
|
-
"""
|
|
129
|
-
try:
|
|
130
|
-
params = _get_luci_context_local_auth_params()
|
|
131
|
-
except LuciContextAuthError:
|
|
132
|
-
return False
|
|
133
|
-
if params is None:
|
|
134
|
-
return False
|
|
135
|
-
return bool(params.default_account_id)
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
def get_luci_context_access_token(scopes=OAUTH_SCOPE_EMAIL):
|
|
139
|
-
"""Returns a valid AccessToken from the local LUCI context auth server.
|
|
140
|
-
|
|
141
|
-
Adapted from
|
|
142
|
-
https://chromium.googlesource.com/infra/luci/luci-py/+/master/client/libs/luci_context/luci_context.py
|
|
143
|
-
See the link above for more details.
|
|
144
|
-
|
|
145
|
-
Returns:
|
|
146
|
-
AccessToken if LUCI_CONTEXT is present and attempt to load it is successful.
|
|
147
|
-
None if LUCI_CONTEXT is absent.
|
|
148
|
-
|
|
149
|
-
Raises:
|
|
150
|
-
LuciContextAuthError if LUCI_CONTEXT is present, but there was a failure
|
|
151
|
-
obtaining its access token.
|
|
152
|
-
"""
|
|
153
|
-
params = _get_luci_context_local_auth_params()
|
|
154
|
-
if params is None:
|
|
155
|
-
return None
|
|
156
|
-
return _get_luci_context_access_token(
|
|
157
|
-
params, datetime.datetime.utcnow(), scopes)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
_LuciContextLocalAuthParams = collections.namedtuple(
|
|
161
|
-
'_LuciContextLocalAuthParams', [
|
|
162
|
-
'default_account_id',
|
|
163
|
-
'secret',
|
|
164
|
-
'rpc_port',
|
|
165
|
-
])
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
def _cache_thread_safe(f):
|
|
169
|
-
"""Decorator caching result of nullary function in thread-safe way."""
|
|
170
|
-
lock = threading.Lock()
|
|
171
|
-
cache = []
|
|
172
|
-
|
|
173
|
-
@functools.wraps(f)
|
|
174
|
-
def caching_wrapper():
|
|
175
|
-
if not cache:
|
|
176
|
-
with lock:
|
|
177
|
-
if not cache:
|
|
178
|
-
cache.append(f())
|
|
179
|
-
return cache[0]
|
|
180
|
-
|
|
181
|
-
# Allow easy way to clear cache, particularly useful in tests.
|
|
182
|
-
caching_wrapper.clear_cache = lambda: cache.pop() if cache else None
|
|
183
|
-
return caching_wrapper
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
@_cache_thread_safe
|
|
187
|
-
def _get_luci_context_local_auth_params():
|
|
188
|
-
"""Returns local auth parameters if local auth is configured else None.
|
|
189
|
-
|
|
190
|
-
Raises LuciContextAuthError on unexpected failures.
|
|
191
|
-
"""
|
|
59
|
+
"""Returns whether LUCI_CONTEXT should be used for ambient authentication."""
|
|
192
60
|
ctx_path = os.environ.get('LUCI_CONTEXT')
|
|
193
61
|
if not ctx_path:
|
|
194
|
-
return
|
|
195
|
-
ctx_path = ctx_path.decode(sys.getfilesystemencoding())
|
|
196
|
-
try:
|
|
197
|
-
loaded = _load_luci_context(ctx_path)
|
|
198
|
-
except (OSError, IOError, ValueError) as e:
|
|
199
|
-
raise LuciContextAuthError('Failed to open, read or decode LUCI_CONTEXT', e)
|
|
200
|
-
try:
|
|
201
|
-
local_auth = loaded.get('local_auth')
|
|
202
|
-
except AttributeError as e:
|
|
203
|
-
raise LuciContextAuthError('LUCI_CONTEXT not in proper format', e)
|
|
204
|
-
if local_auth is None:
|
|
205
|
-
logging.debug('LUCI_CONTEXT configured w/o local auth')
|
|
206
|
-
return None
|
|
207
|
-
try:
|
|
208
|
-
return _LuciContextLocalAuthParams(
|
|
209
|
-
default_account_id=local_auth.get('default_account_id'),
|
|
210
|
-
secret=local_auth.get('secret'),
|
|
211
|
-
rpc_port=int(local_auth.get('rpc_port')))
|
|
212
|
-
except (AttributeError, ValueError) as e:
|
|
213
|
-
raise LuciContextAuthError('local_auth config malformed', e)
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
def _load_luci_context(ctx_path):
|
|
217
|
-
# Kept separate for test mocking.
|
|
218
|
-
with open(ctx_path) as f:
|
|
219
|
-
return json.load(f)
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
def _get_luci_context_access_token(params, now, scopes=OAUTH_SCOPE_EMAIL):
|
|
223
|
-
# No account, local_auth shouldn't be used.
|
|
224
|
-
if not params.default_account_id:
|
|
225
|
-
return None
|
|
226
|
-
if not params.secret:
|
|
227
|
-
raise LuciContextAuthError('local_auth: no secret')
|
|
228
|
-
|
|
229
|
-
logging.debug('local_auth: requesting an access token for account "%s"',
|
|
230
|
-
params.default_account_id)
|
|
231
|
-
http = httplib2.Http()
|
|
232
|
-
host = '127.0.0.1:%d' % params.rpc_port
|
|
233
|
-
resp, content = http.request(
|
|
234
|
-
uri='http://%s/rpc/LuciLocalAuthService.GetOAuthToken' % host,
|
|
235
|
-
method='POST',
|
|
236
|
-
body=json.dumps({
|
|
237
|
-
'account_id': params.default_account_id,
|
|
238
|
-
'scopes': scopes.split(' '),
|
|
239
|
-
'secret': params.secret,
|
|
240
|
-
}),
|
|
241
|
-
headers={'Content-Type': 'application/json'})
|
|
242
|
-
if resp.status != 200:
|
|
243
|
-
raise LuciContextAuthError(
|
|
244
|
-
'local_auth: Failed to grab access token from '
|
|
245
|
-
'LUCI context server with status %d: %r' % (resp.status, content))
|
|
62
|
+
return False
|
|
246
63
|
try:
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
except (AttributeError, ValueError) as e:
|
|
253
|
-
raise LuciContextAuthError('Unexpected access token response format', e)
|
|
254
|
-
if error_code:
|
|
255
|
-
raise LuciContextAuthError(
|
|
256
|
-
'Error %d in retrieving access token: %s', error_code, error_message)
|
|
257
|
-
if not access_token:
|
|
258
|
-
raise LuciContextAuthError(
|
|
259
|
-
'No access token returned from LUCI context server')
|
|
260
|
-
expiry_dt = None
|
|
261
|
-
if expiry:
|
|
262
|
-
try:
|
|
263
|
-
expiry_dt = datetime.datetime.utcfromtimestamp(expiry)
|
|
264
|
-
logging.debug(
|
|
265
|
-
'local_auth: got an access token for '
|
|
266
|
-
'account "%s" that expires in %d sec',
|
|
267
|
-
params.default_account_id, (expiry_dt - now).total_seconds())
|
|
268
|
-
except (TypeError, ValueError) as e:
|
|
269
|
-
raise LuciContextAuthError('Invalid expiry in returned token', e)
|
|
270
|
-
else:
|
|
271
|
-
logging.debug(
|
|
272
|
-
'local auth: got an access token for account "%s" that does not expire',
|
|
273
|
-
params.default_account_id)
|
|
274
|
-
access_token = AccessToken(access_token, expiry_dt)
|
|
275
|
-
if access_token.needs_refresh(now=now):
|
|
276
|
-
raise LuciContextAuthError('Received access token is already expired')
|
|
277
|
-
return access_token
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
def make_auth_config(
|
|
281
|
-
use_oauth2=None,
|
|
282
|
-
save_cookies=None,
|
|
283
|
-
use_local_webserver=None,
|
|
284
|
-
webserver_port=None,
|
|
285
|
-
refresh_token_json=None):
|
|
286
|
-
"""Returns new instance of AuthConfig.
|
|
287
|
-
|
|
288
|
-
If some config option is None, it will be set to a reasonable default value.
|
|
289
|
-
This function also acts as an authoritative place for default values of
|
|
290
|
-
corresponding command line options.
|
|
291
|
-
"""
|
|
292
|
-
default = lambda val, d: val if val is not None else d
|
|
293
|
-
return AuthConfig(
|
|
294
|
-
default(use_oauth2, True),
|
|
295
|
-
default(save_cookies, True),
|
|
296
|
-
default(use_local_webserver, not _is_headless()),
|
|
297
|
-
default(webserver_port, 8090),
|
|
298
|
-
default(refresh_token_json, ''))
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
def add_auth_options(parser, default_config=None):
|
|
302
|
-
"""Appends OAuth related options to OptionParser."""
|
|
303
|
-
default_config = default_config or make_auth_config()
|
|
304
|
-
parser.auth_group = optparse.OptionGroup(parser, 'Auth options')
|
|
305
|
-
parser.add_option_group(parser.auth_group)
|
|
306
|
-
|
|
307
|
-
# OAuth2 vs password switch.
|
|
308
|
-
auth_default = 'use OAuth2' if default_config.use_oauth2 else 'use password'
|
|
309
|
-
parser.auth_group.add_option(
|
|
310
|
-
'--oauth2',
|
|
311
|
-
action='store_true',
|
|
312
|
-
dest='use_oauth2',
|
|
313
|
-
default=default_config.use_oauth2,
|
|
314
|
-
help='Use OAuth 2.0 instead of a password. [default: %s]' % auth_default)
|
|
315
|
-
parser.auth_group.add_option(
|
|
316
|
-
'--no-oauth2',
|
|
317
|
-
action='store_false',
|
|
318
|
-
dest='use_oauth2',
|
|
319
|
-
default=default_config.use_oauth2,
|
|
320
|
-
help='Use password instead of OAuth 2.0. [default: %s]' % auth_default)
|
|
321
|
-
|
|
322
|
-
# Password related options, deprecated.
|
|
323
|
-
parser.auth_group.add_option(
|
|
324
|
-
'--no-cookies',
|
|
325
|
-
action='store_false',
|
|
326
|
-
dest='save_cookies',
|
|
327
|
-
default=default_config.save_cookies,
|
|
328
|
-
help='Do not save authentication cookies to local disk.')
|
|
329
|
-
|
|
330
|
-
# OAuth2 related options.
|
|
331
|
-
parser.auth_group.add_option(
|
|
332
|
-
'--auth-no-local-webserver',
|
|
333
|
-
action='store_false',
|
|
334
|
-
dest='use_local_webserver',
|
|
335
|
-
default=default_config.use_local_webserver,
|
|
336
|
-
help='Do not run a local web server when performing OAuth2 login flow.')
|
|
337
|
-
parser.auth_group.add_option(
|
|
338
|
-
'--auth-host-port',
|
|
339
|
-
type=int,
|
|
340
|
-
default=default_config.webserver_port,
|
|
341
|
-
help='Port a local web server should listen on. Used only if '
|
|
342
|
-
'--auth-no-local-webserver is not set. [default: %default]')
|
|
343
|
-
parser.auth_group.add_option(
|
|
344
|
-
'--auth-refresh-token-json',
|
|
345
|
-
default=default_config.refresh_token_json,
|
|
346
|
-
help='Path to a JSON file with role account refresh token to use.')
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
def extract_auth_config_from_options(options):
|
|
350
|
-
"""Given OptionParser parsed options, extracts AuthConfig from it.
|
|
351
|
-
|
|
352
|
-
OptionParser should be populated with auth options by 'add_auth_options'.
|
|
353
|
-
"""
|
|
354
|
-
return make_auth_config(
|
|
355
|
-
use_oauth2=options.use_oauth2,
|
|
356
|
-
save_cookies=False if options.use_oauth2 else options.save_cookies,
|
|
357
|
-
use_local_webserver=options.use_local_webserver,
|
|
358
|
-
webserver_port=options.auth_host_port,
|
|
359
|
-
refresh_token_json=options.auth_refresh_token_json)
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
def auth_config_to_command_options(auth_config):
|
|
363
|
-
"""AuthConfig -> list of strings with command line options.
|
|
364
|
-
|
|
365
|
-
Omits options that are set to default values.
|
|
366
|
-
"""
|
|
367
|
-
if not auth_config:
|
|
368
|
-
return []
|
|
369
|
-
defaults = make_auth_config()
|
|
370
|
-
opts = []
|
|
371
|
-
if auth_config.use_oauth2 != defaults.use_oauth2:
|
|
372
|
-
opts.append('--oauth2' if auth_config.use_oauth2 else '--no-oauth2')
|
|
373
|
-
if auth_config.save_cookies != auth_config.save_cookies:
|
|
374
|
-
if not auth_config.save_cookies:
|
|
375
|
-
opts.append('--no-cookies')
|
|
376
|
-
if auth_config.use_local_webserver != defaults.use_local_webserver:
|
|
377
|
-
if not auth_config.use_local_webserver:
|
|
378
|
-
opts.append('--auth-no-local-webserver')
|
|
379
|
-
if auth_config.webserver_port != defaults.webserver_port:
|
|
380
|
-
opts.extend(['--auth-host-port', str(auth_config.webserver_port)])
|
|
381
|
-
if auth_config.refresh_token_json != defaults.refresh_token_json:
|
|
382
|
-
opts.extend([
|
|
383
|
-
'--auth-refresh-token-json', str(auth_config.refresh_token_json)])
|
|
384
|
-
return opts
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
def get_authenticator_for_host(hostname, config, scopes=OAUTH_SCOPE_EMAIL):
|
|
388
|
-
"""Returns Authenticator instance to access given host.
|
|
389
|
-
|
|
390
|
-
Args:
|
|
391
|
-
hostname: a naked hostname or http(s)://<hostname>[/] URL. Used to derive
|
|
392
|
-
a cache key for token cache.
|
|
393
|
-
config: AuthConfig instance.
|
|
394
|
-
scopes: space separated oauth scopes. Defaults to OAUTH_SCOPE_EMAIL.
|
|
395
|
-
|
|
396
|
-
Returns:
|
|
397
|
-
Authenticator object.
|
|
398
|
-
|
|
399
|
-
Raises:
|
|
400
|
-
AuthenticationError if hostname is invalid.
|
|
401
|
-
"""
|
|
402
|
-
hostname = hostname.lower().rstrip('/')
|
|
403
|
-
# Append some scheme, otherwise urlparse puts hostname into parsed.path.
|
|
404
|
-
if '://' not in hostname:
|
|
405
|
-
hostname = 'https://' + hostname
|
|
406
|
-
parsed = urlparse.urlparse(hostname)
|
|
407
|
-
|
|
408
|
-
if parsed.path or parsed.params or parsed.query or parsed.fragment:
|
|
409
|
-
raise AuthenticationError(
|
|
410
|
-
'Expecting a hostname or root host URL, got %s instead' % hostname)
|
|
411
|
-
return Authenticator(parsed.netloc, config, scopes)
|
|
64
|
+
with open(ctx_path) as f:
|
|
65
|
+
loaded = json.load(f)
|
|
66
|
+
except (OSError, IOError, ValueError):
|
|
67
|
+
return False
|
|
68
|
+
return loaded.get('local_auth', {}).get('default_account_id') is not None
|
|
412
69
|
|
|
413
70
|
|
|
414
71
|
class Authenticator(object):
|
|
415
72
|
"""Object that knows how to refresh access tokens when needed.
|
|
416
73
|
|
|
417
74
|
Args:
|
|
418
|
-
|
|
419
|
-
to keep the tokens. See hostname_to_token_cache_key.
|
|
420
|
-
config: AuthConfig object that holds authentication configuration.
|
|
75
|
+
scopes: space separated oauth scopes. Defaults to OAUTH_SCOPE_EMAIL.
|
|
421
76
|
"""
|
|
422
77
|
|
|
423
|
-
def __init__(self,
|
|
424
|
-
assert isinstance(config, AuthConfig)
|
|
425
|
-
assert config.use_oauth2
|
|
78
|
+
def __init__(self, scopes=OAUTH_SCOPE_EMAIL):
|
|
426
79
|
self._access_token = None
|
|
427
|
-
self._config = config
|
|
428
|
-
self._lock = threading.Lock()
|
|
429
|
-
self._token_cache_key = token_cache_key
|
|
430
|
-
self._external_token = None
|
|
431
80
|
self._scopes = scopes
|
|
432
|
-
if config.refresh_token_json:
|
|
433
|
-
self._external_token = _read_refresh_token_json(config.refresh_token_json)
|
|
434
|
-
logging.debug('Using auth config %r', config)
|
|
435
|
-
|
|
436
|
-
def login(self):
|
|
437
|
-
"""Performs interactive login flow if necessary.
|
|
438
|
-
|
|
439
|
-
Raises:
|
|
440
|
-
AuthenticationError on error or if interrupted.
|
|
441
|
-
"""
|
|
442
|
-
if self._external_token:
|
|
443
|
-
raise AuthenticationError(
|
|
444
|
-
'Can\'t run login flow when using --auth-refresh-token-json.')
|
|
445
|
-
return self.get_access_token(
|
|
446
|
-
force_refresh=True, allow_user_interaction=True)
|
|
447
|
-
|
|
448
|
-
def logout(self):
|
|
449
|
-
"""Revokes the refresh token and deletes it from the cache.
|
|
450
|
-
|
|
451
|
-
Returns True if had some credentials cached.
|
|
452
|
-
"""
|
|
453
|
-
with self._lock:
|
|
454
|
-
self._access_token = None
|
|
455
|
-
storage = self._get_storage()
|
|
456
|
-
credentials = storage.get()
|
|
457
|
-
had_creds = bool(credentials)
|
|
458
|
-
if credentials and credentials.refresh_token and credentials.revoke_uri:
|
|
459
|
-
try:
|
|
460
|
-
credentials.revoke(httplib2.Http())
|
|
461
|
-
except client.TokenRevokeError as e:
|
|
462
|
-
logging.warning('Failed to revoke refresh token: %s', e)
|
|
463
|
-
storage.delete()
|
|
464
|
-
return had_creds
|
|
465
81
|
|
|
466
82
|
def has_cached_credentials(self):
|
|
467
|
-
"""Returns True if
|
|
468
|
-
|
|
469
|
-
Doesn't make network calls.
|
|
83
|
+
"""Returns True if credentials can be obtained.
|
|
470
84
|
|
|
471
|
-
If returns False, get_access_token() later will ask for interactive
|
|
472
|
-
raising LoginRequiredError.
|
|
85
|
+
If returns False, get_access_token() later will probably ask for interactive
|
|
86
|
+
login by raising LoginRequiredError.
|
|
473
87
|
|
|
474
|
-
If returns True,
|
|
475
|
-
login, though it is not guaranteed, since cached token can be already
|
|
476
|
-
revoked and there's no way to figure this out without actually trying to use
|
|
477
|
-
it.
|
|
88
|
+
If returns True, get_access_token() won't ask for interactive login.
|
|
478
89
|
"""
|
|
479
|
-
|
|
480
|
-
return bool(self._get_cached_credentials())
|
|
90
|
+
return bool(self._get_luci_auth_token())
|
|
481
91
|
|
|
482
|
-
def get_access_token(self
|
|
483
|
-
use_local_auth=True):
|
|
92
|
+
def get_access_token(self):
|
|
484
93
|
"""Returns AccessToken, refreshing it if necessary.
|
|
485
94
|
|
|
486
|
-
Args:
|
|
487
|
-
force_refresh: forcefully refresh access token even if it is not expired.
|
|
488
|
-
allow_user_interaction: True to enable blocking for user input if needed.
|
|
489
|
-
use_local_auth: default to local auth if needed.
|
|
490
|
-
|
|
491
95
|
Raises:
|
|
492
|
-
|
|
493
|
-
LoginRequiredError if user interaction is required, but
|
|
494
|
-
allow_user_interaction is False.
|
|
96
|
+
LoginRequiredError if user interaction is required.
|
|
495
97
|
"""
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
if not use_local_auth:
|
|
499
|
-
logging.error('Failed to create access token')
|
|
500
|
-
raise
|
|
501
|
-
try:
|
|
502
|
-
self._access_token = get_luci_context_access_token()
|
|
503
|
-
if not self._access_token:
|
|
504
|
-
logging.error('Failed to create access token')
|
|
505
|
-
raise
|
|
506
|
-
return self._access_token
|
|
507
|
-
except LuciContextAuthError:
|
|
508
|
-
logging.exception('Failed to use local auth')
|
|
509
|
-
raise exi[0], exi[1], exi[2]
|
|
510
|
-
|
|
511
|
-
with self._lock:
|
|
512
|
-
if force_refresh:
|
|
513
|
-
logging.debug('Forcing access token refresh')
|
|
514
|
-
try:
|
|
515
|
-
self._access_token = self._create_access_token(allow_user_interaction)
|
|
516
|
-
return self._access_token
|
|
517
|
-
except LoginRequiredError:
|
|
518
|
-
return get_loc_auth_tkn()
|
|
519
|
-
|
|
520
|
-
# Load from on-disk cache on a first access.
|
|
521
|
-
if not self._access_token:
|
|
522
|
-
self._access_token = self._load_access_token()
|
|
523
|
-
|
|
524
|
-
# Refresh if expired or missing.
|
|
525
|
-
if not self._access_token or self._access_token.needs_refresh():
|
|
526
|
-
# Maybe some other process already updated it, reload from the cache.
|
|
527
|
-
self._access_token = self._load_access_token()
|
|
528
|
-
# Nope, still expired, need to run the refresh flow.
|
|
529
|
-
if not self._access_token or self._access_token.needs_refresh():
|
|
530
|
-
try:
|
|
531
|
-
self._access_token = self._create_access_token(
|
|
532
|
-
allow_user_interaction)
|
|
533
|
-
except LoginRequiredError:
|
|
534
|
-
get_loc_auth_tkn()
|
|
98
|
+
if self._access_token and not self._access_token.needs_refresh():
|
|
99
|
+
return self._access_token
|
|
535
100
|
|
|
101
|
+
# Token expired or missing. Maybe some other process already updated it,
|
|
102
|
+
# reload from the cache.
|
|
103
|
+
self._access_token = self._get_luci_auth_token()
|
|
104
|
+
if self._access_token and not self._access_token.needs_refresh():
|
|
536
105
|
return self._access_token
|
|
537
106
|
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
resp, content = httplib2.Http().request(
|
|
542
|
-
uri='https://www.googleapis.com/oauth2/v2/tokeninfo?%s' % (
|
|
543
|
-
urllib.urlencode({'access_token': access_token.token})))
|
|
544
|
-
if resp.status == 200:
|
|
545
|
-
return json.loads(content)
|
|
546
|
-
raise AuthenticationError('Failed to fetch the token info: %r' % content)
|
|
107
|
+
# Nope, still expired. Needs user interaction.
|
|
108
|
+
logging.error('Failed to create access token')
|
|
109
|
+
raise LoginRequiredError(self._scopes)
|
|
547
110
|
|
|
548
111
|
def authorize(self, http):
|
|
549
112
|
"""Monkey patches authentication logic of httplib2.Http instance.
|
|
550
113
|
|
|
551
114
|
The modified http.request method will add authentication headers to each
|
|
552
|
-
request and will refresh access_tokens when a 401 is received on a
|
|
553
115
|
request.
|
|
554
116
|
|
|
555
117
|
Args:
|
|
@@ -559,7 +121,6 @@ class Authenticator(object):
|
|
|
559
121
|
A modified instance of http that was passed in.
|
|
560
122
|
"""
|
|
561
123
|
# Adapted from oauth2client.OAuth2Credentials.authorize.
|
|
562
|
-
|
|
563
124
|
request_orig = http.request
|
|
564
125
|
|
|
565
126
|
@functools.wraps(request_orig)
|
|
@@ -569,307 +130,34 @@ class Authenticator(object):
|
|
|
569
130
|
connection_type=None):
|
|
570
131
|
headers = (headers or {}).copy()
|
|
571
132
|
headers['Authorization'] = 'Bearer %s' % self.get_access_token().token
|
|
572
|
-
|
|
133
|
+
return request_orig(
|
|
573
134
|
uri, method, body, headers, redirections, connection_type)
|
|
574
|
-
if resp.status in client.REFRESH_STATUS_CODES:
|
|
575
|
-
logging.info('Refreshing due to a %s', resp.status)
|
|
576
|
-
access_token = self.get_access_token(force_refresh=True)
|
|
577
|
-
headers['Authorization'] = 'Bearer %s' % access_token.token
|
|
578
|
-
return request_orig(
|
|
579
|
-
uri, method, body, headers, redirections, connection_type)
|
|
580
|
-
else:
|
|
581
|
-
return (resp, content)
|
|
582
135
|
|
|
583
136
|
http.request = new_request
|
|
584
137
|
return http
|
|
585
138
|
|
|
586
139
|
## Private methods.
|
|
587
140
|
|
|
588
|
-
def
|
|
589
|
-
"""
|
|
590
|
-
# Do not mix cache keys for different externally provided tokens.
|
|
591
|
-
if self._external_token:
|
|
592
|
-
token_hash = hashlib.sha1(self._external_token.refresh_token).hexdigest()
|
|
593
|
-
cache_key = '%s:refresh_tok:%s' % (self._token_cache_key, token_hash)
|
|
594
|
-
else:
|
|
595
|
-
cache_key = self._token_cache_key
|
|
596
|
-
path = _get_token_cache_path()
|
|
597
|
-
logging.debug('Using token storage %r (cache key %r)', path, cache_key)
|
|
598
|
-
return multistore_file.get_credential_storage_custom_string_key(
|
|
599
|
-
path, cache_key)
|
|
600
|
-
|
|
601
|
-
def _get_cached_credentials(self):
|
|
602
|
-
"""Returns oauth2client.Credentials loaded from storage."""
|
|
603
|
-
storage = self._get_storage()
|
|
604
|
-
credentials = storage.get()
|
|
605
|
-
|
|
606
|
-
if not credentials:
|
|
607
|
-
logging.debug('No cached token')
|
|
608
|
-
else:
|
|
609
|
-
_log_credentials_info('cached token', credentials)
|
|
610
|
-
|
|
611
|
-
# Is using --auth-refresh-token-json?
|
|
612
|
-
if self._external_token:
|
|
613
|
-
# Cached credentials are valid and match external token -> use them. It is
|
|
614
|
-
# important to reuse credentials from the storage because they contain
|
|
615
|
-
# cached access token.
|
|
616
|
-
valid = (
|
|
617
|
-
credentials and not credentials.invalid and
|
|
618
|
-
credentials.refresh_token == self._external_token.refresh_token and
|
|
619
|
-
credentials.client_id == self._external_token.client_id and
|
|
620
|
-
credentials.client_secret == self._external_token.client_secret)
|
|
621
|
-
if valid:
|
|
622
|
-
logging.debug('Cached credentials match external refresh token')
|
|
623
|
-
return credentials
|
|
624
|
-
# Construct new credentials from externally provided refresh token,
|
|
625
|
-
# associate them with cache storage (so that access_token will be placed
|
|
626
|
-
# in the cache later too).
|
|
627
|
-
logging.debug('Putting external refresh token into the cache')
|
|
628
|
-
credentials = client.OAuth2Credentials(
|
|
629
|
-
access_token=None,
|
|
630
|
-
client_id=self._external_token.client_id,
|
|
631
|
-
client_secret=self._external_token.client_secret,
|
|
632
|
-
refresh_token=self._external_token.refresh_token,
|
|
633
|
-
token_expiry=None,
|
|
634
|
-
token_uri='https://accounts.google.com/o/oauth2/token',
|
|
635
|
-
user_agent=None,
|
|
636
|
-
revoke_uri=None)
|
|
637
|
-
credentials.set_store(storage)
|
|
638
|
-
storage.put(credentials)
|
|
639
|
-
return credentials
|
|
640
|
-
|
|
641
|
-
# Not using external refresh token -> return whatever is cached.
|
|
642
|
-
return credentials if (credentials and not credentials.invalid) else None
|
|
643
|
-
|
|
644
|
-
def _load_access_token(self):
|
|
645
|
-
"""Returns cached AccessToken if it is not expired yet."""
|
|
646
|
-
logging.debug('Reloading access token from cache')
|
|
647
|
-
creds = self._get_cached_credentials()
|
|
648
|
-
if not creds or not creds.access_token or creds.access_token_expired:
|
|
649
|
-
logging.debug('Access token is missing or expired')
|
|
650
|
-
return None
|
|
651
|
-
return AccessToken(str(creds.access_token), creds.token_expiry)
|
|
652
|
-
|
|
653
|
-
def _create_access_token(self, allow_user_interaction=False):
|
|
654
|
-
"""Mints and caches a new access token, launching OAuth2 dance if necessary.
|
|
655
|
-
|
|
656
|
-
Uses cached refresh token, if present. In that case user interaction is not
|
|
657
|
-
required and function will finish quietly. Otherwise it will launch 3-legged
|
|
658
|
-
OAuth2 flow, that needs user interaction.
|
|
659
|
-
|
|
660
|
-
Args:
|
|
661
|
-
allow_user_interaction: if True, allow interaction with the user (e.g.
|
|
662
|
-
reading standard input, or launching a browser).
|
|
141
|
+
def _run_luci_auth_login(self):
|
|
142
|
+
"""Run luci-auth login.
|
|
663
143
|
|
|
664
144
|
Returns:
|
|
665
|
-
AccessToken.
|
|
666
|
-
|
|
667
|
-
Raises:
|
|
668
|
-
AuthenticationError on error or if authentication flow was interrupted.
|
|
669
|
-
LoginRequiredError if user interaction is required, but
|
|
670
|
-
allow_user_interaction is False.
|
|
145
|
+
AccessToken with credentials.
|
|
671
146
|
"""
|
|
672
|
-
logging.debug(
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
credentials = self._get_cached_credentials()
|
|
676
|
-
|
|
677
|
-
# 3-legged flow with (perhaps cached) refresh token.
|
|
678
|
-
refreshed = False
|
|
679
|
-
if credentials and not credentials.invalid:
|
|
680
|
-
try:
|
|
681
|
-
logging.debug('Attempting to refresh access_token')
|
|
682
|
-
credentials.refresh(httplib2.Http())
|
|
683
|
-
_log_credentials_info('refreshed token', credentials)
|
|
684
|
-
refreshed = True
|
|
685
|
-
except client.Error as err:
|
|
686
|
-
logging.warning(
|
|
687
|
-
'OAuth error during access token refresh (%s). '
|
|
688
|
-
'Attempting a full authentication flow.', err)
|
|
689
|
-
|
|
690
|
-
# Refresh token is missing or invalid, go through the full flow.
|
|
691
|
-
if not refreshed:
|
|
692
|
-
# Can't refresh externally provided token.
|
|
693
|
-
if self._external_token:
|
|
694
|
-
raise AuthenticationError(
|
|
695
|
-
'Token provided via --auth-refresh-token-json is no longer valid.')
|
|
696
|
-
if not allow_user_interaction:
|
|
697
|
-
logging.debug('Requesting user to login')
|
|
698
|
-
raise LoginRequiredError(self._token_cache_key)
|
|
699
|
-
logging.debug('Launching OAuth browser flow')
|
|
700
|
-
credentials = _run_oauth_dance(self._config, self._scopes)
|
|
701
|
-
_log_credentials_info('new token', credentials)
|
|
702
|
-
|
|
703
|
-
logging.info(
|
|
704
|
-
'OAuth access_token refreshed. Expires in %s.',
|
|
705
|
-
credentials.token_expiry - datetime.datetime.utcnow())
|
|
706
|
-
storage = self._get_storage()
|
|
707
|
-
credentials.set_store(storage)
|
|
708
|
-
storage.put(credentials)
|
|
709
|
-
return AccessToken(str(credentials.access_token), credentials.token_expiry)
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
## Private functions.
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
def _get_token_cache_path():
|
|
716
|
-
# On non Win just use HOME.
|
|
717
|
-
if sys.platform != 'win32':
|
|
718
|
-
return os.path.join(os.path.expanduser('~'), OAUTH_TOKENS_CACHE)
|
|
719
|
-
# Prefer USERPROFILE over HOME, since HOME is overridden in
|
|
720
|
-
# git-..._bin/cmd/git.cmd to point to depot_tools. depot-tools-auth.py script
|
|
721
|
-
# (and all other scripts) doesn't use this override and thus uses another
|
|
722
|
-
# value for HOME. git.cmd doesn't touch USERPROFILE though, and usually
|
|
723
|
-
# USERPROFILE == HOME on Windows.
|
|
724
|
-
if 'USERPROFILE' in os.environ:
|
|
725
|
-
return os.path.join(os.environ['USERPROFILE'], OAUTH_TOKENS_CACHE)
|
|
726
|
-
return os.path.join(os.path.expanduser('~'), OAUTH_TOKENS_CACHE)
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
def _is_headless():
|
|
730
|
-
"""True if machine doesn't seem to have a display."""
|
|
731
|
-
return sys.platform == 'linux2' and not os.environ.get('DISPLAY')
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
def _read_refresh_token_json(path):
|
|
735
|
-
"""Returns RefreshToken by reading it from the JSON file."""
|
|
736
|
-
try:
|
|
737
|
-
with open(path, 'r') as f:
|
|
738
|
-
data = json.load(f)
|
|
739
|
-
return RefreshToken(
|
|
740
|
-
client_id=str(data.get('client_id', OAUTH_CLIENT_ID)),
|
|
741
|
-
client_secret=str(data.get('client_secret', OAUTH_CLIENT_SECRET)),
|
|
742
|
-
refresh_token=str(data['refresh_token']))
|
|
743
|
-
except (IOError, ValueError) as e:
|
|
744
|
-
raise AuthenticationError(
|
|
745
|
-
'Failed to read refresh token from %s: %s' % (path, e))
|
|
746
|
-
except KeyError as e:
|
|
747
|
-
raise AuthenticationError(
|
|
748
|
-
'Failed to read refresh token from %s: missing key %s' % (path, e))
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
def _log_credentials_info(title, credentials):
|
|
752
|
-
"""Dumps (non sensitive) part of client.Credentials object to debug log."""
|
|
753
|
-
if credentials:
|
|
754
|
-
logging.debug('%s info: %r', title, {
|
|
755
|
-
'access_token_expired': credentials.access_token_expired,
|
|
756
|
-
'has_access_token': bool(credentials.access_token),
|
|
757
|
-
'invalid': credentials.invalid,
|
|
758
|
-
'utcnow': datetime.datetime.utcnow(),
|
|
759
|
-
'token_expiry': credentials.token_expiry,
|
|
760
|
-
})
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
def _run_oauth_dance(config, scopes):
|
|
764
|
-
"""Perform full 3-legged OAuth2 flow with the browser.
|
|
765
|
-
|
|
766
|
-
Returns:
|
|
767
|
-
oauth2client.Credentials.
|
|
768
|
-
|
|
769
|
-
Raises:
|
|
770
|
-
AuthenticationError on errors.
|
|
771
|
-
"""
|
|
772
|
-
flow = client.OAuth2WebServerFlow(
|
|
773
|
-
OAUTH_CLIENT_ID,
|
|
774
|
-
OAUTH_CLIENT_SECRET,
|
|
775
|
-
scopes,
|
|
776
|
-
approval_prompt='force')
|
|
777
|
-
|
|
778
|
-
use_local_webserver = config.use_local_webserver
|
|
779
|
-
port = config.webserver_port
|
|
780
|
-
if config.use_local_webserver:
|
|
781
|
-
success = False
|
|
782
|
-
try:
|
|
783
|
-
httpd = _ClientRedirectServer(('localhost', port), _ClientRedirectHandler)
|
|
784
|
-
except socket.error:
|
|
785
|
-
pass
|
|
786
|
-
else:
|
|
787
|
-
success = True
|
|
788
|
-
use_local_webserver = success
|
|
789
|
-
if not success:
|
|
790
|
-
print(
|
|
791
|
-
'Failed to start a local webserver listening on port %d.\n'
|
|
792
|
-
'Please check your firewall settings and locally running programs that '
|
|
793
|
-
'may be blocking or using those ports.\n\n'
|
|
794
|
-
'Falling back to --auth-no-local-webserver and continuing with '
|
|
795
|
-
'authentication.\n' % port)
|
|
796
|
-
|
|
797
|
-
if use_local_webserver:
|
|
798
|
-
oauth_callback = 'http://localhost:%s/' % port
|
|
799
|
-
else:
|
|
800
|
-
oauth_callback = client.OOB_CALLBACK_URN
|
|
801
|
-
flow.redirect_uri = oauth_callback
|
|
802
|
-
authorize_url = flow.step1_get_authorize_url()
|
|
803
|
-
|
|
804
|
-
if use_local_webserver:
|
|
805
|
-
webbrowser.open(authorize_url, new=1, autoraise=True)
|
|
806
|
-
print(
|
|
807
|
-
'Your browser has been opened to visit:\n\n'
|
|
808
|
-
' %s\n\n'
|
|
809
|
-
'If your browser is on a different machine then exit and re-run this '
|
|
810
|
-
'application with the command-line parameter\n\n'
|
|
811
|
-
' --auth-no-local-webserver\n' % authorize_url)
|
|
812
|
-
else:
|
|
813
|
-
print(
|
|
814
|
-
'Go to the following link in your browser:\n\n'
|
|
815
|
-
' %s\n' % authorize_url)
|
|
816
|
-
|
|
817
|
-
try:
|
|
818
|
-
code = None
|
|
819
|
-
if use_local_webserver:
|
|
820
|
-
httpd.handle_request()
|
|
821
|
-
if 'error' in httpd.query_params:
|
|
822
|
-
raise AuthenticationError(
|
|
823
|
-
'Authentication request was rejected: %s' %
|
|
824
|
-
httpd.query_params['error'])
|
|
825
|
-
if 'code' not in httpd.query_params:
|
|
826
|
-
raise AuthenticationError(
|
|
827
|
-
'Failed to find "code" in the query parameters of the redirect.\n'
|
|
828
|
-
'Try running with --auth-no-local-webserver.')
|
|
829
|
-
code = httpd.query_params['code']
|
|
830
|
-
else:
|
|
831
|
-
code = raw_input('Enter verification code: ').strip()
|
|
832
|
-
except KeyboardInterrupt:
|
|
833
|
-
raise AuthenticationError('Authentication was canceled.')
|
|
834
|
-
|
|
835
|
-
try:
|
|
836
|
-
return flow.step2_exchange(code)
|
|
837
|
-
except client.FlowExchangeError as e:
|
|
838
|
-
raise AuthenticationError('Authentication has failed: %s' % e)
|
|
839
|
-
|
|
147
|
+
logging.debug('Running luci-auth login')
|
|
148
|
+
subprocess2.check_call(['luci-auth', 'login', '-scopes', self._scopes])
|
|
149
|
+
return self._get_luci_auth_token()
|
|
840
150
|
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
into the servers query_params and then stops serving.
|
|
855
|
-
"""
|
|
856
|
-
|
|
857
|
-
def do_GET(self):
|
|
858
|
-
"""Handle a GET request.
|
|
859
|
-
|
|
860
|
-
Parses the query parameters and prints a message
|
|
861
|
-
if the flow has completed. Note that we can't detect
|
|
862
|
-
if an error occurred.
|
|
863
|
-
"""
|
|
864
|
-
self.send_response(200)
|
|
865
|
-
self.send_header('Content-type', 'text/html')
|
|
866
|
-
self.end_headers()
|
|
867
|
-
query = self.path.split('?', 1)[-1]
|
|
868
|
-
query = dict(urlparse.parse_qsl(query))
|
|
869
|
-
self.server.query_params = query
|
|
870
|
-
self.wfile.write('<html><head><title>Authentication Status</title></head>')
|
|
871
|
-
self.wfile.write('<body><p>The authentication flow has completed.</p>')
|
|
872
|
-
self.wfile.write('</body></html>')
|
|
873
|
-
|
|
874
|
-
def log_message(self, _format, *args):
|
|
875
|
-
"""Do not log messages to stdout while running as command line program."""
|
|
151
|
+
def _get_luci_auth_token(self):
|
|
152
|
+
logging.debug('Running luci-auth token')
|
|
153
|
+
try:
|
|
154
|
+
out, err = subprocess2.check_call_out(
|
|
155
|
+
['luci-auth', 'token', '-scopes', self._scopes, '-json-output', '-'],
|
|
156
|
+
stdout=subprocess2.PIPE, stderr=subprocess2.PIPE)
|
|
157
|
+
logging.debug('luci-auth token stderr:\n%s', err)
|
|
158
|
+
token_info = json.loads(out)
|
|
159
|
+
return AccessToken(
|
|
160
|
+
token_info['token'],
|
|
161
|
+
datetime.datetime.utcfromtimestamp(token_info['expiry']))
|
|
162
|
+
except subprocess2.CalledProcessError:
|
|
163
|
+
return None
|