| OLD | NEW |
| (Empty) |
| 1 #!/usr/bin/env python | |
| 2 # Copyright (c) 2012 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 """ This module contains miscellaneous tools used by the buildbot scripts. """ | |
| 7 | |
| 8 import os | |
| 9 | |
| 10 from git_utils import GIT | |
| 11 import shell_utils | |
| 12 | |
| 13 | |
| 14 # Absolute path to the root of this Skia buildbot checkout. | |
| 15 BUILDBOT_PATH = os.path.realpath(os.path.join( | |
| 16 os.path.dirname(os.path.abspath(__file__)), | |
| 17 os.pardir, os.pardir, os.pardir)) | |
| 18 | |
| 19 | |
| 20 def ArgsToDict(argv): | |
| 21 """ Collect command-line arguments of the form '--key value' into a | |
| 22 dictionary. Fail if the arguments do not fit this format. """ | |
| 23 dictionary = {} | |
| 24 PREFIX = '--' | |
| 25 # Expect the first arg to be the path to the script, which we don't want. | |
| 26 argv = argv[1:] | |
| 27 while argv: | |
| 28 if argv[0].startswith(PREFIX): | |
| 29 dictionary[argv[0][len(PREFIX):]] = argv[1] | |
| 30 argv = argv[2:] | |
| 31 else: | |
| 32 raise Exception('Malformed input: %s' % argv) | |
| 33 return dictionary | |
| 34 | |
| 35 | |
| 36 def ConfirmOptionsSet(name_value_dict): | |
| 37 """Raise an exception if any of the given command-line options were not set. | |
| 38 | |
| 39 name_value_dict: dictionary mapping option names to option values | |
| 40 """ | |
| 41 for (name, value) in name_value_dict.iteritems(): | |
| 42 if value is None: | |
| 43 raise Exception('missing command-line option %s; rerun with --help' % | |
| 44 name) | |
| 45 | |
| 46 | |
| 47 def GetAbsPath(relative_path): | |
| 48 """My own implementation of os.path.abspath() that better handles paths | |
| 49 which approach Window's 260-character limit. | |
| 50 See https://code.google.com/p/skia/issues/detail?id=674 | |
| 51 | |
| 52 This implementation adds path components one at a time, resolving the | |
| 53 absolute path each time, to take advantage of any chdirs into outer | |
| 54 directories that will shorten the total path length. | |
| 55 | |
| 56 TODO(epoger): share a single implementation with bench_graph_svg.py, instead | |
| 57 of pasting this same code into both files.""" | |
| 58 if os.path.isabs(relative_path): | |
| 59 return relative_path | |
| 60 path_parts = relative_path.split(os.sep) | |
| 61 abs_path = os.path.abspath('.') | |
| 62 for path_part in path_parts: | |
| 63 abs_path = os.path.abspath(os.path.join(abs_path, path_part)) | |
| 64 return abs_path | |
| 65 | |
| 66 | |
| 67 class ChDir(object): | |
| 68 """Enter and exit the given directory appropriately.""" | |
| 69 | |
| 70 def __init__(self, directory): | |
| 71 """Instantiate the ChDir. | |
| 72 | |
| 73 Args: | |
| 74 directory: string; the directory to enter. | |
| 75 """ | |
| 76 self._destination = directory | |
| 77 self._origin = None | |
| 78 | |
| 79 def __enter__(self): | |
| 80 """Change to the destination directory. | |
| 81 | |
| 82 Does not check whether the directory exists. | |
| 83 """ | |
| 84 self._origin = os.getcwd() | |
| 85 print 'chdir %s' % self._destination | |
| 86 os.chdir(self._destination) | |
| 87 | |
| 88 def __exit__(self, *args): | |
| 89 """Change back to the original directory.""" | |
| 90 print 'chdir %s' % self._origin | |
| 91 os.chdir(self._origin) | |
| 92 | |
| 93 | |
| 94 class GitBranch(object): | |
| 95 """Class to manage git branches. | |
| 96 | |
| 97 This class allows one to create a new branch in a repository to make changes, | |
| 98 then it commits the changes, switches to master branch, and deletes the | |
| 99 created temporary branch upon exit. | |
| 100 """ | |
| 101 def __init__(self, branch_name, commit_msg, upload=True, commit_queue=False): | |
| 102 self._branch_name = branch_name | |
| 103 self._commit_msg = commit_msg | |
| 104 self._upload = upload | |
| 105 self._commit_queue = commit_queue | |
| 106 self._patch_set = 0 | |
| 107 | |
| 108 def __enter__(self): | |
| 109 shell_utils.run([GIT, 'reset', '--hard', 'HEAD']) | |
| 110 shell_utils.run([GIT, 'checkout', 'master']) | |
| 111 if self._branch_name in shell_utils.run([GIT, 'branch']): | |
| 112 shell_utils.run([GIT, 'branch', '-D', self._branch_name]) | |
| 113 shell_utils.run([GIT, 'checkout', '-b', self._branch_name, | |
| 114 '-t', 'origin/master']) | |
| 115 return self | |
| 116 | |
| 117 def commit_and_upload(self, use_commit_queue=False): | |
| 118 shell_utils.run([GIT, 'commit', '-a', '-m', | |
| 119 self._commit_msg]) | |
| 120 upload_cmd = [GIT, 'cl', 'upload', '-f', '--bypass-hooks', | |
| 121 '--bypass-watchlists'] | |
| 122 self._patch_set += 1 | |
| 123 if self._patch_set > 1: | |
| 124 upload_cmd.extend(['-t', 'Patch set %d' % self._patch_set]) | |
| 125 if use_commit_queue: | |
| 126 upload_cmd.append('--use-commit-queue') | |
| 127 shell_utils.run(upload_cmd) | |
| 128 | |
| 129 def __exit__(self, exc_type, _value, _traceback): | |
| 130 if self._upload: | |
| 131 # Only upload if no error occurred. | |
| 132 try: | |
| 133 if exc_type is None: | |
| 134 self.commit_and_upload(use_commit_queue=self._commit_queue) | |
| 135 finally: | |
| 136 shell_utils.run([GIT, 'checkout', 'master']) | |
| 137 shell_utils.run([GIT, 'branch', '-D', self._branch_name]) | |
| 138 | |
| OLD | NEW |