libv8 6.3.292.48.1 → 6.7.288.46.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (195) hide show
  1. checksums.yaml +5 -5
  2. data/.travis.yml +10 -34
  3. data/CHANGELOG.md +16 -0
  4. data/README.md +9 -63
  5. data/Rakefile +2 -2
  6. data/ext/libv8/builder.rb +22 -87
  7. data/ext/libv8/extconf.rb +1 -1
  8. data/ext/libv8/paths.rb +5 -18
  9. data/lib/libv8/version.rb +1 -1
  10. data/spec/location_spec.rb +1 -2
  11. data/spec/spec_helper.rb +0 -1
  12. data/vendor/depot_tools/.gitattributes +1 -2
  13. data/vendor/depot_tools/OWNERS +0 -1
  14. data/vendor/depot_tools/PRESUBMIT.py +11 -6
  15. data/vendor/depot_tools/README.md +0 -1
  16. data/vendor/depot_tools/WATCHLISTS +0 -6
  17. data/vendor/depot_tools/auth.py +129 -87
  18. data/vendor/depot_tools/autoninja +11 -1
  19. data/vendor/depot_tools/autoninja.bat +7 -1
  20. data/vendor/depot_tools/autoninja.py +14 -6
  21. data/vendor/depot_tools/bootstrap/win/manifest.txt +1 -1
  22. data/vendor/depot_tools/bootstrap/win/manifest_bleeding_edge.txt +1 -1
  23. data/vendor/depot_tools/cipd +23 -2
  24. data/vendor/depot_tools/cipd.bat +2 -2
  25. data/vendor/depot_tools/cipd_client_version +1 -1
  26. data/vendor/depot_tools/cipd_manifest.txt +17 -7
  27. data/vendor/depot_tools/cit.py +7 -6
  28. data/vendor/depot_tools/cpplint.py +195 -35
  29. data/vendor/depot_tools/detect_host_arch.py +51 -0
  30. data/vendor/depot_tools/download_from_google_storage.py +85 -26
  31. data/vendor/depot_tools/fetch.py +11 -6
  32. data/vendor/depot_tools/fetch_configs/chromium.py +0 -1
  33. data/vendor/depot_tools/fetch_configs/goma_client.py +41 -0
  34. data/vendor/depot_tools/fetch_configs/infra.py +0 -1
  35. data/vendor/depot_tools/fetch_configs/infra_internal.py +0 -1
  36. data/vendor/depot_tools/gclient-new-workdir.py +4 -0
  37. data/vendor/depot_tools/gclient.py +732 -476
  38. data/vendor/depot_tools/gclient_eval.py +569 -58
  39. data/vendor/depot_tools/gclient_scm.py +258 -46
  40. data/vendor/depot_tools/gclient_utils.py +17 -1
  41. data/vendor/depot_tools/gerrit_util.py +46 -13
  42. data/vendor/depot_tools/git_cache.py +0 -2
  43. data/vendor/depot_tools/git_cl.py +176 -335
  44. data/vendor/depot_tools/git_common.py +19 -16
  45. data/vendor/depot_tools/git_footers.py +19 -5
  46. data/vendor/depot_tools/git_hyper_blame.py +9 -3
  47. data/vendor/depot_tools/git_new_branch.py +15 -3
  48. data/vendor/depot_tools/git_upstream_diff.py +7 -2
  49. data/vendor/depot_tools/gsutil.py +1 -1
  50. data/vendor/depot_tools/infra/config/cq.cfg +1 -2
  51. data/vendor/depot_tools/infra/config/recipes.cfg +1 -1
  52. data/vendor/depot_tools/luci-auth +13 -0
  53. data/vendor/depot_tools/luci-auth.bat +8 -0
  54. data/vendor/depot_tools/man/html/depot_tools.html +0 -8
  55. data/vendor/depot_tools/man/html/git-upstream-diff.html +20 -3
  56. data/vendor/depot_tools/man/man1/git-upstream-diff.1 +27 -6
  57. data/vendor/depot_tools/man/man7/depot_tools.7 +0 -5
  58. data/vendor/depot_tools/man/man7/depot_tools_tutorial.7 +2 -2
  59. data/vendor/depot_tools/man/src/git-upstream-diff.txt +21 -3
  60. data/vendor/depot_tools/man/src/make_docs.sh +6 -0
  61. data/vendor/depot_tools/my_activity.py +283 -93
  62. data/vendor/depot_tools/owners.py +9 -4
  63. data/vendor/depot_tools/owners_finder.py +7 -3
  64. data/vendor/depot_tools/post_build_ninja_summary.py +322 -0
  65. data/vendor/depot_tools/presubmit_canned_checks.py +91 -106
  66. data/vendor/depot_tools/presubmit_support.py +219 -157
  67. data/vendor/depot_tools/prpc +13 -0
  68. data/vendor/depot_tools/prpc.bat +8 -0
  69. data/vendor/depot_tools/recipes/OWNERS +3 -1
  70. data/vendor/depot_tools/recipes/README.recipes.md +70 -111
  71. data/vendor/depot_tools/recipes/recipe_modules/bot_update/__init__.py +12 -5
  72. data/vendor/depot_tools/recipes/recipe_modules/bot_update/api.py +36 -68
  73. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/deprecated_got_revision_mapping.json +0 -8
  74. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/{trychange_oauth2_json.json → no_apply_patch_on_gclient.json} +64 -10
  75. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/{no_shallow.json → shallow.json} +1 -1
  76. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob.json +0 -8
  77. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_empty_revision.json +0 -8
  78. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail.json +0 -6
  79. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch.json +0 -7
  80. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch_download.json +0 -6
  81. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_angle_deprecated.json +44 -0
  82. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/{trychange_oauth2_buildbot.json → tryjob_gerrit_branch_heads.json} +51 -5
  83. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8.json +0 -8
  84. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8_head_by_default.json +48 -8
  85. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.py +19 -26
  86. data/vendor/depot_tools/recipes/recipe_modules/bot_update/resources/bot_update.py +193 -155
  87. data/vendor/depot_tools/recipes/recipe_modules/bot_update/test_api.py +9 -0
  88. data/vendor/depot_tools/recipes/recipe_modules/gclient/api.py +2 -7
  89. data/vendor/depot_tools/recipes/recipe_modules/gclient/config.py +31 -5
  90. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/basic.json +37 -19
  91. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/buildbot.json +37 -19
  92. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/revision.json +37 -19
  93. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/tryserver.json +37 -23
  94. data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.py +4 -0
  95. data/vendor/depot_tools/recipes/recipe_modules/gerrit/api.py +40 -8
  96. data/vendor/depot_tools/recipes/recipe_modules/gerrit/examples/full.expected/basic.json +3 -3
  97. data/vendor/depot_tools/recipes/recipe_modules/gerrit/examples/full.py +6 -3
  98. data/vendor/depot_tools/recipes/recipe_modules/gitiles/OWNERS +0 -1
  99. data/vendor/depot_tools/recipes/recipe_modules/tryserver/__init__.py +0 -1
  100. data/vendor/depot_tools/recipes/recipe_modules/tryserver/api.py +7 -56
  101. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_wrong_patch.json +0 -1
  102. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.py +15 -16
  103. data/vendor/depot_tools/recipes/recipes.py +4 -2
  104. data/vendor/depot_tools/recipes/trigger_recipe_roller.txt +12 -0
  105. data/vendor/depot_tools/roll_dep.py +35 -37
  106. data/vendor/depot_tools/support/chromite_wrapper +1 -1
  107. data/vendor/depot_tools/third_party/logilab/astroid/README.chromium +3 -3
  108. data/vendor/depot_tools/third_party/logilab/astroid/__pkginfo__.py +2 -2
  109. data/vendor/depot_tools/third_party/logilab/astroid/astpeephole.py +86 -0
  110. data/vendor/depot_tools/third_party/logilab/astroid/bases.py +53 -66
  111. data/vendor/depot_tools/third_party/logilab/astroid/brain/py2pytest.py +31 -31
  112. data/vendor/depot_tools/third_party/logilab/astroid/brain/pynose.py +39 -16
  113. data/vendor/depot_tools/third_party/logilab/astroid/brain/pysix_moves.py +225 -189
  114. data/vendor/depot_tools/third_party/logilab/astroid/inference.py +45 -41
  115. data/vendor/depot_tools/third_party/logilab/astroid/manager.py +1 -0
  116. data/vendor/depot_tools/third_party/logilab/astroid/modutils.py +2 -2
  117. data/vendor/depot_tools/third_party/logilab/astroid/node_classes.py +3 -2
  118. data/vendor/depot_tools/third_party/logilab/astroid/nodes.py +1 -0
  119. data/vendor/depot_tools/third_party/logilab/astroid/protocols.py +57 -3
  120. data/vendor/depot_tools/third_party/logilab/astroid/raw_building.py +1 -1
  121. data/vendor/depot_tools/third_party/logilab/astroid/rebuilder.py +21 -1
  122. data/vendor/depot_tools/third_party/logilab/astroid/scoped_nodes.py +58 -33
  123. data/vendor/depot_tools/third_party/pylint/README.chromium +2 -2
  124. data/vendor/depot_tools/third_party/pylint/__pkginfo__.py +3 -3
  125. data/vendor/depot_tools/third_party/pylint/checkers/base.py +6 -18
  126. data/vendor/depot_tools/third_party/pylint/checkers/classes.py +64 -63
  127. data/vendor/depot_tools/third_party/pylint/checkers/design_analysis.py +25 -57
  128. data/vendor/depot_tools/third_party/pylint/checkers/format.py +14 -10
  129. data/vendor/depot_tools/third_party/pylint/checkers/python3.py +142 -37
  130. data/vendor/depot_tools/third_party/pylint/checkers/spelling.py +10 -1
  131. data/vendor/depot_tools/third_party/pylint/checkers/stdlib.py +50 -7
  132. data/vendor/depot_tools/third_party/pylint/checkers/strings.py +1 -1
  133. data/vendor/depot_tools/third_party/pylint/epylint.py +2 -1
  134. data/vendor/depot_tools/third_party/pylint/gui.py +1 -1
  135. data/vendor/depot_tools/third_party/pylint/lint.py +88 -23
  136. data/vendor/depot_tools/third_party/pylint/reporters/html.py +37 -5
  137. data/vendor/depot_tools/third_party/pylint/testutils.py +1 -1
  138. data/vendor/depot_tools/third_party/pylint/utils.py +5 -0
  139. data/vendor/depot_tools/vpython +31 -1
  140. data/vendor/depot_tools/win_toolchain/get_toolchain_if_necessary.py +35 -2
  141. data/vendor/depot_tools/win_toolchain/package_from_installed.py +0 -15
  142. data/vendor/depot_tools/yapf +17 -0
  143. data/vendor/depot_tools/{apply_issue.bat → yapf.bat} +2 -2
  144. metadata +16 -58
  145. data/ext/libv8/compiler.rb +0 -39
  146. data/ext/libv8/compiler/apple_llvm.rb +0 -22
  147. data/ext/libv8/compiler/clang.rb +0 -22
  148. data/ext/libv8/compiler/gcc.rb +0 -22
  149. data/ext/libv8/compiler/generic_compiler.rb +0 -66
  150. data/ext/libv8/make.rb +0 -13
  151. data/ext/libv8/patcher.rb +0 -21
  152. data/patches/0001-Build-a-standalone-static-library.patch +0 -26
  153. data/patches/0002-Don-t-compile-unnecessary-stuff.patch +0 -85
  154. data/patches/0003-Use-the-fPIC-flag-for-the-static-library.patch +0 -25
  155. data/patches/0004-Do-not-embed-debug-symbols-in-macOS-libraries.patch +0 -25
  156. data/patches/0005-Remove-TryInstallOptimizedCode.patch +0 -321
  157. data/patches/mingw-generate-makefiles.sh +0 -97
  158. data/spec/compiler/apple_llvm_spec.rb +0 -37
  159. data/spec/compiler/clang_spec.rb +0 -37
  160. data/spec/compiler/gcc_spec.rb +0 -37
  161. data/spec/compiler/generic_compiler_spec.rb +0 -50
  162. data/spec/compiler_spec.rb +0 -45
  163. data/spec/support/compiler_helpers.rb +0 -47
  164. data/vendor/depot_tools/apply_issue +0 -8
  165. data/vendor/depot_tools/apply_issue.py +0 -315
  166. data/vendor/depot_tools/man/html/git-cherry-pick-upload.html +0 -815
  167. data/vendor/depot_tools/man/man1/git-cherry-pick-upload.1 +0 -80
  168. data/vendor/depot_tools/man/src/_git-cherry-pick-upload_desc.helper.txt +0 -1
  169. data/vendor/depot_tools/man/src/git-cherry-pick-upload.demo.1.sh +0 -17
  170. data/vendor/depot_tools/man/src/git-cherry-pick-upload.txt +0 -35
  171. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/trychange_oauth2.json +0 -8
  172. data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/trychange_oauth2_json_win.json +0 -196
  173. data/vendor/depot_tools/recipes/recipe_modules/rietveld/__init__.py +0 -6
  174. data/vendor/depot_tools/recipes/recipe_modules/rietveld/api.py +0 -97
  175. data/vendor/depot_tools/recipes/recipe_modules/rietveld/examples/full.expected/basic.json +0 -8
  176. data/vendor/depot_tools/recipes/recipe_modules/rietveld/examples/full.expected/buildbot.json +0 -30
  177. data/vendor/depot_tools/recipes/recipe_modules/rietveld/examples/full.expected/no_auth.json +0 -27
  178. data/vendor/depot_tools/recipes/recipe_modules/rietveld/examples/full.py +0 -38
  179. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_rietveld_patch.json +0 -69
  180. data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_rietveld_patch_new.json +0 -69
  181. data/vendor/depot_tools/third_party/cq_client/OWNERS +0 -2
  182. data/vendor/depot_tools/third_party/cq_client/README.depot_tools.md +0 -2
  183. data/vendor/depot_tools/third_party/cq_client/README.md +0 -59
  184. data/vendor/depot_tools/third_party/cq_client/__init__.py +0 -3
  185. data/vendor/depot_tools/third_party/cq_client/v1/__init__.py +0 -3
  186. data/vendor/depot_tools/third_party/cq_client/v1/cq.pb.go +0 -810
  187. data/vendor/depot_tools/third_party/cq_client/v1/cq.proto +0 -281
  188. data/vendor/depot_tools/third_party/cq_client/v1/cq_pb2.py +0 -794
  189. data/vendor/depot_tools/third_party/cq_client/v1/testdata/cq_both.cfg +0 -71
  190. data/vendor/depot_tools/third_party/cq_client/v1/testdata/cq_gerrit.cfg +0 -58
  191. data/vendor/depot_tools/third_party/cq_client/v1/testdata/cq_rietveld.cfg +0 -60
  192. data/vendor/depot_tools/third_party/cq_client/v2/__init__.py +0 -3
  193. data/vendor/depot_tools/third_party/cq_client/v2/cq.pb.go +0 -792
  194. data/vendor/depot_tools/third_party/cq_client/v2/cq.proto +0 -270
  195. data/vendor/depot_tools/third_party/cq_client/v2/cq_pb2.py +0 -841
