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

Side by Side Diff: tools/roll_deps.py

Issue 126523002: Changes to roll_deps.py (Closed) Base URL: https://skia.googlecode.com/svn/trunk
Patch Set: argh! Created 6 years, 11 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | 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 107 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 ' a temporary will be cloned. Defaults to SKIA_GIT_CHECKOUT' 118 ' a temporary will be cloned. Defaults to SKIA_GIT_CHECKOUT'
119 '_PATH, if that environment variable is set.', 119 '_PATH, if that environment variable is set.',
120 default=os.environ.get('SKIA_GIT_CHECKOUT_PATH')) 120 default=os.environ.get('SKIA_GIT_CHECKOUT_PATH'))
121 option_parser.add_option( 121 option_parser.add_option(
122 '', '--search_depth', type='int', default=100, 122 '', '--search_depth', type='int', default=100,
123 help='How far back to look for the revision.') 123 help='How far back to look for the revision.')
124 option_parser.add_option( 124 option_parser.add_option(
125 '', '--git_path', help='Git executable, defaults to "git".', 125 '', '--git_path', help='Git executable, defaults to "git".',
126 default='git') 126 default='git')
127 option_parser.add_option( 127 option_parser.add_option(
128 '', '--save_branches', help='Save the temporary branches', 128 '', '--save_branches',
129 action='store_true', dest='save_branches', default=False) 129 help='Save the temporary branches (default)',
130 action='store_true', dest='save_branches', default=True)
131 option_parser.add_option(
132 '', '--delete_branches', help='Delete the temporary branches',
133 action='store_false', dest='save_branches', default=True)
borenet 2014/01/07 21:39:34 If these are changing the same variable, why do we
hal.canary 2014/01/08 18:57:38 Done.
130 option_parser.add_option( 134 option_parser.add_option(
131 '', '--verbose', help='Do not suppress the output from `git cl`.', 135 '', '--verbose', help='Do not suppress the output from `git cl`.',
132 action='store_true', dest='verbose', default=False) 136 action='store_true', dest='verbose', default=False)
133 option_parser.add_option( 137 option_parser.add_option(
134 '', '--skip_cl_upload', help='Skip the cl upload step; useful' 138 '', '--skip_cl_upload', help='Skip the cl upload step; useful'
135 ' for testing or with --save_branches.', 139 ' for testing or with --save_branches.',
136 action='store_true', default=False) 140 action='store_true', default=False)
137 141
138 default_bots_help = ( 142 default_bots_help = (
139 'Comma-separated list of bots, defaults to a list of %d bots.' 143 'Comma-separated list of bots, defaults to a list of %d bots.'
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
261 'origin/master'], cwd=skia_dir) 265 'origin/master'], cwd=skia_dir)
262 266
263 if revision < 0 or not git_hash: 267 if revision < 0 or not git_hash:
264 raise DepsRollError('Git hash can not be found.') 268 raise DepsRollError('Git hash can not be found.')
265 return revision, git_hash 269 return revision, git_hash
266 finally: 270 finally:
267 if use_temp: 271 if use_temp:
268 shutil.rmtree(skia_dir) 272 shutil.rmtree(skia_dir)
269 273
270 274
275 class ChangeDir(object):
276 """Use with a with-statement to temporarily change directories."""
277 # pylint: disable=I0011,R0903
278
279 def __init__(self, directory):
280 self._directory = directory
281
282 def __enter__(self):
283 cwd = os.getcwd()
284 os.chdir(self._directory)
285 self._directory = cwd
286
287 def __exit__(self, etype, value, traceback):
288 os.chdir(self._directory)
289
290
271 class GitBranchCLUpload(object): 291 class GitBranchCLUpload(object):
272 """Class to manage git branches and git-cl-upload. 292 """Class to manage git branches and git-cl-upload.
273 293
274 This class allows one to create a new branch in a repository based 294 This class allows one to create a new branch in a repository based
275 off of origin/master, make changes to the tree inside the 295 off of origin/master, make changes to the tree inside the
276 with-block, upload that new branch to Rietveld, restore the original 296 with-block, upload that new branch to Rietveld, restore the original
277 tree state, and delete the local copy of the new branch. 297 tree state, and delete the local copy of the new branch.
278 298
279 See roll_deps() for an example of use. 299 See roll_deps() for an example of use.
280 300
(...skipping 25 matching lines...) Expand all
306 self.issue = None 326 self.issue = None
307 327
308 def stage_for_commit(self, *paths): 328 def stage_for_commit(self, *paths):
309 """Calls `git add ...` on each argument. 329 """Calls `git add ...` on each argument.
310 330
311 Args: 331 Args:
312 *paths: (list of strings) list of filenames to pass to `git add`. 332 *paths: (list of strings) list of filenames to pass to `git add`.
313 """ 333 """
314 self._file_list.extend(paths) 334 self._file_list.extend(paths)
315 335
336 def set_message(self, message):
337 """Change the message."""
338 self._message = message
339
316 def __enter__(self): 340 def __enter__(self):
317 git = self._config.git 341 git = self._config.git
318 def branch_exists(branch): 342 def branch_exists(branch):
319 """Return true iff branch exists.""" 343 """Return true iff branch exists."""
320 return 0 == subprocess.call( 344 return 0 == subprocess.call(
321 [git, 'show-ref', '--quiet', branch]) 345 [git, 'show-ref', '--quiet', branch])
322 def has_diff(): 346 def has_diff():
323 """Return true iff repository has uncommited changes.""" 347 """Return true iff repository has uncommited changes."""
324 return bool(subprocess.call([git, 'diff', '--quiet', 'HEAD'])) 348 return bool(subprocess.call([git, 'diff', '--quiet', 'HEAD']))
349 def get_svn_revision():
350 """Works in both git and git-svn. returns a string"""
351 last_log_message = subprocess.check_output(
352 [git, 'log', '-n', '1', '--format=format:%B'])
353 svn_format = (
354 '(git-svn-id: svn://svn.chromium.org/chrome/trunk/src@|'
355 'SVN changes up to revision )([0-9]+)')
356 search = re.search(svn_format, last_log_message)
357 if not search:
358 raise DepsRollError(
359 'Revision number missing from Chromium origin/master.')
360 return search.group(2)
325 self._stash = has_diff() 361 self._stash = has_diff()
326 if self._stash: 362 if self._stash:
327 check_call([git, 'stash', 'save']) 363 check_call([git, 'stash', 'save'])
328 try: 364 try:
329 self._original_branch = strip_output( 365 self._original_branch = strip_output(
330 [git, 'symbolic-ref', '--short', 'HEAD']) 366 [git, 'symbolic-ref', '--short', 'HEAD'])
331 except (subprocess.CalledProcessError,): 367 except (subprocess.CalledProcessError,):
332 self._original_branch = strip_output( 368 self._original_branch = strip_output(
333 [git, 'rev-parse', 'HEAD']) 369 [git, 'rev-parse', 'HEAD'])
334 370
335 if not self._branch_name: 371 if not self._branch_name:
336 self._branch_name = self._config.default_branch_name 372 self._branch_name = self._config.default_branch_name
337 373
338 if branch_exists(self._branch_name): 374 if branch_exists(self._branch_name):
339 check_call([git, 'checkout', '-q', 'master']) 375 check_call([git, 'checkout', '-q', 'master'])
340 check_call([git, 'branch', '-q', '-D', self._branch_name]) 376 check_call([git, 'branch', '-q', '-D', self._branch_name])
341 377
342 check_call( 378 check_call(
343 [git, 'checkout', '-q', '-b', 379 [git, 'checkout', '-q', '-b',
344 self._branch_name, 'origin/master']) 380 self._branch_name, 'origin/master'])
345 381 self._svn_info = get_svn_revision()
346 svn_info = subprocess.check_output(['git', 'svn', 'info'])
347 svn_info_search = re.search(r'Last Changed Rev: ([0-9]+)\W', svn_info)
348 assert svn_info_search
349 self._svn_info = svn_info_search.group(1)
350 382
351 def __exit__(self, etype, value, traceback): 383 def __exit__(self, etype, value, traceback):
352 # pylint: disable=I0011,R0912 384 # pylint: disable=I0011,R0912
353 git = self._config.git 385 git = self._config.git
354 def quiet_check_call(*args, **kwargs): 386 def quiet_check_call(*args, **kwargs):
355 """Call check_call, but pipe output to devnull.""" 387 """Call check_call, but pipe output to devnull."""
356 with open(os.devnull, 'w') as devnull: 388 with open(os.devnull, 'w') as devnull:
357 check_call(*args, stdout=devnull, **kwargs) 389 check_call(*args, stdout=devnull, **kwargs)
358 390
359 for filename in self._file_list: 391 for filename in self._file_list:
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after
450 revision: (int) Skia SVN revision. 482 revision: (int) Skia SVN revision.
451 git_hash: (string) Skia Git hash. 483 git_hash: (string) Skia Git hash.
452 484
453 Returns: 485 Returns:
454 a tuple containing textual description of the two issues. 486 a tuple containing textual description of the two issues.
455 487
456 Raises: 488 Raises:
457 OSError: failed to execute git or git-cl. 489 OSError: failed to execute git or git-cl.
458 subprocess.CalledProcessError: git returned unexpected status. 490 subprocess.CalledProcessError: git returned unexpected status.
459 """ 491 """
492 def search_within_file(path, pattern, default=None):
borenet 2014/01/07 21:31:12 I think this function could live outside of roll_d
hal.canary 2014/01/08 18:57:38 Done. It's in a utility class. If you want to ma
493 """Search for regular expression in a file.
494
495 Opens a file for reading and searches line by line for a match to
496 the regex and returns the parenthesized group named return for the
497 first match.
borenet 2014/01/07 21:31:12 Please document that the pattern can't contain new
hal.canary 2014/01/08 18:57:38 Done.
498
499 For example:
500 pattern = '^root(:[^:]*){4}:(?P<return>[^:]*)'
501 search_within_file('/etc/passwd', pattern)
502 should return root's home directory (/root on my system).
503
504 Args:
505 path: (string) filename
506 pattern: (string) to be passed to re.compile
507 default: what to return if no match
508
509 Returns:
510 A string or whatever default is
511 """
512 with open(path, 'r') as input_stream:
513 pattern_object = re.compile(pattern)
514 for line in input_stream:
515 match = pattern_object.search(line)
516 if match:
517 return match.group('return')
518 return default
519
520 def search_within_string(input_string, pattern, default=None):
borenet 2014/01/07 21:31:12 Same comment about this function: I think it could
hal.canary 2014/01/08 18:57:38 Done.
521 """Search for regular expression in a string.
522
523 Args:
524 input_string: (string) to be searched
525 pattern: (string) to be passed to re.compile
526 default: what to return if no match
527
528 Returns:
529 A string or whatever default is
530 """
531 match = re.search(pattern, input_string)
532 return match.group('return') if match else default
533
460 git = config.git 534 git = config.git
461 cwd = os.getcwd() 535 with ChangeDir(config.chromium_path):
462 os.chdir(config.chromium_path)
463 try:
464 check_call([git, 'fetch', '-q', 'origin']) 536 check_call([git, 'fetch', '-q', 'origin'])
465 master_hash = strip_output( 537 master_hash = strip_output(
466 [git, 'show-ref', 'origin/master', '--hash']) 538 [git, 'show-ref', 'origin/master', '--hash'])
467 539
540 branch = None
541
468 # master_hash[8] gives each whitespace CL a unique name. 542 # master_hash[8] gives each whitespace CL a unique name.
469 message = ('whitespace change %s\n\nThis CL was created by' 543 message = ('whitespace change %s\n\nThis CL was created by'
470 ' Skia\'s roll_deps.py script.\n') % master_hash[:8] 544 ' Skia\'s roll_deps.py script.\n') % master_hash[:8]
471 branch = branch_name(message) if config.save_branches else None 545 if config.save_branches:
546 branch = 'control_%s' % master_hash[:8]
borenet 2014/01/07 21:31:12 Maybe we should have a short_hash(hash) function?
hal.canary 2014/01/08 18:57:38 In Python, string[:8] is clear enough.
472 547
473 codereview = GitBranchCLUpload(config, message, branch) 548 codereview = GitBranchCLUpload(config, message, branch)
474 with codereview: 549 with codereview:
475 with open('build/whitespace_file.txt', 'a') as output_stream: 550 with open('build/whitespace_file.txt', 'a') as output_stream:
476 output_stream.write('\nCONTROL\n') 551 output_stream.write('\nCONTROL\n')
477 codereview.stage_for_commit('build/whitespace_file.txt') 552 codereview.stage_for_commit('build/whitespace_file.txt')
478 whitespace_cl = codereview.issue 553 whitespace_cl = codereview.issue
479 if branch: 554 if branch:
480 whitespace_cl = '%s\n branch: %s' % (whitespace_cl, branch) 555 whitespace_cl = '%s\n branch: %s' % (whitespace_cl, branch)
481 control_url_match = re.search('https?://[^) ]+', codereview.issue) 556
482 if control_url_match: 557 control_url = search_within_string(
483 message = ('roll skia DEPS to %d\n\nThis CL was created by' 558 codereview.issue, '(?P<return>https?://[^) ]+)', '?')
484 ' Skia\'s roll_deps.py script.\n\ncontrol: %s' 559
485 % (revision, control_url_match.group(0))) 560 if config.save_branches:
486 else: 561 branch = 'roll_%d_%s' % (revision, master_hash[:8])
borenet 2014/01/07 21:39:34 I just found this: http://stackoverflow.com/a/6065
hal.canary 2014/01/08 18:57:38 Good idea, but defering to robert.
487 message = ('roll skia DEPS to %d\n\nThis CL was created by' 562 codereview = GitBranchCLUpload(config, '?', branch)
488 ' Skia\'s roll_deps.py script.') % revision
489 branch = branch_name(message) if config.save_branches else None
490 codereview = GitBranchCLUpload(config, message, branch)
491 with codereview: 563 with codereview:
564 old_revision = search_within_file(
565 'DEPS', '"skia_revision": "(?P<return>[0-9]+)",', '?')
566 assert revision != int(old_revision)
borenet 2014/01/07 21:31:12 Can we move the whitespace CL uploading to after t
hal.canary 2014/01/08 18:57:38 I moved that assert up. And turned it into a chec
567 codereview.set_message(
568 'roll skia DEPS to %d\n\nold revision:%s\n'
569 'new revision:%d\nThis CL was created by'
570 ' Skia\'s roll_deps.py script.\n\ncontrol: %s'
571 % (revision, old_revision, revision, control_url))
492 change_skia_deps(revision, git_hash, 'DEPS') 572 change_skia_deps(revision, git_hash, 'DEPS')
493 codereview.stage_for_commit('DEPS') 573 codereview.stage_for_commit('DEPS')
494 deps_cl = codereview.issue 574 deps_cl = codereview.issue
495 if branch: 575 if branch:
496 deps_cl = '%s\n branch: %s' % (deps_cl, branch) 576 deps_cl = '%s\n branch: %s' % (deps_cl, branch)
497 577
498 return deps_cl, whitespace_cl 578 return deps_cl, whitespace_cl
499 finally:
500 os.chdir(cwd)
501 579
502 580
503 def find_hash_and_roll_deps(config, revision): 581 def find_hash_and_roll_deps(config, revision):
504 """Call find_hash_from_revision() and roll_deps(). 582 """Call find_hash_from_revision() and roll_deps().
505 583
506 The calls to git will be verbose on standard output. After a 584 The calls to git will be verbose on standard output. After a
507 successful upload of both issues, print links to the new 585 successful upload of both issues, print links to the new
508 codereview issues. 586 codereview issues.
509 587
510 Args: 588 Args:
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 if not test_git_executable(options.git_path): 621 if not test_git_executable(options.git_path):
544 option_parser.error('Invalid git executable.') 622 option_parser.error('Invalid git executable.')
545 623
546 config = DepsRollConfig(options) 624 config = DepsRollConfig(options)
547 find_hash_and_roll_deps(config, options.revision) 625 find_hash_and_roll_deps(config, options.revision)
548 626
549 627
550 if __name__ == '__main__': 628 if __name__ == '__main__':
551 main(sys.argv[1:]) 629 main(sys.argv[1:])
552 630
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698