Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(327)

Side by Side Diff: tools/roll_deps.py

Issue 141483011: add_codereview_message script to append messages to a CL (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: linting Created 6 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« tools/git_utils.py ('K') | « tools/misc_utils.py ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python2 1 #!/usr/bin/python2
2 2
3 # Copyright 2014 Google Inc. 3 # Copyright 2014 Google Inc.
4 # 4 #
5 # Use of this source code is governed by a BSD-style license that can be 5 # Use of this source code is governed by a BSD-style license that can be
6 # found in the LICENSE file. 6 # found in the LICENSE file.
7 7
8 """Skia's Chromium DEPS roll script. 8 """Skia's Chromium DEPS roll script.
9 9
10 This script: 10 This script:
(...skipping 11 matching lines...) Expand all
22 22
23 23
24 import optparse 24 import optparse
25 import os 25 import os
26 import re 26 import re
27 import shutil 27 import shutil
28 import subprocess 28 import subprocess
29 import sys 29 import sys
30 import tempfile 30 import tempfile
31 31
32 import git_utils
33 import misc_utils
34
32 35
33 DEFAULT_BOTS_LIST = [ 36 DEFAULT_BOTS_LIST = [
34 'android_clang_dbg', 37 'android_clang_dbg',
35 'android_dbg', 38 'android_dbg',
36 'android_rel', 39 'android_rel',
37 'cros_daisy', 40 'cros_daisy',
38 'linux', 41 'linux',
39 'linux_asan', 42 'linux_asan',
40 'linux_chromeos', 43 'linux_chromeos',
41 'linux_chromeos_asan', 44 'linux_chromeos_asan',
(...skipping 29 matching lines...) Expand all
71 # pylint: disable=I0011,R0903,R0902 74 # pylint: disable=I0011,R0903,R0902
72 def __init__(self, options=None): 75 def __init__(self, options=None):
73 self.skia_url = 'https://skia.googlesource.com/skia.git' 76 self.skia_url = 'https://skia.googlesource.com/skia.git'
74 self.revision_format = ( 77 self.revision_format = (
75 'git-svn-id: http://skia.googlecode.com/svn/trunk@%d ') 78 'git-svn-id: http://skia.googlecode.com/svn/trunk@%d ')
76 79
77 if not options: 80 if not options:
78 options = DepsRollConfig.GetOptionParser() 81 options = DepsRollConfig.GetOptionParser()
79 # pylint: disable=I0011,E1103 82 # pylint: disable=I0011,E1103
80 self.verbose = options.verbose 83 self.verbose = options.verbose
81 self.vsp = VerboseSubprocess(self.verbose) 84 self.vsp = misc_utils.VerboseSubprocess(self.verbose)
82 self.save_branches = not options.delete_branches 85 self.save_branches = not options.delete_branches
83 self.search_depth = options.search_depth 86 self.search_depth = options.search_depth
84 self.chromium_path = options.chromium_path 87 self.chromium_path = options.chromium_path
85 self.git = options.git_path 88 self.git = options.git_path
86 self.skip_cl_upload = options.skip_cl_upload 89 self.skip_cl_upload = options.skip_cl_upload
87 # Split and remove empty strigns from the bot list. 90 # Split and remove empty strigns from the bot list.
88 self.cl_bot_list = [bot for bot in options.bots.split(',') if bot] 91 self.cl_bot_list = [bot for bot in options.bots.split(',') if bot]
89 self.skia_git_checkout_path = options.skia_git_path 92 self.skia_git_checkout_path = options.skia_git_path
90 self.default_branch_name = 'autogenerated_deps_roll_branch' 93 self.default_branch_name = 'autogenerated_deps_roll_branch'
91 self.reviewers_list = ','.join([ 94 self.reviewers_list = ','.join([
92 # 'rmistry@google.com', 95 # 'rmistry@google.com',
93 # 'reed@google.com', 96 # 'reed@google.com',
94 # 'bsalomon@google.com', 97 # 'bsalomon@google.com',
95 # 'robertphillips@google.com', 98 # 'robertphillips@google.com',
96 ]) 99 ])
97 self.cc_list = ','.join([ 100 self.cc_list = ','.join([
98 # 'skia-team@google.com', 101 # 'skia-team@google.com',
99 ]) 102 ])
100 103
101 @staticmethod 104 @staticmethod
102 def GetOptionParser(): 105 def GetOptionParser():
103 # pylint: disable=I0011,C0103 106 # pylint: disable=I0011,C0103
104 """Returns an optparse.OptionParser object. 107 """Returns an optparse.OptionParser object.
105 108
106 Returns: 109 Returns:
107 An optparse.OptionParser object. 110 An optparse.OptionParser object.
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
152 'Comma-separated list of bots, defaults to a list of %d bots.' 155 'Comma-separated list of bots, defaults to a list of %d bots.'
153 ' To skip `git cl try`, set this to an empty string.' 156 ' To skip `git cl try`, set this to an empty string.'
154 % len(DEFAULT_BOTS_LIST)) 157 % len(DEFAULT_BOTS_LIST))
155 default_bots = ','.join(DEFAULT_BOTS_LIST) 158 default_bots = ','.join(DEFAULT_BOTS_LIST)
156 option_parser.add_option( 159 option_parser.add_option(
157 '', '--bots', help=default_bots_help, default=default_bots) 160 '', '--bots', help=default_bots_help, default=default_bots)
158 161
159 return option_parser 162 return option_parser
160 163
161 164
162 def test_git_executable(git_executable):
163 """Test the git executable.
164
165 Args:
166 git_executable: git executable path.
167 Returns:
168 True if test is successful.
169 """
170 with open(os.devnull, 'w') as devnull:
171 try:
172 subprocess.call([git_executable, '--version'], stdout=devnull)
173 except (OSError,):
174 return False
175 return True
176
177
178 class DepsRollError(Exception): 165 class DepsRollError(Exception):
179 """Exceptions specific to this module.""" 166 """Exceptions specific to this module."""
180 pass 167 pass
181 168
182 169
183 class VerboseSubprocess(object):
184 """Call subprocess methods, but print out command before executing.
185
186 Attributes:
187 verbose: (boolean) should we print out the command or not. If
188 not, this is the same as calling the subprocess method
189 quiet: (boolean) suppress stdout on check_call and call.
190 prefix: (string) When verbose, what to print before each command.
191 """
192
193 def __init__(self, verbose):
194 self.verbose = verbose
195 self.quiet = not verbose
196 self.prefix = '~~$ '
197
198 @staticmethod
199 def _fix(string):
200 """Quote and escape a string if necessary."""
201 if ' ' in string or '\n' in string:
202 string = '"%s"' % string.replace('\n', '\\n')
203 return string
204
205 @staticmethod
206 def print_subprocess_args(prefix, *args, **kwargs):
207 """Print out args in a human-readable manner."""
208 if 'cwd' in kwargs:
209 print '%scd %s' % (prefix, kwargs['cwd'])
210 print prefix + ' '.join(VerboseSubprocess._fix(arg) for arg in args[0])
211 if 'cwd' in kwargs:
212 print '%scd -' % prefix
213
214 def check_call(self, *args, **kwargs):
215 """Wrapper for subprocess.check_call().
216
217 Args:
218 *args: to be passed to subprocess.check_call()
219 **kwargs: to be passed to subprocess.check_call()
220 Returns:
221 Whatever subprocess.check_call() returns.
222 Raises:
223 OSError or subprocess.CalledProcessError: raised by check_call.
224 """
225 if self.verbose:
226 self.print_subprocess_args(self.prefix, *args, **kwargs)
227 if self.quiet:
228 with open(os.devnull, 'w') as devnull:
229 return subprocess.check_call(*args, stdout=devnull, **kwargs)
230 else:
231 return subprocess.check_call(*args, **kwargs)
232
233 def call(self, *args, **kwargs):
234 """Wrapper for subprocess.check().
235
236 Args:
237 *args: to be passed to subprocess.check_call()
238 **kwargs: to be passed to subprocess.check_call()
239 Returns:
240 Whatever subprocess.call() returns.
241 Raises:
242 OSError or subprocess.CalledProcessError: raised by call.
243 """
244 if self.verbose:
245 self.print_subprocess_args(self.prefix, *args, **kwargs)
246 if self.quiet:
247 with open(os.devnull, 'w') as devnull:
248 return subprocess.call(*args, stdout=devnull, **kwargs)
249 else:
250 return subprocess.call(*args, **kwargs)
251
252 def check_output(self, *args, **kwargs):
253 """Wrapper for subprocess.check_output().
254
255 Args:
256 *args: to be passed to subprocess.check_output()
257 **kwargs: to be passed to subprocess.check_output()
258 Returns:
259 Whatever subprocess.check_output() returns.
260 Raises:
261 OSError or subprocess.CalledProcessError: raised by check_output.
262 """
263 if self.verbose:
264 self.print_subprocess_args(self.prefix, *args, **kwargs)
265 return subprocess.check_output(*args, **kwargs)
266
267 def strip_output(self, *args, **kwargs):
268 """Wrap subprocess.check_output and str.strip().
269
270 Pass the given arguments into subprocess.check_output() and return
271 the results, after stripping any excess whitespace.
272
273 Args:
274 *args: to be passed to subprocess.check_output()
275 **kwargs: to be passed to subprocess.check_output()
276
277 Returns:
278 The output of the process as a string without leading or
279 trailing whitespace.
280 Raises:
281 OSError or subprocess.CalledProcessError: raised by check_output.
282 """
283 if self.verbose:
284 self.print_subprocess_args(self.prefix, *args, **kwargs)
285 return str(subprocess.check_output(*args, **kwargs)).strip()
286
287 def popen(self, *args, **kwargs):
288 """Wrapper for subprocess.Popen().
289
290 Args:
291 *args: to be passed to subprocess.Popen()
292 **kwargs: to be passed to subprocess.Popen()
293 Returns:
294 The output of subprocess.Popen()
295 Raises:
296 OSError or subprocess.CalledProcessError: raised by Popen.
297 """
298 if self.verbose:
299 self.print_subprocess_args(self.prefix, *args, **kwargs)
300 return subprocess.Popen(*args, **kwargs)
301
302
303 class ChangeDir(object):
304 """Use with a with-statement to temporarily change directories."""
305 # pylint: disable=I0011,R0903
306
307 def __init__(self, directory, verbose=False):
308 self._directory = directory
309 self._verbose = verbose
310
311 def __enter__(self):
312 if self._verbose:
313 print '~~$ cd %s' % self._directory
314 cwd = os.getcwd()
315 os.chdir(self._directory)
316 self._directory = cwd
317
318 def __exit__(self, etype, value, traceback):
319 if self._verbose:
320 print '~~$ cd %s' % self._directory
321 os.chdir(self._directory)
322
323
324 class ReSearch(object):
325 """A collection of static methods for regexing things."""
326
327 @staticmethod
328 def search_within_stream(input_stream, pattern, default=None):
329 """Search for regular expression in a file-like object.
330
331 Opens a file for reading and searches line by line for a match to
332 the regex and returns the parenthesized group named return for the
333 first match. Does not search across newlines.
334
335 For example:
336 pattern = '^root(:[^:]*){4}:(?P<return>[^:]*)'
337 with open('/etc/passwd', 'r') as stream:
338 return search_within_file(stream, pattern)
339 should return root's home directory (/root on my system).
340
341 Args:
342 input_stream: file-like object to be read
343 pattern: (string) to be passed to re.compile
344 default: what to return if no match
345
346 Returns:
347 A string or whatever default is
348 """
349 pattern_object = re.compile(pattern)
350 for line in input_stream:
351 match = pattern_object.search(line)
352 if match:
353 return match.group('return')
354 return default
355
356 @staticmethod
357 def search_within_string(input_string, pattern, default=None):
358 """Search for regular expression in a string.
359
360 Args:
361 input_string: (string) to be searched
362 pattern: (string) to be passed to re.compile
363 default: what to return if no match
364
365 Returns:
366 A string or whatever default is
367 """
368 match = re.search(pattern, input_string)
369 return match.group('return') if match else default
370
371 @staticmethod
372 def search_within_output(verbose, pattern, default, *args, **kwargs):
373 """Search for regular expression in a process output.
374
375 Does not search across newlines.
376
377 Args:
378 verbose: (boolean) shoule we call
379 VerboseSubprocess.print_subprocess_args?
380 pattern: (string) to be passed to re.compile
381 default: what to return if no match
382 *args: to be passed to subprocess.Popen()
383 **kwargs: to be passed to subprocess.Popen()
384
385 Returns:
386 A string or whatever default is
387 """
388 if verbose:
389 VerboseSubprocess.print_subprocess_args(
390 '~~$ ', *args, **kwargs)
391 proc = subprocess.Popen(*args, stdout=subprocess.PIPE, **kwargs)
392 return ReSearch.search_within_stream(proc.stdout, pattern, default)
393
394
395 def get_svn_revision(config, commit): 170 def get_svn_revision(config, commit):
396 """Works in both git and git-svn. returns a string.""" 171 """Works in both git and git-svn. returns a string."""
397 svn_format = ( 172 svn_format = (
398 '(git-svn-id: [^@ ]+@|SVN changes up to revision |' 173 '(git-svn-id: [^@ ]+@|SVN changes up to revision |'
399 'LKGR w/ DEPS up to revision )(?P<return>[0-9]+)') 174 'LKGR w/ DEPS up to revision )(?P<return>[0-9]+)')
400 svn_revision = ReSearch.search_within_output( 175 svn_revision = misc_utils.ReSearch.search_within_output(
401 config.verbose, svn_format, None, 176 config.verbose, svn_format, None,
402 [config.git, 'log', '-n', '1', '--format=format:%B', commit]) 177 [config.git, 'log', '-n', '1', '--format=format:%B', commit])
403 if not svn_revision: 178 if not svn_revision:
404 raise DepsRollError( 179 raise DepsRollError(
405 'Revision number missing from Chromium origin/master.') 180 'Revision number missing from Chromium origin/master.')
406 return int(svn_revision) 181 return int(svn_revision)
407 182
408 183
409 class SkiaGitCheckout(object): 184 class SkiaGitCheckout(object):
410 """Class to create a temporary skia git checkout, if necessary. 185 """Class to create a temporary skia git checkout, if necessary.
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 """ 296 """
522 with SkiaGitCheckout(config, config.search_depth): 297 with SkiaGitCheckout(config, config.search_depth):
523 git_hash = config.vsp.strip_output( 298 git_hash = config.vsp.strip_output(
524 ['git', 'log', '-n', '1', '--format=format:%H', partial_hash]) 299 ['git', 'log', '-n', '1', '--format=format:%H', partial_hash])
525 if not git_hash: 300 if not git_hash:
526 raise DepsRollError('Partial Git hash can not be found.') 301 raise DepsRollError('Partial Git hash can not be found.')
527 revision = get_svn_revision(config, git_hash) 302 revision = get_svn_revision(config, git_hash)
528 return revision, git_hash 303 return revision, git_hash
529 304
530 305
531 class GitBranchCLUpload(object):
532 """Class to manage git branches and git-cl-upload.
533
534 This class allows one to create a new branch in a repository based
535 off of origin/master, make changes to the tree inside the
536 with-block, upload that new branch to Rietveld, restore the original
537 tree state, and delete the local copy of the new branch.
538
539 See roll_deps() for an example of use.
540
541 Constructor Args:
542 config: (roll_deps.DepsRollConfig) object containing options.
543 message: (string) the commit message, can be multiline.
544 set_brach_name: (string or none) if not None, the name of the
545 branch to use. If None, then use a temporary branch that
546 will be deleted.
547
548 Attributes:
549 issue: a string describing the codereview issue, after __exit__
550 has been called, othrwise, None.
551
552 Raises:
553 OSError: failed to execute git or git-cl.
554 subprocess.CalledProcessError: git returned unexpected status.
555 """
556 # pylint: disable=I0011,R0903,R0902
557
558 def __init__(self, config, message, set_branch_name):
559 self._message = message
560 self._file_list = []
561 self._branch_name = set_branch_name
562 self._stash = None
563 self._original_branch = None
564 self._config = config
565 self.issue = None
566
567 def stage_for_commit(self, *paths):
568 """Calls `git add ...` on each argument.
569
570 Args:
571 *paths: (list of strings) list of filenames to pass to `git add`.
572 """
573 self._file_list.extend(paths)
574
575 def __enter__(self):
576 git = self._config.git
577 vsp = self._config.vsp
578 def branch_exists(branch):
579 """Return true iff branch exists."""
580 return 0 == vsp.call([git, 'show-ref', '--quiet', branch])
581 def has_diff():
582 """Return true iff repository has uncommited changes."""
583 return bool(vsp.call([git, 'diff', '--quiet', 'HEAD']))
584
585 self._stash = has_diff()
586 if self._stash:
587 vsp.check_call([git, 'stash', 'save'])
588 try:
589 full_branch = vsp.strip_output([git, 'symbolic-ref', 'HEAD'])
590 self._original_branch = full_branch.split('/')[-1]
591 except (subprocess.CalledProcessError,):
592 self._original_branch = vsp.strip_output(
593 [git, 'rev-parse', 'HEAD'])
594
595 if not self._branch_name:
596 self._branch_name = self._config.default_branch_name
597
598 if branch_exists(self._branch_name):
599 vsp.check_call([git, 'checkout', '-q', 'master'])
600 vsp.check_call([git, 'branch', '-D', self._branch_name])
601
602 vsp.check_call(
603 [git, 'checkout', '-q', '-b', self._branch_name, 'origin/master'])
604
605 def __exit__(self, etype, value, traceback):
606 # pylint: disable=I0011,R0912
607 git = self._config.git
608 vsp = self._config.vsp
609 svn_info = str(get_svn_revision(self._config, 'HEAD'))
610
611 for filename in self._file_list:
612 assert os.path.exists(filename)
613 vsp.check_call([git, 'add', filename])
614 vsp.check_call([git, 'commit', '-q', '-m', self._message])
615
616 git_cl = [git, 'cl', 'upload', '-f',
617 '--bypass-hooks', '--bypass-watchlists']
618 if self._config.cc_list:
619 git_cl.append('--cc=%s' % self._config.cc_list)
620 if self._config.reviewers_list:
621 git_cl.append('--reviewers=%s' % self._config.reviewers_list)
622
623 git_try = [git, 'cl', 'try', '--revision', svn_info]
624 git_try.extend([arg for bot in self._config.cl_bot_list
625 for arg in ('-b', bot)])
626
627 if self._config.skip_cl_upload:
628 print 'You should call:'
629 print ' cd %s' % os.getcwd()
630 VerboseSubprocess.print_subprocess_args(
631 ' ', [git, 'checkout', self._branch_name])
632 VerboseSubprocess.print_subprocess_args(' ', git_cl)
633 if self._config.cl_bot_list:
634 VerboseSubprocess.print_subprocess_args(' ', git_try)
635 print
636 self.issue = ''
637 else:
638 vsp.check_call(git_cl)
639 self.issue = vsp.strip_output([git, 'cl', 'issue'])
640 if self._config.cl_bot_list:
641 vsp.check_call(git_try)
642
643 # deal with the aftermath of failed executions of this script.
644 if self._config.default_branch_name == self._original_branch:
645 self._original_branch = 'master'
646 vsp.check_call([git, 'checkout', '-q', self._original_branch])
647
648 if self._config.default_branch_name == self._branch_name:
649 vsp.check_call([git, 'branch', '-D', self._branch_name])
650 if self._stash:
651 vsp.check_call([git, 'stash', 'pop'])
652
653
654 def change_skia_deps(revision, git_hash, depspath): 306 def change_skia_deps(revision, git_hash, depspath):
655 """Update the DEPS file. 307 """Update the DEPS file.
656 308
657 Modify the skia_revision and skia_hash entries in the given DEPS file. 309 Modify the skia_revision and skia_hash entries in the given DEPS file.
658 310
659 Args: 311 Args:
660 revision: (int) Skia SVN revision. 312 revision: (int) Skia SVN revision.
661 git_hash: (string) Skia Git hash. 313 git_hash: (string) Skia Git hash.
662 depspath: (string) path to DEPS file. 314 depspath: (string) path to DEPS file.
663 """ 315 """
664 temp_file = tempfile.NamedTemporaryFile(delete=False, 316 temp_file = tempfile.NamedTemporaryFile(delete=False,
665 prefix='skia_DEPS_ROLL_tmp_') 317 prefix='skia_DEPS_ROLL_tmp_')
666 try: 318 try:
667 deps_regex_rev = re.compile('"skia_revision": "[0-9]*",') 319 deps_regex_rev = re.compile('"skia_revision": "[0-9]*",')
668 deps_regex_hash = re.compile('"skia_hash": "[0-9a-f]*",') 320 deps_regex_hash = re.compile('"skia_hash": "[0-9a-f]*",')
669 321
670 deps_regex_rev_repl = '"skia_revision": "%d",' % revision 322 deps_regex_rev_repl = '"skia_revision": "%d",' % revision
671 deps_regex_hash_repl = '"skia_hash": "%s",' % git_hash 323 deps_regex_hash_repl = '"skia_hash": "%s",' % git_hash
672 324
673 with open(depspath, 'r') as input_stream: 325 with open(depspath, 'r') as input_stream:
674 for line in input_stream: 326 for line in input_stream:
675 line = deps_regex_rev.sub(deps_regex_rev_repl, line) 327 line = deps_regex_rev.sub(deps_regex_rev_repl, line)
676 line = deps_regex_hash.sub(deps_regex_hash_repl, line) 328 line = deps_regex_hash.sub(deps_regex_hash_repl, line)
677 temp_file.write(line) 329 temp_file.write(line)
678 finally: 330 finally:
679 temp_file.close() 331 temp_file.close()
680 shutil.move(temp_file.name, depspath) 332 shutil.move(temp_file.name, depspath)
681 333
682 334
335 def git_cl_uploader(config, message, file_list):
336 """Create a commit in the current git branch; upload via git-cl.
337
338 Assumes that you are already on the branch you want to be on.
339
340 Args:
341 config: (roll_deps.DepsRollConfig) object containing options.
342 message: (string) the commit message, can be multiline.
343 file_list: (list of strings) list of filenames to pass to `git add`.
344
345 Returns:
346 The output of `git cl issue`, if not config.skip_cl_upload, else ''.
347 """
348
349 git, vsp = config.git, config.vsp
350 svn_info = str(get_svn_revision(config, 'HEAD'))
351
352 for filename in file_list:
353 assert os.path.exists(filename)
354 vsp.check_call([git, 'add', filename])
355
356 vsp.check_call([git, 'commit', '-q', '-m', message])
357
358 git_cl = [git, 'cl', 'upload', '-f',
359 '--bypass-hooks', '--bypass-watchlists']
360 if config.cc_list:
361 git_cl.append('--cc=%s' % config.cc_list)
362 if config.reviewers_list:
363 git_cl.append('--reviewers=%s' % config.reviewers_list)
364
365 git_try = [git, 'cl', 'try', '--revision', svn_info]
366 git_try.extend([arg for bot in config.cl_bot_list for arg in ('-b', bot)])
367
368 branch_name = git_utils.git_branch_name(git, vsp.verbose)
369
370 if config.skip_cl_upload:
371 space = ' '
372 print 'You should call:'
373 print '%scd %s' % (space, os.getcwd())
374 misc_utils.print_subprocess_args(
375 ' ', [git, 'checkout', branch_name])
376 misc_utils.print_subprocess_args(space, git_cl)
377 if config.cl_bot_list:
378 misc_utils.print_subprocess_args(space, git_try)
379 print
380 return ''
381 else:
382 vsp.check_call(git_cl)
383 issue = vsp.strip_output([git, 'cl', 'issue'])
384 if config.cl_bot_list:
385 vsp.check_call(git_try)
386 return issue
387
388
683 def roll_deps(config, revision, git_hash): 389 def roll_deps(config, revision, git_hash):
684 """Upload changed DEPS and a whitespace change. 390 """Upload changed DEPS and a whitespace change.
685 391
686 Given the correct git_hash, create two Reitveld issues. 392 Given the correct git_hash, create two Reitveld issues.
687 393
688 Args: 394 Args:
689 config: (roll_deps.DepsRollConfig) object containing options. 395 config: (roll_deps.DepsRollConfig) object containing options.
690 revision: (int) Skia SVN revision. 396 revision: (int) Skia SVN revision.
691 git_hash: (string) Skia Git hash. 397 git_hash: (string) Skia Git hash.
692 398
693 Returns: 399 Returns:
694 a tuple containing textual description of the two issues. 400 a tuple containing textual description of the two issues.
695 401
696 Raises: 402 Raises:
697 OSError: failed to execute git or git-cl. 403 OSError: failed to execute git or git-cl.
698 subprocess.CalledProcessError: git returned unexpected status. 404 subprocess.CalledProcessError: git returned unexpected status.
699 """ 405 """
700 406
701 git = config.git 407 git = config.git
702 with ChangeDir(config.chromium_path, config.verbose): 408 with misc_utils.ChangeDir(config.chromium_path, config.verbose):
703 config.vsp.check_call([git, 'fetch', '-q', 'origin']) 409 config.vsp.check_call([git, 'fetch', '-q', 'origin'])
704 410
705 old_revision = ReSearch.search_within_output( 411 old_revision = misc_utils.ReSearch.search_within_output(
706 config.verbose, '"skia_revision": "(?P<return>[0-9]+)",', None, 412 config.verbose, '"skia_revision": "(?P<return>[0-9]+)",', None,
707 [git, 'show', 'origin/master:DEPS']) 413 [git, 'show', 'origin/master:DEPS'])
708 assert old_revision 414 assert old_revision
709 if revision == int(old_revision): 415 if revision == int(old_revision):
710 print 'DEPS is up to date!' 416 print 'DEPS is up to date!'
711 return None 417 return None
712 418
713 master_hash = config.vsp.strip_output( 419 master_hash = config.vsp.strip_output(
714 [git, 'show-ref', 'origin/master', '--hash']) 420 [git, 'show-ref', 'origin/master', '--hash'])
715 master_revision = get_svn_revision(config, 'origin/master') 421 master_revision = get_svn_revision(config, 'origin/master')
716 422
717 branch = None
718
719 # master_hash[8] gives each whitespace CL a unique name. 423 # master_hash[8] gives each whitespace CL a unique name.
424 branch = 'control_%s' % master_hash[:8]
720 message = ('whitespace change %s\n\n' 425 message = ('whitespace change %s\n\n'
721 'Chromium base revision: %d / %s\n\n' 426 'Chromium base revision: %d / %s\n\n'
722 'This CL was created by Skia\'s roll_deps.py script.\n' 427 'This CL was created by Skia\'s roll_deps.py script.\n'
723 ) % (master_hash[:8], master_revision, master_hash[:8]) 428 ) % (master_hash[:8], master_revision, master_hash[:8])
724 if config.save_branches: 429 with git_utils.ChangeGitBranch(git, branch, 'origin/master',
725 branch = 'control_%s' % master_hash[:8] 430 config.verbose,
431 not config.save_branches):
432 branch = git_utils.git_branch_name(git, config.vsp.verbose)
726 433
727 codereview = GitBranchCLUpload(config, message, branch)
728 with codereview:
729 with open('build/whitespace_file.txt', 'a') as output_stream: 434 with open('build/whitespace_file.txt', 'a') as output_stream:
730 output_stream.write('\nCONTROL\n') 435 output_stream.write('\nCONTROL\n')
731 codereview.stage_for_commit('build/whitespace_file.txt')
732 whitespace_cl = codereview.issue
733 if branch:
734 whitespace_cl = '%s\n branch: %s' % (whitespace_cl, branch)
735 436
736 control_url = ReSearch.search_within_string( 437 whitespace_cl = git_cl_uploader(
737 codereview.issue, '(?P<return>https?://[^) ]+)', '?') 438 config, message, ['build/whitespace_file.txt'])
738 439
739 if config.save_branches: 440 control_url = misc_utils.ReSearch.search_within_string(
740 branch = 'roll_%d_%s' % (revision, master_hash[:8]) 441 whitespace_cl, '(?P<return>https?://[^) ]+)', '?')
442 if config.save_branches:
443 whitespace_cl = '%s\n branch: %s' % (whitespace_cl, branch)
444
445 branch = 'roll_%d_%s' % (revision, master_hash[:8])
741 message = ( 446 message = (
742 'roll skia DEPS to %d\n\n' 447 'roll skia DEPS to %d\n\n'
743 'Chromium base revision: %d / %s\n' 448 'Chromium base revision: %d / %s\n'
744 'Old Skia revision: %s\n' 449 'Old Skia revision: %s\n'
745 'New Skia revision: %d\n' 450 'New Skia revision: %d\n'
746 'Control CL: %s\n\n' 451 'Control CL: %s\n\n'
747 'This CL was created by Skia\'s roll_deps.py script.\n\n' 452 'This CL was created by Skia\'s roll_deps.py script.\n\n'
748 'Bypassing commit queue trybots:\n' 453 'Bypassing commit queue trybots:\n'
749 'NOTRY=true\n' 454 'NOTRY=true\n'
750 % (revision, master_revision, master_hash[:8], 455 % (revision, master_revision, master_hash[:8],
751 old_revision, revision, control_url)) 456 old_revision, revision, control_url))
752 codereview = GitBranchCLUpload(config, message, branch) 457 with git_utils.ChangeGitBranch(git, branch, 'origin/master',
753 with codereview: 458 config.verbose,
459 not config.save_branches):
460 branch = git_utils.git_branch_name(git, config.vsp.verbose)
461
754 change_skia_deps(revision, git_hash, 'DEPS') 462 change_skia_deps(revision, git_hash, 'DEPS')
755 codereview.stage_for_commit('DEPS') 463 deps_cl = git_cl_uploader(config, message, ['DEPS'])
756 deps_cl = codereview.issue 464 if config.save_branches:
757 if branch: 465 deps_cl = '%s\n branch: %s' % (deps_cl, branch)
758 deps_cl = '%s\n branch: %s' % (deps_cl, branch)
759 466
760 return deps_cl, whitespace_cl 467 return deps_cl, whitespace_cl
761 468
762 469
763 def find_hash_and_roll_deps(config, revision=None, partial_hash=None): 470 def find_hash_and_roll_deps(config, revision=None, partial_hash=None):
764 """Call find_hash_from_revision() and roll_deps(). 471 """Call find_hash_from_revision() and roll_deps().
765 472
766 The calls to git will be verbose on standard output. After a 473 The calls to git will be verbose on standard output. After a
767 successful upload of both issues, print links to the new 474 successful upload of both issues, print links to the new
768 codereview issues. 475 codereview issues.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
807 Args: 514 Args:
808 args: sys.argv[1:]-type argument list. 515 args: sys.argv[1:]-type argument list.
809 """ 516 """
810 option_parser = DepsRollConfig.GetOptionParser() 517 option_parser = DepsRollConfig.GetOptionParser()
811 options = option_parser.parse_args(args)[0] 518 options = option_parser.parse_args(args)[0]
812 519
813 if not options.chromium_path: 520 if not options.chromium_path:
814 option_parser.error('Must specify chromium_path.') 521 option_parser.error('Must specify chromium_path.')
815 if not os.path.isdir(options.chromium_path): 522 if not os.path.isdir(options.chromium_path):
816 option_parser.error('chromium_path must be a directory.') 523 option_parser.error('chromium_path must be a directory.')
817 if not test_git_executable(options.git_path): 524 if not git_utils.test_git_executable(options.git_path):
818 option_parser.error('Invalid git executable.') 525 option_parser.error('Invalid git executable.')
819 526
820 config = DepsRollConfig(options) 527 config = DepsRollConfig(options)
821 find_hash_and_roll_deps(config, options.revision, options.git_hash) 528 find_hash_and_roll_deps(config, options.revision, options.git_hash)
822 529
823 530
824 if __name__ == '__main__': 531 if __name__ == '__main__':
825 main(sys.argv[1:]) 532 main(sys.argv[1:])
826 533
OLDNEW
« tools/git_utils.py ('K') | « tools/misc_utils.py ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698