@@ -6,13 +6,17 @@
6
6
 
7
7
  from __future__ import print_function
8
8
 
9
+ import collections
10
+ import contextlib
9
11
  import errno
12
+ import json
10
13
  import logging
11
14
  import os
12
15
  import posixpath
13
16
  import re
14
17
  import sys
15
18
  import tempfile
19
+ import threading
16
20
  import traceback
17
21
  import urlparse
18
22
 
@@ -81,37 +85,6 @@ class GitDiffFilterer(DiffFiltererWrapper):
81
85
  return re.sub("[a|b]/" + self._current_file, self._replacement_file, line)
82
86
 
83
87
 
84
- ### SCM abstraction layer
85
-
86
- # Factory Method for SCM wrapper creation
87
-
88
- def GetScmName(url):
89
- if not url:
90
- return None
91
- url, _ = gclient_utils.SplitUrlRevision(url)
92
- if url.endswith('.git'):
93
- return 'git'
94
- protocol = url.split('://')[0]
95
- if protocol in (
96
- 'file', 'git', 'git+http', 'git+https', 'http', 'https', 'ssh', 'sso'):
97
- return 'git'
98
- return None
99
-
100
-
101
- def CreateSCM(url, root_dir=None, relpath=None, out_fh=None, out_cb=None):
102
- SCM_MAP = {
103
- 'git' : GitWrapper,
104
- }
105
-
106
- scm_name = GetScmName(url)
107
- if not scm_name in SCM_MAP:
108
- raise gclient_utils.Error('No SCM found for url %s' % url)
109
- scm_class = SCM_MAP[scm_name]
110
- if not scm_class.BinaryExists():
111
- raise gclient_utils.Error('%s command not found' % scm_name)
112
- return scm_class(url, root_dir, relpath, out_fh, out_cb)
113
-
114
-
115
88
  # SCMWrapper base class
