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.
- checksums.yaml +5 -5
- data/.travis.yml +10 -34
- data/CHANGELOG.md +16 -0
- data/README.md +9 -63
- data/Rakefile +2 -2
- data/ext/libv8/builder.rb +22 -87
- data/ext/libv8/extconf.rb +1 -1
- data/ext/libv8/paths.rb +5 -18
- data/lib/libv8/version.rb +1 -1
- data/spec/location_spec.rb +1 -2
- data/spec/spec_helper.rb +0 -1
- data/vendor/depot_tools/.gitattributes +1 -2
- data/vendor/depot_tools/OWNERS +0 -1
- data/vendor/depot_tools/PRESUBMIT.py +11 -6
- data/vendor/depot_tools/README.md +0 -1
- data/vendor/depot_tools/WATCHLISTS +0 -6
- data/vendor/depot_tools/auth.py +129 -87
- data/vendor/depot_tools/autoninja +11 -1
- data/vendor/depot_tools/autoninja.bat +7 -1
- data/vendor/depot_tools/autoninja.py +14 -6
- data/vendor/depot_tools/bootstrap/win/manifest.txt +1 -1
- data/vendor/depot_tools/bootstrap/win/manifest_bleeding_edge.txt +1 -1
- data/vendor/depot_tools/cipd +23 -2
- data/vendor/depot_tools/cipd.bat +2 -2
- data/vendor/depot_tools/cipd_client_version +1 -1
- data/vendor/depot_tools/cipd_manifest.txt +17 -7
- data/vendor/depot_tools/cit.py +7 -6
- data/vendor/depot_tools/cpplint.py +195 -35
- data/vendor/depot_tools/detect_host_arch.py +51 -0
- data/vendor/depot_tools/download_from_google_storage.py +85 -26
- data/vendor/depot_tools/fetch.py +11 -6
- data/vendor/depot_tools/fetch_configs/chromium.py +0 -1
- data/vendor/depot_tools/fetch_configs/goma_client.py +41 -0
- data/vendor/depot_tools/fetch_configs/infra.py +0 -1
- data/vendor/depot_tools/fetch_configs/infra_internal.py +0 -1
- data/vendor/depot_tools/gclient-new-workdir.py +4 -0
- data/vendor/depot_tools/gclient.py +732 -476
- data/vendor/depot_tools/gclient_eval.py +569 -58
- data/vendor/depot_tools/gclient_scm.py +258 -46
- data/vendor/depot_tools/gclient_utils.py +17 -1
- data/vendor/depot_tools/gerrit_util.py +46 -13
- data/vendor/depot_tools/git_cache.py +0 -2
- data/vendor/depot_tools/git_cl.py +176 -335
- data/vendor/depot_tools/git_common.py +19 -16
- data/vendor/depot_tools/git_footers.py +19 -5
- data/vendor/depot_tools/git_hyper_blame.py +9 -3
- data/vendor/depot_tools/git_new_branch.py +15 -3
- data/vendor/depot_tools/git_upstream_diff.py +7 -2
- data/vendor/depot_tools/gsutil.py +1 -1
- data/vendor/depot_tools/infra/config/cq.cfg +1 -2
- data/vendor/depot_tools/infra/config/recipes.cfg +1 -1
- data/vendor/depot_tools/luci-auth +13 -0
- data/vendor/depot_tools/luci-auth.bat +8 -0
- data/vendor/depot_tools/man/html/depot_tools.html +0 -8
- data/vendor/depot_tools/man/html/git-upstream-diff.html +20 -3
- data/vendor/depot_tools/man/man1/git-upstream-diff.1 +27 -6
- data/vendor/depot_tools/man/man7/depot_tools.7 +0 -5
- data/vendor/depot_tools/man/man7/depot_tools_tutorial.7 +2 -2
- data/vendor/depot_tools/man/src/git-upstream-diff.txt +21 -3
- data/vendor/depot_tools/man/src/make_docs.sh +6 -0
- data/vendor/depot_tools/my_activity.py +283 -93
- data/vendor/depot_tools/owners.py +9 -4
- data/vendor/depot_tools/owners_finder.py +7 -3
- data/vendor/depot_tools/post_build_ninja_summary.py +322 -0
- data/vendor/depot_tools/presubmit_canned_checks.py +91 -106
- data/vendor/depot_tools/presubmit_support.py +219 -157
- data/vendor/depot_tools/prpc +13 -0
- data/vendor/depot_tools/prpc.bat +8 -0
- data/vendor/depot_tools/recipes/OWNERS +3 -1
- data/vendor/depot_tools/recipes/README.recipes.md +70 -111
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/__init__.py +12 -5
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/api.py +36 -68
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/deprecated_got_revision_mapping.json +0 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/{trychange_oauth2_json.json → no_apply_patch_on_gclient.json} +64 -10
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/{no_shallow.json → shallow.json} +1 -1
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob.json +0 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_empty_revision.json +0 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail.json +0 -6
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch.json +0 -7
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_fail_patch_download.json +0 -6
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_gerrit_angle_deprecated.json +44 -0
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/{trychange_oauth2_buildbot.json → tryjob_gerrit_branch_heads.json} +51 -5
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8.json +0 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/tryjob_v8_head_by_default.json +48 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.py +19 -26
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/resources/bot_update.py +193 -155
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/test_api.py +9 -0
- data/vendor/depot_tools/recipes/recipe_modules/gclient/api.py +2 -7
- data/vendor/depot_tools/recipes/recipe_modules/gclient/config.py +31 -5
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/basic.json +37 -19
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/buildbot.json +37 -19
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/revision.json +37 -19
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.expected/tryserver.json +37 -23
- data/vendor/depot_tools/recipes/recipe_modules/gclient/examples/full.py +4 -0
- data/vendor/depot_tools/recipes/recipe_modules/gerrit/api.py +40 -8
- data/vendor/depot_tools/recipes/recipe_modules/gerrit/examples/full.expected/basic.json +3 -3
- data/vendor/depot_tools/recipes/recipe_modules/gerrit/examples/full.py +6 -3
- data/vendor/depot_tools/recipes/recipe_modules/gitiles/OWNERS +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/__init__.py +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/api.py +7 -56
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_wrong_patch.json +0 -1
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.py +15 -16
- data/vendor/depot_tools/recipes/recipes.py +4 -2
- data/vendor/depot_tools/recipes/trigger_recipe_roller.txt +12 -0
- data/vendor/depot_tools/roll_dep.py +35 -37
- data/vendor/depot_tools/support/chromite_wrapper +1 -1
- data/vendor/depot_tools/third_party/logilab/astroid/README.chromium +3 -3
- data/vendor/depot_tools/third_party/logilab/astroid/__pkginfo__.py +2 -2
- data/vendor/depot_tools/third_party/logilab/astroid/astpeephole.py +86 -0
- data/vendor/depot_tools/third_party/logilab/astroid/bases.py +53 -66
- data/vendor/depot_tools/third_party/logilab/astroid/brain/py2pytest.py +31 -31
- data/vendor/depot_tools/third_party/logilab/astroid/brain/pynose.py +39 -16
- data/vendor/depot_tools/third_party/logilab/astroid/brain/pysix_moves.py +225 -189
- data/vendor/depot_tools/third_party/logilab/astroid/inference.py +45 -41
- data/vendor/depot_tools/third_party/logilab/astroid/manager.py +1 -0
- data/vendor/depot_tools/third_party/logilab/astroid/modutils.py +2 -2
- data/vendor/depot_tools/third_party/logilab/astroid/node_classes.py +3 -2
- data/vendor/depot_tools/third_party/logilab/astroid/nodes.py +1 -0
- data/vendor/depot_tools/third_party/logilab/astroid/protocols.py +57 -3
- data/vendor/depot_tools/third_party/logilab/astroid/raw_building.py +1 -1
- data/vendor/depot_tools/third_party/logilab/astroid/rebuilder.py +21 -1
- data/vendor/depot_tools/third_party/logilab/astroid/scoped_nodes.py +58 -33
- data/vendor/depot_tools/third_party/pylint/README.chromium +2 -2
- data/vendor/depot_tools/third_party/pylint/__pkginfo__.py +3 -3
- data/vendor/depot_tools/third_party/pylint/checkers/base.py +6 -18
- data/vendor/depot_tools/third_party/pylint/checkers/classes.py +64 -63
- data/vendor/depot_tools/third_party/pylint/checkers/design_analysis.py +25 -57
- data/vendor/depot_tools/third_party/pylint/checkers/format.py +14 -10
- data/vendor/depot_tools/third_party/pylint/checkers/python3.py +142 -37
- data/vendor/depot_tools/third_party/pylint/checkers/spelling.py +10 -1
- data/vendor/depot_tools/third_party/pylint/checkers/stdlib.py +50 -7
- data/vendor/depot_tools/third_party/pylint/checkers/strings.py +1 -1
- data/vendor/depot_tools/third_party/pylint/epylint.py +2 -1
- data/vendor/depot_tools/third_party/pylint/gui.py +1 -1
- data/vendor/depot_tools/third_party/pylint/lint.py +88 -23
- data/vendor/depot_tools/third_party/pylint/reporters/html.py +37 -5
- data/vendor/depot_tools/third_party/pylint/testutils.py +1 -1
- data/vendor/depot_tools/third_party/pylint/utils.py +5 -0
- data/vendor/depot_tools/vpython +31 -1
- data/vendor/depot_tools/win_toolchain/get_toolchain_if_necessary.py +35 -2
- data/vendor/depot_tools/win_toolchain/package_from_installed.py +0 -15
- data/vendor/depot_tools/yapf +17 -0
- data/vendor/depot_tools/{apply_issue.bat → yapf.bat} +2 -2
- metadata +16 -58
- data/ext/libv8/compiler.rb +0 -39
- data/ext/libv8/compiler/apple_llvm.rb +0 -22
- data/ext/libv8/compiler/clang.rb +0 -22
- data/ext/libv8/compiler/gcc.rb +0 -22
- data/ext/libv8/compiler/generic_compiler.rb +0 -66
- data/ext/libv8/make.rb +0 -13
- data/ext/libv8/patcher.rb +0 -21
- data/patches/0001-Build-a-standalone-static-library.patch +0 -26
- data/patches/0002-Don-t-compile-unnecessary-stuff.patch +0 -85
- data/patches/0003-Use-the-fPIC-flag-for-the-static-library.patch +0 -25
- data/patches/0004-Do-not-embed-debug-symbols-in-macOS-libraries.patch +0 -25
- data/patches/0005-Remove-TryInstallOptimizedCode.patch +0 -321
- data/patches/mingw-generate-makefiles.sh +0 -97
- data/spec/compiler/apple_llvm_spec.rb +0 -37
- data/spec/compiler/clang_spec.rb +0 -37
- data/spec/compiler/gcc_spec.rb +0 -37
- data/spec/compiler/generic_compiler_spec.rb +0 -50
- data/spec/compiler_spec.rb +0 -45
- data/spec/support/compiler_helpers.rb +0 -47
- data/vendor/depot_tools/apply_issue +0 -8
- data/vendor/depot_tools/apply_issue.py +0 -315
- data/vendor/depot_tools/man/html/git-cherry-pick-upload.html +0 -815
- data/vendor/depot_tools/man/man1/git-cherry-pick-upload.1 +0 -80
- data/vendor/depot_tools/man/src/_git-cherry-pick-upload_desc.helper.txt +0 -1
- data/vendor/depot_tools/man/src/git-cherry-pick-upload.demo.1.sh +0 -17
- data/vendor/depot_tools/man/src/git-cherry-pick-upload.txt +0 -35
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/trychange_oauth2.json +0 -8
- data/vendor/depot_tools/recipes/recipe_modules/bot_update/examples/full.expected/trychange_oauth2_json_win.json +0 -196
- data/vendor/depot_tools/recipes/recipe_modules/rietveld/__init__.py +0 -6
- data/vendor/depot_tools/recipes/recipe_modules/rietveld/api.py +0 -97
- data/vendor/depot_tools/recipes/recipe_modules/rietveld/examples/full.expected/basic.json +0 -8
- data/vendor/depot_tools/recipes/recipe_modules/rietveld/examples/full.expected/buildbot.json +0 -30
- data/vendor/depot_tools/recipes/recipe_modules/rietveld/examples/full.expected/no_auth.json +0 -27
- data/vendor/depot_tools/recipes/recipe_modules/rietveld/examples/full.py +0 -38
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_rietveld_patch.json +0 -69
- data/vendor/depot_tools/recipes/recipe_modules/tryserver/examples/full.expected/with_rietveld_patch_new.json +0 -69
- data/vendor/depot_tools/third_party/cq_client/OWNERS +0 -2
- data/vendor/depot_tools/third_party/cq_client/README.depot_tools.md +0 -2
- data/vendor/depot_tools/third_party/cq_client/README.md +0 -59
- data/vendor/depot_tools/third_party/cq_client/__init__.py +0 -3
- data/vendor/depot_tools/third_party/cq_client/v1/__init__.py +0 -3
- data/vendor/depot_tools/third_party/cq_client/v1/cq.pb.go +0 -810
- data/vendor/depot_tools/third_party/cq_client/v1/cq.proto +0 -281
- data/vendor/depot_tools/third_party/cq_client/v1/cq_pb2.py +0 -794
- data/vendor/depot_tools/third_party/cq_client/v1/testdata/cq_both.cfg +0 -71
- data/vendor/depot_tools/third_party/cq_client/v1/testdata/cq_gerrit.cfg +0 -58
- data/vendor/depot_tools/third_party/cq_client/v1/testdata/cq_rietveld.cfg +0 -60
- data/vendor/depot_tools/third_party/cq_client/v2/__init__.py +0 -3
- data/vendor/depot_tools/third_party/cq_client/v2/cq.pb.go +0 -792
- data/vendor/depot_tools/third_party/cq_client/v2/cq.proto +0 -270
- data/vendor/depot_tools/third_party/cq_client/v2/cq_pb2.py +0 -841
@@ -14,9 +14,6 @@ Example:
|
|
14
14
|
- my_activity.py -jd to output stats for the week to json with deltas data.
|
15
15
|
"""
|
16
16
|
|
17
|
-
# TODO(vadimsh): This script knows too much about ClientLogin and cookies. It
|
18
|
-
# will stop to work on ~20 Apr 2015.
|
19
|
-
|
20
17
|
# These services typically only provide a created time and a last modified time
|
21
18
|
# for each item for general queries. This is not enough to determine if there
|
22
19
|
# was activity in a given time period. So, we first query for all things created
|
@@ -24,11 +21,15 @@ Example:
|
|
24
21
|
# check those details to determine if there was activity in the given period.
|
25
22
|
# This means that query time scales mostly with (today() - begin).
|
26
23
|
|
24
|
+
import collections
|
25
|
+
import contextlib
|
27
26
|
from datetime import datetime
|
28
27
|
from datetime import timedelta
|
29
28
|
from functools import partial
|
29
|
+
import itertools
|
30
30
|
import json
|
31
31
|
import logging
|
32
|
+
from multiprocessing.pool import ThreadPool
|
32
33
|
import optparse
|
33
34
|
import os
|
34
35
|
import subprocess
|
@@ -112,27 +113,23 @@ gerrit_instances = [
|
|
112
113
|
},
|
113
114
|
]
|
114
115
|
|
115
|
-
|
116
|
-
{
|
117
|
-
'name': 'chromium',
|
116
|
+
monorail_projects = {
|
117
|
+
'chromium': {
|
118
118
|
'shorturl': 'crbug.com',
|
119
119
|
'short_url_protocol': 'https',
|
120
120
|
},
|
121
|
-
{
|
122
|
-
|
123
|
-
},
|
124
|
-
{
|
125
|
-
'name': 'gyp',
|
126
|
-
},
|
127
|
-
{
|
128
|
-
'name': 'skia',
|
129
|
-
},
|
130
|
-
{
|
131
|
-
'name': 'pdfium',
|
121
|
+
'google-breakpad': {},
|
122
|
+
'gyp': {},
|
123
|
+
'skia': {},
|
124
|
+
'pdfium': {
|
132
125
|
'shorturl': 'crbug.com/pdfium',
|
133
126
|
'short_url_protocol': 'https',
|
134
127
|
},
|
135
|
-
|
128
|
+
'v8': {
|
129
|
+
'shorturl': 'crbug.com/v8',
|
130
|
+
'short_url_protocol': 'https',
|
131
|
+
},
|
132
|
+
}
|
136
133
|
|
137
134
|
def username(email):
|
138
135
|
"""Keeps the username of an email address."""
|
@@ -183,8 +180,8 @@ def datetime_from_rietveld(date_string):
|
|
183
180
|
return datetime.strptime(date_string, '%Y-%m-%d %H:%M:%S')
|
184
181
|
|
185
182
|
|
186
|
-
def
|
187
|
-
return datetime.strptime(date_string, '%Y-%m-%dT%H:%M:%S
|
183
|
+
def datetime_from_monorail(date_string):
|
184
|
+
return datetime.strptime(date_string, '%Y-%m-%dT%H:%M:%S')
|
188
185
|
|
189
186
|
|
190
187
|
class MyActivity(object):
|
@@ -196,8 +193,15 @@ class MyActivity(object):
|
|
196
193
|
self.changes = []
|
197
194
|
self.reviews = []
|
198
195
|
self.issues = []
|
196
|
+
self.referenced_issues = []
|
199
197
|
self.check_cookies()
|
200
198
|
self.google_code_auth_token = None
|
199
|
+
self.access_errors = set()
|
200
|
+
|
201
|
+
def show_progress(self, how='.'):
|
202
|
+
if sys.stdout.isatty():
|
203
|
+
sys.stdout.write(how)
|
204
|
+
sys.stdout.flush()
|
201
205
|
|
202
206
|
# Check the codereview cookie jar to determine which Rietveld instances to
|
203
207
|
# authenticate to.
|
@@ -247,6 +251,7 @@ class MyActivity(object):
|
|
247
251
|
reviewer=reviewer_email,
|
248
252
|
modified_after=query_modified_after,
|
249
253
|
with_messages=True)
|
254
|
+
self.show_progress()
|
250
255
|
|
251
256
|
issues = filter(
|
252
257
|
lambda i: (datetime_from_rietveld(i['created']) < self.modified_before),
|
@@ -279,11 +284,14 @@ class MyActivity(object):
|
|
279
284
|
if description:
|
280
285
|
# Handle both "Bug: 99999" and "BUG=99999" bug notations
|
281
286
|
# Multiple bugs can be noted on a single line or in multiple ones.
|
282
|
-
matches = re.findall(
|
283
|
-
|
287
|
+
matches = re.findall(
|
288
|
+
r'BUG[=:]\s?((((?:[a-zA-Z0-9-]+:)?\d+)(,\s?)?)+)', description,
|
289
|
+
flags=re.IGNORECASE)
|
284
290
|
if matches:
|
285
291
|
for match in matches:
|
286
292
|
bugs.extend(match[0].replace(' ', '').split(','))
|
293
|
+
# Add default chromium: prefix if none specified.
|
294
|
+
bugs = [bug if ':' in bug else 'chromium:%s' % bug for bug in bugs]
|
287
295
|
|
288
296
|
return bugs
|
289
297
|
|
@@ -293,6 +301,7 @@ class MyActivity(object):
|
|
293
301
|
patchset_props = remote.get_patchset_properties(
|
294
302
|
issue['issue'],
|
295
303
|
issue['patchsets'][-1])
|
304
|
+
self.show_progress()
|
296
305
|
ret['delta'] = '+%d,-%d' % (
|
297
306
|
sum(f['num_added'] for f in patchset_props['files'].itervalues()),
|
298
307
|
sum(f['num_removed'] for f in patchset_props['files'].itervalues()))
|
@@ -327,7 +336,7 @@ class MyActivity(object):
|
|
327
336
|
ret['created'] = datetime_from_rietveld(issue['created'])
|
328
337
|
ret['replies'] = self.process_rietveld_replies(issue['messages'])
|
329
338
|
|
330
|
-
ret['
|
339
|
+
ret['bugs'] = self.extract_bug_number_from_description(issue)
|
331
340
|
ret['landed_days_ago'] = issue['landed_days_ago']
|
332
341
|
|
333
342
|
return ret
|
@@ -343,8 +352,7 @@ class MyActivity(object):
|
|
343
352
|
ret.append(r)
|
344
353
|
return ret
|
345
354
|
|
346
|
-
|
347
|
-
def gerrit_changes_over_rest(instance, filters):
|
355
|
+
def gerrit_changes_over_rest(self, instance, filters):
|
348
356
|
# Convert the "key:value" filter to a list of (key, value) pairs.
|
349
357
|
req = list(f.split(':', 1) for f in filters)
|
350
358
|
try:
|
@@ -354,7 +362,9 @@ class MyActivity(object):
|
|
354
362
|
o_params=['MESSAGES', 'LABELS', 'DETAILED_ACCOUNTS',
|
355
363
|
'CURRENT_REVISION', 'CURRENT_COMMIT']))
|
356
364
|
except gerrit_util.GerritError, e:
|
357
|
-
|
365
|
+
error_message = 'Looking up %r: %s' % (instance['url'], e)
|
366
|
+
if error_message not in self.access_errors:
|
367
|
+
self.access_errors.add(error_message)
|
358
368
|
return []
|
359
369
|
|
360
370
|
def gerrit_search(self, instance, owner=None, reviewer=None):
|
@@ -364,6 +374,7 @@ class MyActivity(object):
|
|
364
374
|
filters = ['-age:%ss' % max_age, user_filter]
|
365
375
|
|
366
376
|
issues = self.gerrit_changes_over_rest(instance, filters)
|
377
|
+
self.show_progress()
|
367
378
|
issues = [self.process_gerrit_issue(instance, issue)
|
368
379
|
for issue in issues]
|
369
380
|
|
@@ -399,7 +410,7 @@ class MyActivity(object):
|
|
399
410
|
ret['replies'] = []
|
400
411
|
ret['reviewers'] = set(r['author'] for r in ret['replies'])
|
401
412
|
ret['reviewers'].discard(ret['author'])
|
402
|
-
ret['
|
413
|
+
ret['bugs'] = self.extract_bug_number_from_description(issue)
|
403
414
|
return ret
|
404
415
|
|
405
416
|
@staticmethod
|
@@ -415,64 +426,114 @@ class MyActivity(object):
|
|
415
426
|
})
|
416
427
|
return ret
|
417
428
|
|
418
|
-
def
|
429
|
+
def monorail_get_auth_http(self):
|
419
430
|
auth_config = auth.extract_auth_config_from_options(self.options)
|
420
431
|
authenticator = auth.get_authenticator_for_host(
|
421
432
|
'bugs.chromium.org', auth_config)
|
422
|
-
|
433
|
+
return authenticator.authorize(httplib2.Http())
|
434
|
+
|
435
|
+
def filter_modified_monorail_issue(self, issue):
|
436
|
+
"""Precisely checks if an issue has been modified in the time range.
|
437
|
+
|
438
|
+
This fetches all issue comments to check if the issue has been modified in
|
439
|
+
the time range specified by user. This is needed because monorail only
|
440
|
+
allows filtering by last updated and published dates, which is not
|
441
|
+
sufficient to tell whether a given issue has been modified at some specific
|
442
|
+
time range. Any update to the issue is a reported as comment on Monorail.
|
443
|
+
|
444
|
+
Args:
|
445
|
+
issue: Issue dict as returned by monorail_query_issues method. In
|
446
|
+
particular, must have a key 'uid' formatted as 'project:issue_id'.
|
447
|
+
|
448
|
+
Returns:
|
449
|
+
Passed issue if modified, None otherwise.
|
450
|
+
"""
|
451
|
+
http = self.monorail_get_auth_http()
|
452
|
+
project, issue_id = issue['uid'].split(':')
|
423
453
|
url = ('https://monorail-prod.appspot.com/_ah/api/monorail/v1/projects'
|
424
|
-
'/%s/issues') %
|
425
|
-
|
426
|
-
|
454
|
+
'/%s/issues/%s/comments?maxResults=10000') % (project, issue_id)
|
455
|
+
_, body = http.request(url)
|
456
|
+
self.show_progress()
|
457
|
+
content = json.loads(body)
|
458
|
+
if not content:
|
459
|
+
logging.error('Unable to parse %s response from monorail.', project)
|
460
|
+
return issue
|
427
461
|
|
428
|
-
|
429
|
-
'
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
462
|
+
for item in content.get('items', []):
|
463
|
+
comment_published = datetime_from_monorail(item['published'])
|
464
|
+
if self.filter_modified(comment_published):
|
465
|
+
return issue
|
466
|
+
|
467
|
+
return None
|
468
|
+
|
469
|
+
def monorail_query_issues(self, project, query):
|
470
|
+
http = self.monorail_get_auth_http()
|
471
|
+
url = ('https://monorail-prod.appspot.com/_ah/api/monorail/v1/projects'
|
472
|
+
'/%s/issues') % project
|
473
|
+
query_data = urllib.urlencode(query)
|
434
474
|
url = url + '?' + query_data
|
435
475
|
_, body = http.request(url)
|
476
|
+
self.show_progress()
|
436
477
|
content = json.loads(body)
|
437
478
|
if not content:
|
438
|
-
logging.error('Unable to parse %s response from
|
439
|
-
instance['name'])
|
479
|
+
logging.error('Unable to parse %s response from monorail.', project)
|
440
480
|
return []
|
441
481
|
|
442
482
|
issues = []
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
483
|
+
project_config = monorail_projects.get(project, {})
|
484
|
+
for item in content.get('items', []):
|
485
|
+
if project_config.get('shorturl'):
|
486
|
+
protocol = project_config.get('short_url_protocol', 'http')
|
487
|
+
item_url = '%s://%s/%d' % (
|
488
|
+
protocol, project_config['shorturl'], item['id'])
|
489
|
+
else:
|
490
|
+
item_url = 'https://bugs.chromium.org/p/%s/issues/detail?id=%d' % (
|
491
|
+
project, item['id'])
|
492
|
+
issue = {
|
493
|
+
'uid': '%s:%s' % (project, item['id']),
|
494
|
+
'header': item['title'],
|
495
|
+
'created': datetime_from_monorail(item['published']),
|
496
|
+
'modified': datetime_from_monorail(item['updated']),
|
497
|
+
'author': item['author']['name'],
|
498
|
+
'url': item_url,
|
499
|
+
'comments': [],
|
500
|
+
'status': item['status'],
|
501
|
+
'labels': [],
|
502
|
+
'components': []
|
503
|
+
}
|
504
|
+
if 'owner' in item:
|
505
|
+
issue['owner'] = item['owner']['name']
|
506
|
+
else:
|
507
|
+
issue['owner'] = 'None'
|
508
|
+
if 'labels' in item:
|
509
|
+
issue['labels'] = item['labels']
|
510
|
+
if 'components' in item:
|
511
|
+
issue['components'] = item['components']
|
512
|
+
issues.append(issue)
|
473
513
|
|
474
514
|
return issues
|
475
515
|
|
516
|
+
def monorail_issue_search(self, project):
|
517
|
+
epoch = datetime.utcfromtimestamp(0)
|
518
|
+
user_str = '%s@chromium.org' % self.user
|
519
|
+
|
520
|
+
issues = self.monorail_query_issues(project, {
|
521
|
+
'maxResults': 10000,
|
522
|
+
'q': user_str,
|
523
|
+
'publishedMax': '%d' % (self.modified_before - epoch).total_seconds(),
|
524
|
+
'updatedMin': '%d' % (self.modified_after - epoch).total_seconds(),
|
525
|
+
})
|
526
|
+
|
527
|
+
return [
|
528
|
+
issue for issue in issues
|
529
|
+
if issue['author'] == user_str or issue['owner'] == user_str]
|
530
|
+
|
531
|
+
def monorail_get_issues(self, project, issue_ids):
|
532
|
+
return self.monorail_query_issues(project, {
|
533
|
+
'maxResults': 10000,
|
534
|
+
'q': 'id:%s' % ','.join(issue_ids)
|
535
|
+
})
|
536
|
+
|
476
537
|
def print_heading(self, heading):
|
477
538
|
print
|
478
539
|
print self.options.output_format_heading.format(heading=heading)
|
@@ -528,8 +589,12 @@ class MyActivity(object):
|
|
528
589
|
optional_values = {
|
529
590
|
'created': review['created'].date().isoformat(),
|
530
591
|
'modified': review['modified'].date().isoformat(),
|
592
|
+
'status': review['status'],
|
531
593
|
'activity': activity,
|
532
594
|
}
|
595
|
+
if self.options.deltas:
|
596
|
+
optional_values['delta'] = review['delta']
|
597
|
+
|
533
598
|
self.print_generic(self.options.output_format,
|
534
599
|
self.options.output_format_reviews,
|
535
600
|
review['header'],
|
@@ -588,26 +653,43 @@ class MyActivity(object):
|
|
588
653
|
pass
|
589
654
|
|
590
655
|
def get_changes(self):
|
591
|
-
|
592
|
-
|
593
|
-
|
594
|
-
|
595
|
-
|
656
|
+
num_instances = len(rietveld_instances) + len(gerrit_instances)
|
657
|
+
with contextlib.closing(ThreadPool(num_instances)) as pool:
|
658
|
+
rietveld_changes = pool.map_async(
|
659
|
+
lambda instance: self.rietveld_search(instance, owner=self.user),
|
660
|
+
rietveld_instances)
|
661
|
+
gerrit_changes = pool.map_async(
|
662
|
+
lambda instance: self.gerrit_search(instance, owner=self.user),
|
663
|
+
gerrit_instances)
|
664
|
+
rietveld_changes = itertools.chain.from_iterable(rietveld_changes.get())
|
665
|
+
gerrit_changes = itertools.chain.from_iterable(gerrit_changes.get())
|
666
|
+
self.changes = list(rietveld_changes) + list(gerrit_changes)
|
596
667
|
|
597
668
|
def print_changes(self):
|
598
669
|
if self.changes:
|
599
670
|
self.print_heading('Changes')
|
600
671
|
for change in self.changes:
|
601
|
-
|
672
|
+
self.print_change(change)
|
602
673
|
|
603
|
-
def
|
604
|
-
|
605
|
-
|
674
|
+
def print_access_errors(self):
|
675
|
+
if self.access_errors:
|
676
|
+
logging.error('Access Errors:')
|
677
|
+
for error in self.access_errors:
|
678
|
+
logging.error(error.rstrip())
|
606
679
|
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
680
|
+
def get_reviews(self):
|
681
|
+
num_instances = len(rietveld_instances) + len(gerrit_instances)
|
682
|
+
with contextlib.closing(ThreadPool(num_instances)) as pool:
|
683
|
+
rietveld_reviews = pool.map_async(
|
684
|
+
lambda instance: self.rietveld_search(instance, reviewer=self.user),
|
685
|
+
rietveld_instances)
|
686
|
+
gerrit_reviews = pool.map_async(
|
687
|
+
lambda instance: self.gerrit_search(instance, reviewer=self.user),
|
688
|
+
gerrit_instances)
|
689
|
+
rietveld_reviews = itertools.chain.from_iterable(rietveld_reviews.get())
|
690
|
+
gerrit_reviews = itertools.chain.from_iterable(gerrit_reviews.get())
|
691
|
+
gerrit_reviews = [r for r in gerrit_reviews if r['owner'] != self.user]
|
692
|
+
self.reviews = list(rietveld_reviews) + list(gerrit_reviews)
|
611
693
|
|
612
694
|
def print_reviews(self):
|
613
695
|
if self.reviews:
|
@@ -616,8 +698,38 @@ class MyActivity(object):
|
|
616
698
|
self.print_review(review)
|
617
699
|
|
618
700
|
def get_issues(self):
|
619
|
-
|
620
|
-
|
701
|
+
with contextlib.closing(ThreadPool(len(monorail_projects))) as pool:
|
702
|
+
monorail_issues = pool.map(
|
703
|
+
self.monorail_issue_search, monorail_projects.keys())
|
704
|
+
monorail_issues = list(itertools.chain.from_iterable(monorail_issues))
|
705
|
+
|
706
|
+
if not monorail_issues:
|
707
|
+
return
|
708
|
+
|
709
|
+
with contextlib.closing(ThreadPool(len(monorail_issues))) as pool:
|
710
|
+
filtered_issues = pool.map(
|
711
|
+
self.filter_modified_monorail_issue, monorail_issues)
|
712
|
+
self.issues = [issue for issue in filtered_issues if issue]
|
713
|
+
|
714
|
+
def get_referenced_issues(self):
|
715
|
+
if not self.issues:
|
716
|
+
self.get_issues()
|
717
|
+
|
718
|
+
if not self.changes:
|
719
|
+
self.get_changes()
|
720
|
+
|
721
|
+
referenced_issue_uids = set(itertools.chain.from_iterable(
|
722
|
+
change['bugs'] for change in self.changes))
|
723
|
+
fetched_issue_uids = set(issue['uid'] for issue in self.issues)
|
724
|
+
missing_issue_uids = referenced_issue_uids - fetched_issue_uids
|
725
|
+
|
726
|
+
missing_issues_by_project = collections.defaultdict(list)
|
727
|
+
for issue_uid in missing_issue_uids:
|
728
|
+
project, issue_id = issue_uid.split(':')
|
729
|
+
missing_issues_by_project[project].append(issue_id)
|
730
|
+
|
731
|
+
for project, issue_ids in missing_issues_by_project.iteritems():
|
732
|
+
self.referenced_issues += self.monorail_get_issues(project, issue_ids)
|
621
733
|
|
622
734
|
def print_issues(self):
|
623
735
|
if self.issues:
|
@@ -625,6 +737,51 @@ class MyActivity(object):
|
|
625
737
|
for issue in self.issues:
|
626
738
|
self.print_issue(issue)
|
627
739
|
|
740
|
+
def print_changes_by_issue(self, skip_empty_own):
|
741
|
+
if not self.issues or not self.changes:
|
742
|
+
return
|
743
|
+
|
744
|
+
self.print_heading('Changes by referenced issue(s)')
|
745
|
+
issues = {issue['uid']: issue for issue in self.issues}
|
746
|
+
ref_issues = {issue['uid']: issue for issue in self.referenced_issues}
|
747
|
+
changes_by_issue_uid = collections.defaultdict(list)
|
748
|
+
changes_by_ref_issue_uid = collections.defaultdict(list)
|
749
|
+
changes_without_issue = []
|
750
|
+
for change in self.changes:
|
751
|
+
added = False
|
752
|
+
for issue_uid in change['bugs']:
|
753
|
+
if issue_uid in issues:
|
754
|
+
changes_by_issue_uid[issue_uid].append(change)
|
755
|
+
added = True
|
756
|
+
if issue_uid in ref_issues:
|
757
|
+
changes_by_ref_issue_uid[issue_uid].append(change)
|
758
|
+
added = True
|
759
|
+
if not added:
|
760
|
+
changes_without_issue.append(change)
|
761
|
+
|
762
|
+
# Changes referencing own issues.
|
763
|
+
for issue_uid in issues:
|
764
|
+
if changes_by_issue_uid[issue_uid] or not skip_empty_own:
|
765
|
+
self.print_issue(issues[issue_uid])
|
766
|
+
for change in changes_by_issue_uid[issue_uid]:
|
767
|
+
print '', # this prints one space due to comma, but no newline
|
768
|
+
self.print_change(change)
|
769
|
+
|
770
|
+
# Changes referencing others' issues.
|
771
|
+
for issue_uid in ref_issues:
|
772
|
+
assert changes_by_ref_issue_uid[issue_uid]
|
773
|
+
self.print_issue(ref_issues[issue_uid])
|
774
|
+
for change in changes_by_ref_issue_uid[issue_uid]:
|
775
|
+
print '', # this prints one space due to comma, but no newline
|
776
|
+
self.print_change(change)
|
777
|
+
|
778
|
+
# Changes referencing no issues.
|
779
|
+
if changes_without_issue:
|
780
|
+
print self.options.output_format_no_url.format(title='Other changes')
|
781
|
+
for change in changes_without_issue:
|
782
|
+
print '', # this prints one space due to comma, but no newline
|
783
|
+
self.print_change(change)
|
784
|
+
|
628
785
|
def print_activity(self):
|
629
786
|
self.print_changes()
|
630
787
|
self.print_reviews()
|
@@ -697,7 +854,19 @@ def main():
|
|
697
854
|
parser.add_option(
|
698
855
|
'-d', '--deltas',
|
699
856
|
action='store_true',
|
700
|
-
help='Fetch deltas for changes
|
857
|
+
help='Fetch deltas for changes.')
|
858
|
+
parser.add_option(
|
859
|
+
'--no-referenced-issues',
|
860
|
+
action='store_true',
|
861
|
+
help='Do not fetch issues referenced by owned changes. Useful in '
|
862
|
+
'combination with --changes-by-issue when you only want to list '
|
863
|
+
'issues that have also been modified in the same time period.')
|
864
|
+
parser.add_option(
|
865
|
+
'--skip-own-issues-without-changes',
|
866
|
+
action='store_true',
|
867
|
+
help='Skips listing own issues without changes when showing changes '
|
868
|
+
'grouped by referenced issue(s). See --changes-by-issue for more '
|
869
|
+
'details.')
|
701
870
|
|
702
871
|
activity_types_group = optparse.OptionGroup(parser, 'Activity Types',
|
703
872
|
'By default, all activity will be looked up and '
|
@@ -715,6 +884,9 @@ def main():
|
|
715
884
|
'-r', '--reviews',
|
716
885
|
action='store_true',
|
717
886
|
help='Show reviews.')
|
887
|
+
activity_types_group.add_option(
|
888
|
+
'--changes-by-issue', action='store_true',
|
889
|
+
help='Show changes grouped by referenced issue(s).')
|
718
890
|
parser.add_option_group(activity_types_group)
|
719
891
|
|
720
892
|
output_format_group = optparse.OptionGroup(parser, 'Output Format',
|
@@ -749,6 +921,9 @@ def main():
|
|
749
921
|
'--output-format-heading', metavar='<format>',
|
750
922
|
default=u'{heading}:',
|
751
923
|
help='Specifies the format to use when printing headings.')
|
924
|
+
output_format_group.add_option(
|
925
|
+
'--output-format-no-url', default='{title}',
|
926
|
+
help='Specifies the format to use when printing activity without url.')
|
752
927
|
output_format_group.add_option(
|
753
928
|
'-m', '--markdown', action='store_true',
|
754
929
|
help='Use markdown-friendly output (overrides --output-format '
|
@@ -821,19 +996,22 @@ def main():
|
|
821
996
|
if options.markdown:
|
822
997
|
options.output_format = ' * [{title}]({url})'
|
823
998
|
options.output_format_heading = '### {heading} ###'
|
999
|
+
options.output_format_no_url = ' * {title}'
|
824
1000
|
logging.info('Searching for activity by %s', options.user)
|
825
1001
|
logging.info('Using range %s to %s', options.begin, options.end)
|
826
1002
|
|
827
1003
|
my_activity = MyActivity(options)
|
1004
|
+
my_activity.show_progress('Loading data')
|
828
1005
|
|
829
|
-
if not (options.changes or options.reviews or options.issues
|
1006
|
+
if not (options.changes or options.reviews or options.issues or
|
1007
|
+
options.changes_by_issue):
|
830
1008
|
options.changes = True
|
831
1009
|
options.issues = True
|
832
1010
|
options.reviews = True
|
833
1011
|
|
834
1012
|
# First do any required authentication so none of the user interaction has to
|
835
1013
|
# wait for actual work.
|
836
|
-
if options.changes:
|
1014
|
+
if options.changes or options.changes_by_issue:
|
837
1015
|
my_activity.auth_for_changes()
|
838
1016
|
if options.reviews:
|
839
1017
|
my_activity.auth_for_reviews()
|
@@ -841,15 +1019,21 @@ def main():
|
|
841
1019
|
logging.info('Looking up activity.....')
|
842
1020
|
|
843
1021
|
try:
|
844
|
-
if options.changes:
|
1022
|
+
if options.changes or options.changes_by_issue:
|
845
1023
|
my_activity.get_changes()
|
846
1024
|
if options.reviews:
|
847
1025
|
my_activity.get_reviews()
|
848
|
-
if options.issues:
|
1026
|
+
if options.issues or options.changes_by_issue:
|
849
1027
|
my_activity.get_issues()
|
1028
|
+
if not options.no_referenced_issues:
|
1029
|
+
my_activity.get_referenced_issues()
|
850
1030
|
except auth.AuthenticationError as e:
|
851
1031
|
logging.error('auth.AuthenticationError: %s', e)
|
852
1032
|
|
1033
|
+
my_activity.show_progress('\n')
|
1034
|
+
|
1035
|
+
my_activity.print_access_errors()
|
1036
|
+
|
853
1037
|
output_file = None
|
854
1038
|
try:
|
855
1039
|
if options.output:
|
@@ -862,9 +1046,15 @@ def main():
|
|
862
1046
|
if options.json:
|
863
1047
|
my_activity.dump_json()
|
864
1048
|
else:
|
865
|
-
|
866
|
-
|
867
|
-
|
1049
|
+
if options.changes:
|
1050
|
+
my_activity.print_changes()
|
1051
|
+
if options.reviews:
|
1052
|
+
my_activity.print_reviews()
|
1053
|
+
if options.issues:
|
1054
|
+
my_activity.print_issues()
|
1055
|
+
if options.changes_by_issue:
|
1056
|
+
my_activity.print_changes_by_issue(
|
1057
|
+
options.skip_own_issues_without_changes)
|
868
1058
|
finally:
|
869
1059
|
if output_file:
|
870
1060
|
logging.info('Done printing to file.')
|