OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2014 The Chromium Authors. All rights reserved. | 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 | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 """This scripts takes the path to a dep and an svn revision, and updates the | 6 """This scripts takes the path to a dep and a git or svn revision, and updates |
7 parent repo's DEPS file with the corresponding git revision. Sample invocation: | 7 the parent repo's DEPS file with the corresponding git revision. Sample |
| 8 invocation: |
8 | 9 |
9 [chromium/src]$ roll-dep third_party/WebKit 12345 | 10 [chromium/src]$ roll-dep third_party/WebKit 12345 |
10 | 11 |
11 After the script completes, the DEPS file will be dirty with the new revision. | 12 After the script completes, the DEPS file will be dirty with the new revision. |
12 The user can then: | 13 The user can then: |
13 | 14 |
14 $ git add DEPS | 15 $ git add DEPS |
15 $ git commit | 16 $ git commit |
16 """ | 17 """ |
17 | 18 |
(...skipping 272 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
290 if old_svn_rev and new_svn_rev: | 291 if old_svn_rev and new_svn_rev: |
291 svn_range_str = ' (svn %s:%s)' % (old_svn_rev, new_svn_rev) | 292 svn_range_str = ' (svn %s:%s)' % (old_svn_rev, new_svn_rev) |
292 return dedent(ROLL_DESCRIPTION_STR % { | 293 return dedent(ROLL_DESCRIPTION_STR % { |
293 'dep_path': shorten_dep_path(dep_name), | 294 'dep_path': shorten_dep_path(dep_name), |
294 'before_rev': old_rev_short, | 295 'before_rev': old_rev_short, |
295 'after_rev': new_rev_short, | 296 'after_rev': new_rev_short, |
296 'svn_range': svn_range_str, | 297 'svn_range': svn_range_str, |
297 'revlog_url': url, | 298 'revlog_url': url, |
298 }) | 299 }) |
299 | 300 |
| 301 |
300 def update_deps_entry(deps_lines, deps_ast, value_node, new_rev, comment): | 302 def update_deps_entry(deps_lines, deps_ast, value_node, new_rev, comment): |
301 line_idx = update_node(deps_lines, deps_ast, value_node, new_rev) | 303 line_idx = update_node(deps_lines, deps_ast, value_node, new_rev) |
302 (content, _, _) = deps_lines[line_idx].partition('#') | 304 (content, _, _) = deps_lines[line_idx].partition('#') |
303 if comment: | 305 if comment: |
304 deps_lines[line_idx] = '%s # %s' % (content.rstrip(), comment) | 306 deps_lines[line_idx] = '%s # %s' % (content.rstrip(), comment) |
305 else: | 307 else: |
306 deps_lines[line_idx] = content.rstrip() | 308 deps_lines[line_idx] = content.rstrip() |
307 | 309 |
| 310 |
308 def update_deps(deps_file, dep_path, dep_name, new_rev, comment): | 311 def update_deps(deps_file, dep_path, dep_name, new_rev, comment): |
309 """Update the DEPS file with the new git revision.""" | 312 """Update the DEPS file with the new git revision.""" |
310 commit_msg = '' | 313 commit_msg = '' |
311 with open(deps_file) as fh: | 314 with open(deps_file) as fh: |
312 deps_content = fh.read() | 315 deps_content = fh.read() |
313 deps_locals = {} | 316 deps_locals = {} |
314 def _Var(key): | 317 def _Var(key): |
315 return deps_locals['vars'][key] | 318 return deps_locals['vars'][key] |
316 deps_locals['Var'] = _Var | 319 deps_locals['Var'] = _Var |
317 exec deps_content in {}, deps_locals | 320 exec deps_content in {}, deps_locals |
(...skipping 12 matching lines...) Expand all Loading... |
330 for (os_name, os_node) in izip(deps_os_node.keys, deps_os_node.values): | 333 for (os_name, os_node) in izip(deps_os_node.keys, deps_os_node.values): |
331 dep_idx = find_dict_index(os_node, dep_name) | 334 dep_idx = find_dict_index(os_node, dep_name) |
332 if dep_idx is not None: | 335 if dep_idx is not None: |
333 value_node = os_node.values[dep_idx] | 336 value_node = os_node.values[dep_idx] |
334 if value_node.__class__ is ast.Name and value_node.id == 'None': | 337 if value_node.__class__ is ast.Name and value_node.id == 'None': |
335 pass | 338 pass |
336 else: | 339 else: |
337 update_deps_entry(deps_lines, deps_ast, value_node, new_rev, comment) | 340 update_deps_entry(deps_lines, deps_ast, value_node, new_rev, comment) |
338 commit_msg = generate_commit_message( | 341 commit_msg = generate_commit_message( |
339 deps_locals['deps_os'][os_name.s], dep_path, dep_name, new_rev) | 342 deps_locals['deps_os'][os_name.s], dep_path, dep_name, new_rev) |
340 if commit_msg: | 343 if not commit_msg: |
341 print 'Pinning %s' % dep_name | |
342 print 'to revision %s' % new_rev | |
343 print 'in %s' % deps_file | |
344 with open(deps_file, 'w') as fh: | |
345 for line in deps_lines: | |
346 print >> fh, line | |
347 deps_file_dir = os.path.normpath(os.path.dirname(deps_file)) | |
348 deps_file_root = Popen( | |
349 ['git', 'rev-parse', '--show-toplevel'], | |
350 cwd=deps_file_dir, stdout=PIPE).communicate()[0].strip() | |
351 with open(os.path.join(deps_file_root, '.git', 'MERGE_MSG'), 'w') as fh: | |
352 fh.write(commit_msg) | |
353 else: | |
354 print 'Could not find an entry in %s to update.' % deps_file | 344 print 'Could not find an entry in %s to update.' % deps_file |
355 return 0 if commit_msg else 1 | 345 return 1 |
| 346 |
| 347 print 'Pinning %s' % dep_name |
| 348 print 'to revision %s' % new_rev |
| 349 print 'in %s' % deps_file |
| 350 with open(deps_file, 'w') as fh: |
| 351 for line in deps_lines: |
| 352 print >> fh, line |
| 353 deps_file_dir = os.path.normpath(os.path.dirname(deps_file)) |
| 354 deps_file_root = Popen( |
| 355 ['git', 'rev-parse', '--show-toplevel'], |
| 356 cwd=deps_file_dir, stdout=PIPE).communicate()[0].strip() |
| 357 with open(os.path.join(deps_file_root, '.git', 'MERGE_MSG'), 'w') as fh: |
| 358 fh.write(commit_msg) |
| 359 return 0 |
356 | 360 |
357 | 361 |
358 def main(argv): | 362 def main(argv): |
359 parser = optparse.OptionParser() | 363 usage = 'Usage: roll_dep.py [options] <dep path> <rev> [ <DEPS file> ]' |
| 364 parser = optparse.OptionParser(usage=usage, description=__doc__) |
360 parser.add_option('--no-verify-revision', | 365 parser.add_option('--no-verify-revision', |
361 help='Don\'t verify the revision passed in. This ' | 366 help='Don\'t verify the revision passed in. This ' |
362 'also skips adding an svn revision comment ' | 367 'also skips adding an svn revision comment ' |
363 'for git dependencies and requires the passed ' | 368 'for git dependencies and requires the passed ' |
364 'revision to be a git hash.', | 369 'revision to be a git hash.', |
365 default=False, action='store_true') | 370 default=False, action='store_true') |
366 (options, argv) = parser.parse_args(argv) | 371 options, args = parser.parse_args(argv) |
367 if len(argv) not in (2, 3): | 372 if len(args) not in (2, 3): |
368 print >> sys.stderr, ( | 373 parser.error('Expected either 2 or 3 positional parameters.') |
369 'Usage: roll_dep.py [options] <dep path> <svn revision> ' | 374 arg_dep_path, revision = args[:2] |
370 '[ <DEPS file> ]') | |
371 return 1 | |
372 (arg_dep_path, revision) = argv[0:2] | |
373 gclient_root = find_gclient_root() | 375 gclient_root = find_gclient_root() |
374 dep_path = platform_path(arg_dep_path) | 376 dep_path = platform_path(arg_dep_path) |
375 if not os.path.exists(dep_path): | 377 if not os.path.exists(dep_path): |
376 dep_path = os.path.join(gclient_root, dep_path) | 378 dep_path = os.path.join(gclient_root, dep_path) |
377 if not options.no_verify_revision: | 379 if not options.no_verify_revision: |
378 # Only require the path to exist if the revision should be verified. A path | 380 # Only require the path to exist if the revision should be verified. A path |
379 # to e.g. os deps might not be checked out. | 381 # to e.g. os deps might not be checked out. |
380 assert os.path.isdir(dep_path), 'No such directory: %s' % arg_dep_path | 382 if not os.path.isdir(dep_path): |
381 if len(argv) > 2: | 383 print >> sys.stderr, 'No such directory: %s' % arg_dep_path |
382 deps_file = argv[2] | 384 return 1 |
| 385 if len(args) > 2: |
| 386 deps_file = args[2] |
383 else: | 387 else: |
384 soln = get_solution(gclient_root, dep_path) | 388 soln = get_solution(gclient_root, dep_path) |
385 soln_path = os.path.relpath(os.path.join(gclient_root, soln['name'])) | 389 soln_path = os.path.relpath(os.path.join(gclient_root, soln['name'])) |
386 deps_file = os.path.join(soln_path, 'DEPS') | 390 deps_file = os.path.join(soln_path, 'DEPS') |
387 dep_name = posix_path(os.path.relpath(dep_path, gclient_root)) | 391 dep_name = posix_path(os.path.relpath(dep_path, gclient_root)) |
388 if options.no_verify_revision: | 392 if options.no_verify_revision: |
389 assert is_git_hash(revision), ( | 393 if not is_git_hash(revision): |
390 'The passed revision %s must be a git hash when skipping revision ' | 394 print >> sys.stderr, ( |
391 'verification.' % revision) | 395 'The passed revision %s must be a git hash when skipping revision ' |
| 396 'verification.' % revision) |
| 397 return 1 |
392 git_rev = revision | 398 git_rev = revision |
393 comment = None | 399 comment = None |
394 else: | 400 else: |
395 (git_rev, svn_rev) = get_git_revision(dep_path, revision) | 401 git_rev, svn_rev = get_git_revision(dep_path, revision) |
396 comment = ('from svn revision %s' % svn_rev) if svn_rev else None | 402 comment = ('from svn revision %s' % svn_rev) if svn_rev else None |
397 assert git_rev, 'Could not find git revision matching %s.' % revision | 403 if not git_rev: |
| 404 print >> sys.stderr, 'Could not find git revision matching %s.' % revision |
| 405 return 1 |
398 return update_deps(deps_file, dep_path, dep_name, git_rev, comment) | 406 return update_deps(deps_file, dep_path, dep_name, git_rev, comment) |
399 | 407 |
| 408 |
400 if __name__ == '__main__': | 409 if __name__ == '__main__': |
401 try: | 410 try: |
402 sys.exit(main(sys.argv[1:])) | 411 sys.exit(main(sys.argv[1:])) |
403 except KeyboardInterrupt: | 412 except KeyboardInterrupt: |
404 sys.stderr.write('interrupted\n') | 413 sys.stderr.write('interrupted\n') |
405 sys.exit(1) | 414 sys.exit(1) |
OLD | NEW |