116
89
 
117
90
  class SCMWrapper(object):
@@ -121,7 +94,7 @@ class SCMWrapper(object):
121
94
  """
122
95
 
123
96
  def __init__(self, url=None, root_dir=None, relpath=None, out_fh=None,
124
- out_cb=None):
97
+ out_cb=None, print_outbuf=False):
125
98
  self.url = url
126
99
  self._root_dir = root_dir
127
100
  if self._root_dir:
@@ -135,6 +108,7 @@ class SCMWrapper(object):
135
108
  out_fh = sys.stdout
136
109
  self.out_fh = out_fh
137
110
  self.out_cb = out_cb
111
+ self.print_outbuf = print_outbuf
138
112
 
139
113
  def Print(self, *args, **kwargs):
140
114
  kwargs.setdefault('file', self.out_fh)
@@ -238,11 +212,11 @@ class GitWrapper(SCMWrapper):
238
212
 
239
213
  cache_dir = None
240
214
 
241
- def __init__(self, url=None, *args):
215
+ def __init__(self, url=None, *args, **kwargs):
242
216
  """Removes 'git+' fake prefix from git URL."""
243
217
  if url.startswith('git+http://') or url.startswith('git+https://'):
244
218
  url = url[4:]
245
- SCMWrapper.__init__(self, url, *args)
219
+ SCMWrapper.__init__(self, url, *args, **kwargs)
246
220
  filter_kwargs = { 'time_throttle': 1, 'out_fh': self.out_fh }
247
221
  if self.out_cb:
248
222
  filter_kwargs['predicate'] = self.out_cb
@@ -278,11 +252,10 @@ class GitWrapper(SCMWrapper):
278
252
  ).split()
279
253
 
280
254
  def diff(self, options, _args, _file_list):
281
- try:
282
- merge_base = [self._Capture(['merge-base', 'HEAD', self.remote])]
283
- except subprocess2.CalledProcessError:
284
- merge_base = []
285
- self._Run(['-c', 'core.quotePath=false', 'diff'] + merge_base, options)
255
+ _, revision = gclient_utils.SplitUrlRevision(self.url)
256
+ if not revision:
257
+ revision = 'refs/remotes/%s/master' % self.remote
258
+ self._Run(['-c', 'core.quotePath=false', 'diff', revision], options)
286
259
 
287
260
  def pack(self, _options, _args, _file_list):
288
261
  """Generates a patch file which can be applied to the root of the
