Add show_gm_changes script: show change revisions and hashes for a GM
authorcommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 1 Apr 2014 19:03:19 +0000 (19:03 +0000)
committercommit-bot@chromium.org <commit-bot@chromium.org@2bbb7eff-a529-9590-31e7-b0007b416f81>
Tue, 1 Apr 2014 19:03:19 +0000 (19:03 +0000)
BUG=skia:1920
R=epoger@google.com

Author: borenet@google.com

Review URL: https://codereview.chromium.org/213833017

git-svn-id: http://skia.googlecode.com/svn/trunk@14015 2bbb7eff-a529-9590-31e7-b0007b416f81

gm/show_gm_changes.py [new file with mode: 0755]

diff --git a/gm/show_gm_changes.py b/gm/show_gm_changes.py
new file mode 100755 (executable)
index 0000000..656a153
--- /dev/null
@@ -0,0 +1,117 @@
+#!/usr/bin/python
+# Copyright (c) 2014 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+
+"""Find and display recent changes in the given GM.
+
+Example usage:
+
+$ python gm/show_gm_changes.py Test-Mac10.7-MacMini4.1-GeForce320M-x86-Debug \
+shadertext_gpu --autogen-path .gm-actuals
+
+Rev    Hash
+15990  10904734222736193002
+10729  10752292282035416719
+8504   2915063876615374518
+71     7546128203733045901
+"""
+
+
+import argparse
+import json
+import os
+import re
+import subprocess
+import sys
+
+
+def _get_hash_and_last_change(gm_name, filepath):
+  """Find the current hash for the given GM and the last-changed revision.
+
+  This function runs "svn blame", which is slow.
+
+  Args:
+      gm_name: string; name of the GM in question.
+      filepath: string; path to the actual-results.json file.
+  Returns:
+      tuple of the form (last_changed_rev, hash), where last_changed_rev is an
+      int and hash is a string, or (None, None) if the file does not exist, the
+      GM is not found in the file, or some other problem occurs. 
+  """
+  if not os.path.isfile(filepath):
+    # If the file doesn't exist, we may have synced to before it was created.
+    return (None, None)
+  output = subprocess.check_output(['svn', 'blame', '--force', filepath])
+  pattern = (r'^\s+\d+\s+.+\s+"%s.png" : {\s*\n\s+\d+\s+.+\s+"allowed-digests" '
+             ': \[\s*\n\s+(\d+)\s+.+\s+\[ "bitmap-64bitMD5",\s+\n*(\d+)')
+  match = re.search(pattern % gm_name, output, re.MULTILINE)
+  if match:
+    try:
+      return (int(match.groups()[0]), match.groups()[1])
+    except Exception:
+      # If there are any problems with the above (incorrect number of matches,
+      # inability to parse an integer), just return None.
+      return (None, None)
+  return (None, None)
+
+
+def find_changes(builder_name, gm_name, autogen_path):
+  """Find and return recent changes in the given GM.
+
+  This function runs "svn blame" and "svn update" numerous times and is
+  therefore very slow.
+
+  Args:
+      builder_name: string; name of the builder.
+      gm_name: string; name of the GM.
+      autogen_path: string; path to skia-autogen checkout.
+  Yields:
+      tuples of the form: (autogen_revision, hash)
+  """
+  actuals_path = os.path.join(autogen_path, builder_name, 'actual-results.json')
+
+  # Capture the initial state of the skia-autogen checkout so that we can return
+  # to the same state later.
+  orig_rev = subprocess.check_output(['svnversion', '.'],
+                                     cwd=autogen_path).rstrip()
+
+  try:
+    last_change_rev, hash = _get_hash_and_last_change(gm_name, actuals_path)
+    while last_change_rev:
+      yield (str(last_change_rev), hash)
+      # Sync to the revision just *before* the last change
+      subprocess.check_call(['svn', 'update', '-r', str(last_change_rev - 1)],
+                            cwd=autogen_path,
+                            stdout=subprocess.PIPE,
+                            stderr=subprocess.PIPE)
+      last_change_rev, hash = _get_hash_and_last_change(gm_name, actuals_path)
+  finally:
+    # Return the repository to its initial state.
+    subprocess.check_call(['svn', 'update', '-r', orig_rev],
+                          cwd=autogen_path,
+                          stdout=subprocess.PIPE,
+                          stderr=subprocess.PIPE)
+
+
+def main():
+  """Find and display recent changes in the given GM."""
+  parser = argparse.ArgumentParser(description=sys.modules[__name__].__doc__)
+  parser.add_argument('builder_name', help='Name of the builder.')
+  parser.add_argument('gm_name', help='Name of the GM.')
+  parser.add_argument('--autogen-path', default=os.curdir,
+                      help=('Path to a skia-autogen checkout. This checkout '
+                            'will be modified but the script will attempt to '
+                            'restore it to its original state. Default: '
+                            '"%(default)s"'))
+  args = parser.parse_args()
+
+  print 'Rev\tHash'
+  for change in find_changes(args.builder_name, args.gm_name,
+                             args.autogen_path):
+    print '\t'.join(change)
+  
+
+if __name__ == '__main__':
+  sys.exit(main())