blob: 656a15314e1f5b7c1dae6a12afb2b39505e4e89f [file] [log] [blame]
commit-bot@chromium.org58af0c82014-04-01 19:03:19 +00001#!/usr/bin/python
2# Copyright (c) 2014 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6
7"""Find and display recent changes in the given GM.
8
9Example usage:
10
11$ python gm/show_gm_changes.py Test-Mac10.7-MacMini4.1-GeForce320M-x86-Debug \
12shadertext_gpu --autogen-path .gm-actuals
13
14Rev Hash
1515990 10904734222736193002
1610729 10752292282035416719
178504 2915063876615374518
1871 7546128203733045901
19"""
20
21
22import argparse
23import json
24import os
25import re
26import subprocess
27import sys
28
29
30def _get_hash_and_last_change(gm_name, filepath):
31 """Find the current hash for the given GM and the last-changed revision.
32
33 This function runs "svn blame", which is slow.
34
35 Args:
36 gm_name: string; name of the GM in question.
37 filepath: string; path to the actual-results.json file.
38 Returns:
39 tuple of the form (last_changed_rev, hash), where last_changed_rev is an
40 int and hash is a string, or (None, None) if the file does not exist, the
41 GM is not found in the file, or some other problem occurs.
42 """
43 if not os.path.isfile(filepath):
44 # If the file doesn't exist, we may have synced to before it was created.
45 return (None, None)
46 output = subprocess.check_output(['svn', 'blame', '--force', filepath])
47 pattern = (r'^\s+\d+\s+.+\s+"%s.png" : {\s*\n\s+\d+\s+.+\s+"allowed-digests" '
48 ': \[\s*\n\s+(\d+)\s+.+\s+\[ "bitmap-64bitMD5",\s+\n*(\d+)')
49 match = re.search(pattern % gm_name, output, re.MULTILINE)
50 if match:
51 try:
52 return (int(match.groups()[0]), match.groups()[1])
53 except Exception:
54 # If there are any problems with the above (incorrect number of matches,
55 # inability to parse an integer), just return None.
56 return (None, None)
57 return (None, None)
58
59
60def find_changes(builder_name, gm_name, autogen_path):
61 """Find and return recent changes in the given GM.
62
63 This function runs "svn blame" and "svn update" numerous times and is
64 therefore very slow.
65
66 Args:
67 builder_name: string; name of the builder.
68 gm_name: string; name of the GM.
69 autogen_path: string; path to skia-autogen checkout.
70 Yields:
71 tuples of the form: (autogen_revision, hash)
72 """
73 actuals_path = os.path.join(autogen_path, builder_name, 'actual-results.json')
74
75 # Capture the initial state of the skia-autogen checkout so that we can return
76 # to the same state later.
77 orig_rev = subprocess.check_output(['svnversion', '.'],
78 cwd=autogen_path).rstrip()
79
80 try:
81 last_change_rev, hash = _get_hash_and_last_change(gm_name, actuals_path)
82 while last_change_rev:
83 yield (str(last_change_rev), hash)
84 # Sync to the revision just *before* the last change
85 subprocess.check_call(['svn', 'update', '-r', str(last_change_rev - 1)],
86 cwd=autogen_path,
87 stdout=subprocess.PIPE,
88 stderr=subprocess.PIPE)
89 last_change_rev, hash = _get_hash_and_last_change(gm_name, actuals_path)
90 finally:
91 # Return the repository to its initial state.
92 subprocess.check_call(['svn', 'update', '-r', orig_rev],
93 cwd=autogen_path,
94 stdout=subprocess.PIPE,
95 stderr=subprocess.PIPE)
96
97
98def main():
99 """Find and display recent changes in the given GM."""
100 parser = argparse.ArgumentParser(description=sys.modules[__name__].__doc__)
101 parser.add_argument('builder_name', help='Name of the builder.')
102 parser.add_argument('gm_name', help='Name of the GM.')
103 parser.add_argument('--autogen-path', default=os.curdir,
104 help=('Path to a skia-autogen checkout. This checkout '
105 'will be modified but the script will attempt to '
106 'restore it to its original state. Default: '
107 '"%(default)s"'))
108 args = parser.parse_args()
109
110 print 'Rev\tHash'
111 for change in find_changes(args.builder_name, args.gm_name,
112 args.autogen_path):
113 print '\t'.join(change)
114
115
116if __name__ == '__main__':
117 sys.exit(main())