@@ -367,6 +340,32 @@ class GitWrapper(SCMWrapper):
367
340
  self.Print('FAILED to break lock: %s: %s' % (to_break, ex))
368
341
  raise
369
342
 
343
+ def apply_patch_ref(self, patch_repo, patch_ref, options, file_list):
344
+ base_rev = self._Capture(['rev-parse', 'HEAD'])
345
+ self.Print('===Applying patch ref===')
346
+ self.Print('Repo is %r @ %r, ref is %r, root is %r' % (
347
+ patch_repo, patch_ref, base_rev, self.checkout_path))
348
+ self._Capture(['reset', '--hard'])
349
+ self._Capture(['fetch', patch_repo, patch_ref])
350
+ if file_list is not None:
351
+ file_list.extend(self._GetDiffFilenames('FETCH_HEAD'))
352
+ self._Capture(['checkout', 'FETCH_HEAD'])
353
+
354
+ if options.rebase_patch_ref:
355
+ try:
356
+ # TODO(ehmaldonado): Look into cherry-picking to avoid an expensive
357
+ # checkout + rebase.
358
+ self._Capture(['rebase', base_rev])
359
+ except subprocess2.CalledProcessError as e:
360
+ self.Print('Failed to apply %r @ %r to %r at %r' % (
361
+ patch_repo, patch_ref, base_rev, self.checkout_path))
362
+ self.Print('git returned non-zero exit status %s:\n%s' % (
363
+ e.returncode, e.stderr))
364
+ self._Capture(['rebase', '--abort'])
365
+ raise
366
+ if options.reset_patch_ref:
367
+ self._Capture(['reset', '--soft', base_rev])
368
+
370
369
  def update(self, options, args, file_list):
371
370
  """Runs git to update or transparently checkout the working copy.
372
371
 
@@ -825,12 +824,6 @@ class GitWrapper(SCMWrapper):
825
824
 
826
825
  return sha1
827
826
 
828
- def FullUrlForRelativeUrl(self, url):
829
- # Strip from last '/'
830
- # Equivalent to unix basename
831
- base_url = self.url
832
- return base_url[:base_url.rfind('/')] + url
833
-
834
827
  def GetGitBackupDirPath(self):
835
828
  """Returns the path where the .git folder for the current project can be
836
829
  staged/restored. Use case: subproject moved from DEPS <-> outer project."""
@@ -923,7 +916,14 @@ class GitWrapper(SCMWrapper):
923
916
  dir=parent_dir)
924
917
  try:
925
918
  clone_cmd.append(tmp_dir)
926
- self._Run(clone_cmd, options, cwd=self._root_dir, retry=True)
919
+ if self.print_outbuf:
920
+ print_stdout = True
921
+ stdout = gclient_utils.WriteToStdout(self.out_fh)
922
+ else:
923
+ print_stdout = False
924
+ stdout = self.out_fh
925
+ self._Run(clone_cmd, options, cwd=self._root_dir, retry=True,
926
+ print_stdout=print_stdout, stdout=stdout)
927
927
  gclient_utils.safe_makedirs(self.checkout_path)
928
928
  gclient_utils.safe_rename(os.path.join(tmp_dir, '.git'),
929
929
  os.path.join(self.checkout_path, '.git'))
@@ -1230,3 +1230,215 @@ class GitWrapper(SCMWrapper):
1230
1230
  gclient_utils.CheckCallAndFilterAndHeader(cmd, env=env, **kwargs)
1231
1231
  else:
1232
1232
  gclient_utils.CheckCallAndFilter(cmd, env=env, **kwargs)
1233
+
1234
+
1235
+ class CipdPackage(object):
1236
+ """A representation of a single CIPD package."""
1237
+
1238
+ def __init__(self, name, version, authority_for_subdir):
1239
+ self._authority_for_subdir = authority_for_subdir
1240
+ self._name = name
1241
+ self._version = version
1242
+
1243
+ @property
1244
+ def authority_for_subdir(self):
1245
+ """Whether this package has authority to act on behalf of its subdir.
1246
+
1247
+ Some operations should only be performed once per subdirectory. A package
1248
+ that has authority for its subdirectory is the only package that should
1249
+ perform such operations.
1250
+
1251
+ Returns:
1252
+ bool; whether this package has subdir authority.
1253
+ """
1254
+ return self._authority_for_subdir
1255
+
1256
+ @property
1257
+ def name(self):
1258
+ return self._name
1259
+
1260
+ @property
1261
+ def version(self):
1262
+ return self._version
1263
+
1264
+
1265
+ class CipdRoot(object):
1266
+ """A representation of a single CIPD root."""
1267
+ def __init__(self, root_dir, service_url):
1268
+ self._all_packages = set()
1269
+ self._mutator_lock = threading.Lock()
1270
+ self._packages_by_subdir = collections.defaultdict(list)
1271
+ self._root_dir = root_dir
1272
+ self._service_url = service_url
1273
+
1274
+ def add_package(self, subdir, package, version):
1275
+ """Adds a package to this CIPD root.
1276
+
1277
+ As far as clients are concerned, this grants both root and subdir authority
1278
+ to packages arbitrarily. (The implementation grants root authority to the
1279
+ first package added and subdir authority to the first package added for that
1280
+ subdir, but clients should not depend on or expect that behavior.)
1281
+
1282
+ Args:
1283
+ subdir: str; relative path to where the package should be installed from
1284
+ the cipd root directory.
1285
+ package: str; the cipd package name.
1286
+ version: str; the cipd package version.
1287
+ Returns:
1288
+ CipdPackage; the package that was created and added to this root.
1289
+ """
1290
+ with self._mutator_lock:
1291
+ cipd_package = CipdPackage(
1292
+ package, version,
1293
+ not self._packages_by_subdir[subdir])
1294
+ self._all_packages.add(cipd_package)
1295
+ self._packages_by_subdir[subdir].append(cipd_package)
1296
+ return cipd_package
1297
+
1298
+ def packages(self, subdir):
1299
+ """Get the list of configured packages for the given subdir."""
1300
+ return list(self._packages_by_subdir[subdir])
1301
+
1302
+ def clobber(self):
1303
+ """Remove the .cipd directory.
1304
+
1305
+ This is useful for forcing ensure to redownload and reinitialize all
1306
+ packages.
1307
+ """
1308
+ with self._mutator_lock:
1309
+ cipd_cache_dir = os.path.join(self.root_dir, '.cipd')
1310
+ try:
1311
+ gclient_utils.rmtree(os.path.join(cipd_cache_dir))
1312
+ except OSError:
1313
+ if os.path.exists(cipd_cache_dir):
1314
+ raise
1315
+
1316
+ @contextlib.contextmanager
1317
+ def _create_ensure_file(self):
1318
+ try:
1319
+ ensure_file = None
1320
+ with tempfile.NamedTemporaryFile(
1321
+ suffix='.ensure', delete=False) as ensure_file:
1322
+ for subdir, packages in sorted(self._packages_by_subdir.iteritems()):
1323
+ ensure_file.write('@Subdir %s\n' % subdir)
1324
+ for package in sorted(packages, key=lambda p: p.name):
1325
+ ensure_file.write('%s %s\n' % (package.name, package.version))
1326
+ ensure_file.write('\n')
1327
+ yield ensure_file.name
1328
+ finally:
1329
+ if ensure_file is not None and os.path.exists(ensure_file.name):
1330
+ os.remove(ensure_file.name)
1331
+
1332
+ def ensure(self):
1333
+ """Run `cipd ensure`."""
1334
+ with self._mutator_lock:
1335
+ with self._create_ensure_file() as ensure_file:
1336
+ cmd = [
1337
+ 'cipd', 'ensure',
1338
+ '-log-level', 'error',
1339
+ '-root', self.root_dir,
1340
+ '-ensure-file', ensure_file,
1341
+ ]
1342
+ gclient_utils.CheckCallAndFilterAndHeader(cmd)
1343
+
1344
+ def run(self, command):
1345
+ if command == 'update':
1346
+ self.ensure()
1347
+ elif command == 'revert':
1348
+ self.clobber()
1349
+ self.ensure()
1350
+
1351
+ def created_package(self, package):
1352
+ """Checks whether this root created the given package.
1353
+
1354
+ Args:
1355
+ package: CipdPackage; the package to check.
1356
+ Returns:
1357
+ bool; whether this root created the given package.
1358
+ """
1359
+ return package in self._all_packages
1360
+
1361
+ @property
1362
+ def root_dir(self):
1363
+ return self._root_dir
1364
+
1365
+ @property
1366
+ def service_url(self):
1367
+ return self._service_url
1368
+
1369
+
1370
+ class CipdWrapper(SCMWrapper):
1371
+ """Wrapper for CIPD.
1372
+
1373
+ Currently only supports chrome-infra-packages.appspot.com.
1374
+ """
1375
+ name = 'cipd'
1376
+
1377
+ def __init__(self, url=None, root_dir=None, relpath=None, out_fh=None,
1378
+ out_cb=None, root=None, package=None):
1379
+ super(CipdWrapper, self).__init__(
1380
+ url=url, root_dir=root_dir, relpath=relpath, out_fh=out_fh,
1381
+ out_cb=out_cb)
1382
+ assert root.created_package(package)
1383
+ self._package = package
1384
+ self._root = root
1385
+
1386
+ #override
1387
+ def GetCacheMirror(self):
1388
+ return None
1389
+
1390
+ #override
1391
+ def GetActualRemoteURL(self, options):
1392
+ return self._root.service_url
1393
+
1394
+ #override
1395
+ def DoesRemoteURLMatch(self, options):
1396
+ del options
1397
+ return True
1398
+
1399
+ def revert(self, options, args, file_list):
1400
+ """Does nothing.
1401
+
1402
+ CIPD packages should be reverted at the root by running
1403
+ `CipdRoot.run('revert')`.
1404
+ """
1405
+ pass
1406
+
1407
+ def diff(self, options, args, file_list):
1408
+ """CIPD has no notion of diffing."""
1409
+ pass
1410
+
1411
+ def pack(self, options, args, file_list):
1412
+ """CIPD has no notion of diffing."""
1413
+ pass
1414
+
1415
+ def revinfo(self, options, args, file_list):
1416
+ """Grab the instance ID."""
1417
+ try:
1418
+ tmpdir = tempfile.mkdtemp()
1419
+ describe_json_path = os.path.join(tmpdir, 'describe.json')
1420
+ cmd = [
1421
+ 'cipd', 'describe',
1422
+ self._package.name,
1423
+ '-log-level', 'error',
1424
+ '-version', self._package.version,
1425
+ '-json-output', describe_json_path
1426
+ ]
1427
+ gclient_utils.CheckCallAndFilter(
1428
+ cmd, filter_fn=lambda _line: None, print_stdout=False)
1429
+ with open(describe_json_path) as f:
1430
+ describe_json = json.load(f)
1431
+ return describe_json.get('result', {}).get('pin', {}).get('instance_id')
1432
+ finally:
1433
+ gclient_utils.rmtree(tmpdir)
1434
+
1435
+ def status(self, options, args, file_list):
1436
+ pass
1437
+
1438
+ def update(self, options, args, file_list):
1439
+ """Does nothing.
1440
+
1441
+ CIPD packages should be updated at the root by running
1442
+ `CipdRoot.run('update')`.
1443
+ """
1444
+ pass
@@ -325,6 +325,22 @@ class Wrapper(object):
325
325
  return getattr(self._wrapped, name)
326
326
 
327
327
 
328
+ class WriteToStdout(Wrapper):
329
+ """Creates a file object clone to also print to sys.stdout."""
330
+ def __init__(self, wrapped):
331
+ super(WriteToStdout, self).__init__(wrapped)
332
+ if not hasattr(self, 'lock'):
333
+ self.lock = threading.Lock()
334
+
335
+ def write(self, out, *args, **kwargs):
336
+ self._wrapped.write(out, *args, **kwargs)
337
+ self.lock.acquire()
338
+ try:
339
+ sys.stdout.write(out, *args, **kwargs)
340
+ finally:
341
+ self.lock.release()
342
+
343
+
328
344
  class AutoFlush(Wrapper):
329
345
  """Creates a file object clone to automatically flush after N seconds."""
330
346
  def __init__(self, wrapped, delay):
@@ -1262,7 +1278,7 @@ def freeze(obj):
1262
1278
 
1263
1279
  Will raise TypeError if you pass an object which is not hashable.
1264
1280
  """
1265
- if isinstance(obj, dict):
1281
+ if isinstance(obj, collections.Mapping):
1266
1282
  return FrozenDict((freeze(k), freeze(v)) for k, v in obj.iteritems())
1267
1283
  elif isinstance(obj, (list, tuple)):
1268
1284
  return tuple(freeze(i) for i in obj)
@@ -26,7 +26,9 @@ import urllib
26
26
  import urlparse
27
27
  from cStringIO import StringIO
28
28
 
29
+ import auth
29
30
  import gclient_utils
31
+ import subprocess2
30
32
  from third_party import httplib2
31
33
 
32
34
  LOGGER = logging.getLogger()
@@ -85,6 +87,10 @@ class Authenticator(object):
85
87
  Probes the local system and its environment and identifies the
86
88
  Authenticator instance to use.
87
89
  """
90
+ # LUCI Context takes priority since it's normally present only on bots,
91
+ # which then must use it.
92
+ if LuciContextAuthenticator.is_luci():
93
+ return LuciContextAuthenticator()
88
94
  if GceAuthenticator.is_gce():
89
95
  return GceAuthenticator()
90
96
  return CookiesAuthenticator()
@@ -166,7 +172,11 @@ class CookiesAuthenticator(Authenticator):
166
172
  def get_gitcookies_path(cls):
167
173
  if os.getenv('GIT_COOKIES_PATH'):
168
174
  return os.getenv('GIT_COOKIES_PATH')
169
- return os.path.join(os.environ['HOME'], '.gitcookies')
175
+ try:
176
+ return subprocess2.check_output(
177
+ ['git', 'config', '--path', 'http.cookiefile']).strip()
178
+ except subprocess2.CalledProcessError:
179
+ return os.path.join(os.environ['HOME'], '.gitcookies')
170
180
 
171
181
  @classmethod
172
182
  def _get_gitcookies(cls):
@@ -202,17 +212,17 @@ class CookiesAuthenticator(Authenticator):
202
212
  return self.netrc.authenticators(host)
203
213
 
204
214
  def get_auth_header(self, host):
205
- auth = self._get_auth_for_host(host)
206
- if auth:
207
- return 'Basic %s' % (base64.b64encode('%s:%s' % (auth[0], auth[2])))
215
+ a = self._get_auth_for_host(host)
216
+ if a:
217
+ return 'Basic %s' % (base64.b64encode('%s:%s' % (a[0], a[2])))
208
218
  return None
209
219
 
210
220
  def get_auth_email(self, host):
211
221
  """Best effort parsing of email to be used for auth for the given host."""
212
- auth = self._get_auth_for_host(host)
213
- if not auth:
222
+ a = self._get_auth_for_host(host)
223
+ if not a:
214
224
  return None
215
- login = auth[0]
225
+ login = a[0]
216
226
  # login typically looks like 'git-xxx.example.com'
217
227
  if not login.startswith('git-') or '.' not in login:
218
228
  return None
@@ -251,7 +261,8 @@ class GceAuthenticator(Authenticator):
251
261
  # Based on https://cloud.google.com/compute/docs/metadata#runninggce
252
262
  try:
253
263
  resp, _ = cls._get(cls._INFO_URL)
254
- except (socket.error, httplib2.ServerNotFoundError):
264
+ except (socket.error, httplib2.ServerNotFoundError,
265
+ httplib2.socks.HTTPError):
255
266
  # Could not resolve URL.
256
267
  return False
257
268
  return resp.get('metadata-flavor') == 'Google'
@@ -297,14 +308,36 @@ class GceAuthenticator(Authenticator):
297
308
  return '%(token_type)s %(access_token)s' % token_dict
298
309
 
299
310
 
311
+ class LuciContextAuthenticator(Authenticator):
312
+ """Authenticator implementation that uses LUCI_CONTEXT ambient local auth.
313
+ """
314
+
315
+ @staticmethod
316
+ def is_luci():
317
+ return auth.has_luci_context_local_auth()
318
+
319
+ def __init__(self):
320
+ self._access_token = None
321
+ self._ensure_fresh()
322
+
323
+ def _ensure_fresh(self):
324
+ if not self._access_token or self._access_token.needs_refresh():
325
+ self._access_token = auth.get_luci_context_access_token(
326
+ scopes=' '.join([auth.OAUTH_SCOPE_EMAIL, auth.OAUTH_SCOPE_GERRIT]))
327
+
328
+ def get_auth_header(self, _host):
329
+ self._ensure_fresh()
330
+ return 'Bearer %s' % self._access_token.token
331
+
332
+
300
333
  def CreateHttpConn(host, path, reqtype='GET', headers=None, body=None):
301
334
  """Opens an https connection to a gerrit service, and sends a request."""
302
335
  headers = headers or {}
303
336
  bare_host = host.partition(':')[0]
304
337
 
305
- auth = Authenticator.get().get_auth_header(bare_host)
306
- if auth:
307
- headers.setdefault('Authorization', auth)
338
+ a = Authenticator.get().get_auth_header(bare_host)
339
+ if a:
340
+ headers.setdefault('Authorization', a)
308
341
  else:
309
342
  LOGGER.debug('No authorization found for %s.' % bare_host)
310
343
 
@@ -360,9 +393,9 @@ def ReadHttpResponse(conn, accept_statuses=frozenset([200])):
360
393
  raise GerritAuthenticationError(response.status, reason)
361
394
 
362
395
  # If response.status < 500 then the result is final; break retry loop.
363
- # If the response is 404, it might be because of replication lag, so
396
+ # If the response is 404/409, it might be because of replication lag, so
364
397
  # keep trying anyway.
365
- if ((response.status < 500 and response.status != 404)
398
+ if ((response.status < 500 and response.status not in [404, 409])
366
399
  or response.status in accept_statuses):
367
400
  LOGGER.debug('got response %d for %s %s', response.status,
368
401
  conn.req_params['method'], conn.req_params['uri'])