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

Side by Side Diff: gclient.py

Issue 385007: Run pychecker over most scripts in depot_tools. Catched a few bugs. (Closed)
Patch Set: . Created 11 years, 1 month 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
« no previous file with comments | « gcl.py ('k') | gclient_scm.py » ('j') | 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/python 1 #!/usr/bin/python
2 # 2 #
3 # Copyright 2008 Google Inc. All Rights Reserved. 3 # Copyright 2008 Google Inc. All Rights Reserved.
4 # 4 #
5 # Licensed under the Apache License, Version 2.0 (the "License"); 5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License. 6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at 7 # You may obtain a copy of the License at
8 # 8 #
9 # http://www.apache.org/licenses/LICENSE-2.0 9 # http://www.apache.org/licenses/LICENSE-2.0
10 # 10 #
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 67
68 __author__ = "darinf@gmail.com (Darin Fisher)" 68 __author__ = "darinf@gmail.com (Darin Fisher)"
69 __version__ = "0.3.3" 69 __version__ = "0.3.3"
70 70
71 import errno 71 import errno
72 import logging 72 import logging
73 import optparse 73 import optparse
74 import os 74 import os
75 import pprint 75 import pprint
76 import re 76 import re
77 import stat
78 import sys 77 import sys
79 import urlparse 78 import urlparse
80 import urllib 79 import urllib
81 80
82 import gclient_scm 81 import gclient_scm
83 import gclient_utils 82 import gclient_utils
84 from gclient_utils import Error, FileRead, FileWrite
85 83
86 # default help text 84 # default help text
87 DEFAULT_USAGE_TEXT = ( 85 DEFAULT_USAGE_TEXT = (
88 """usage: %prog <subcommand> [options] [--] [svn options/args...] 86 """usage: %prog <subcommand> [options] [--] [svn options/args...]
89 a wrapper for managing a set of client modules in svn. 87 a wrapper for managing a set of client modules in svn.
90 Version """ + __version__ + """ 88 Version """ + __version__ + """
91 89
92 subcommands: 90 subcommands:
93 cleanup 91 cleanup
94 config 92 config
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after
305 self._config_dict = {} 303 self._config_dict = {}
306 self._deps_hooks = [] 304 self._deps_hooks = []
307 305
308 def SetConfig(self, content): 306 def SetConfig(self, content):
309 self._config_dict = {} 307 self._config_dict = {}
310 self._config_content = content 308 self._config_content = content
311 try: 309 try:
312 exec(content, self._config_dict) 310 exec(content, self._config_dict)
313 except SyntaxError, e: 311 except SyntaxError, e:
314 try: 312 try:
313 __pychecker__ = 'no-objattrs'
315 # Try to construct a human readable error message 314 # Try to construct a human readable error message
316 error_message = [ 315 error_message = [
317 'There is a syntax error in your configuration file.', 316 'There is a syntax error in your configuration file.',
318 'Line #%s, character %s:' % (e.lineno, e.offset), 317 'Line #%s, character %s:' % (e.lineno, e.offset),
319 '"%s"' % re.sub(r'[\r\n]*$', '', e.text) ] 318 '"%s"' % re.sub(r'[\r\n]*$', '', e.text) ]
320 except: 319 except:
321 # Something went wrong, re-raise the original exception 320 # Something went wrong, re-raise the original exception
322 raise e 321 raise e
323 else: 322 else:
324 # Raise a new exception with the human readable message: 323 # Raise a new exception with the human readable message:
325 raise Error('\n'.join(error_message)) 324 raise gclient_utils.Error('\n'.join(error_message))
326 325
327 def SaveConfig(self): 326 def SaveConfig(self):
328 FileWrite(os.path.join(self._root_dir, self._options.config_filename), 327 gclient_utils.FileWrite(os.path.join(self._root_dir,
329 self._config_content) 328 self._options.config_filename),
329 self._config_content)
330 330
331 def _LoadConfig(self): 331 def _LoadConfig(self):
332 client_source = FileRead(os.path.join(self._root_dir, 332 client_source = gclient_utils.FileRead(
333 self._options.config_filename)) 333 os.path.join(self._root_dir, self._options.config_filename))
334 self.SetConfig(client_source) 334 self.SetConfig(client_source)
335 335
336 def ConfigContent(self): 336 def ConfigContent(self):
337 return self._config_content 337 return self._config_content
338 338
339 def GetVar(self, key, default=None): 339 def GetVar(self, key, default=None):
340 return self._config_dict.get(key, default) 340 return self._config_dict.get(key, default)
341 341
342 @staticmethod 342 @staticmethod
343 def LoadCurrentConfig(options, from_dir=None): 343 def LoadCurrentConfig(options, from_dir=None):
(...skipping 26 matching lines...) Expand all
370 def _SaveEntries(self, entries): 370 def _SaveEntries(self, entries):
371 """Creates a .gclient_entries file to record the list of unique checkouts. 371 """Creates a .gclient_entries file to record the list of unique checkouts.
372 372
373 The .gclient_entries file lives in the same directory as .gclient. 373 The .gclient_entries file lives in the same directory as .gclient.
374 374
375 Args: 375 Args:
376 entries: A sequence of solution names. 376 entries: A sequence of solution names.
377 """ 377 """
378 text = "entries = \\\n" + pprint.pformat(entries, 2) + '\n' 378 text = "entries = \\\n" + pprint.pformat(entries, 2) + '\n'
379 file_path = os.path.join(self._root_dir, self._options.entries_filename) 379 file_path = os.path.join(self._root_dir, self._options.entries_filename)
380 FileWrite(file_path, text) 380 gclient_utils.FileWrite(file_path, text)
381 381
382 def _ReadEntries(self): 382 def _ReadEntries(self):
383 """Read the .gclient_entries file for the given client. 383 """Read the .gclient_entries file for the given client.
384 384
385 Args: 385 Args:
386 client: The client for which the entries file should be read. 386 client: The client for which the entries file should be read.
387 387
388 Returns: 388 Returns:
389 A sequence of solution names, which will be empty if there is the 389 A sequence of solution names, which will be empty if there is the
390 entries file hasn't been created yet. 390 entries file hasn't been created yet.
391 """ 391 """
392 scope = {} 392 scope = {}
393 filename = os.path.join(self._root_dir, self._options.entries_filename) 393 filename = os.path.join(self._root_dir, self._options.entries_filename)
394 if not os.path.exists(filename): 394 if not os.path.exists(filename):
395 return [] 395 return []
396 exec(FileRead(filename), scope) 396 exec(gclient_utils.FileRead(filename), scope)
397 return scope["entries"] 397 return scope["entries"]
398 398
399 class FromImpl: 399 class FromImpl:
400 """Used to implement the From syntax.""" 400 """Used to implement the From syntax."""
401 401
402 def __init__(self, module_name): 402 def __init__(self, module_name):
403 self.module_name = module_name 403 self.module_name = module_name
404 404
405 def __str__(self): 405 def __str__(self):
406 return 'From("%s")' % self.module_name 406 return 'From("%s")' % self.module_name
407 407
408 class _VarImpl: 408 class _VarImpl:
409 def __init__(self, custom_vars, local_scope): 409 def __init__(self, custom_vars, local_scope):
410 self._custom_vars = custom_vars 410 self._custom_vars = custom_vars
411 self._local_scope = local_scope 411 self._local_scope = local_scope
412 412
413 def Lookup(self, var_name): 413 def Lookup(self, var_name):
414 """Implements the Var syntax.""" 414 """Implements the Var syntax."""
415 if var_name in self._custom_vars: 415 if var_name in self._custom_vars:
416 return self._custom_vars[var_name] 416 return self._custom_vars[var_name]
417 elif var_name in self._local_scope.get("vars", {}): 417 elif var_name in self._local_scope.get("vars", {}):
418 return self._local_scope["vars"][var_name] 418 return self._local_scope["vars"][var_name]
419 raise Error("Var is not defined: %s" % var_name) 419 raise gclient_utils.Error("Var is not defined: %s" % var_name)
420 420
421 def _ParseSolutionDeps(self, solution_name, solution_deps_content, 421 def _ParseSolutionDeps(self, solution_name, solution_deps_content,
422 custom_vars): 422 custom_vars):
423 """Parses the DEPS file for the specified solution. 423 """Parses the DEPS file for the specified solution.
424 424
425 Args: 425 Args:
426 solution_name: The name of the solution to query. 426 solution_name: The name of the solution to query.
427 solution_deps_content: Content of the DEPS file for the solution 427 solution_deps_content: Content of the DEPS file for the solution
428 custom_vars: A dict of vars to override any vars defined in the DEPS file. 428 custom_vars: A dict of vars to override any vars defined in the DEPS file.
429 429
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
543 if d in deps and type(deps[d]) != str: 543 if d in deps and type(deps[d]) != str:
544 if url.module_name == deps[d].module_name: 544 if url.module_name == deps[d].module_name:
545 continue 545 continue
546 else: 546 else:
547 parsed_url = urlparse.urlparse(url) 547 parsed_url = urlparse.urlparse(url)
548 scheme = parsed_url[0] 548 scheme = parsed_url[0]
549 if not scheme: 549 if not scheme:
550 # A relative url. Fetch the real base. 550 # A relative url. Fetch the real base.
551 path = parsed_url[2] 551 path = parsed_url[2]
552 if path[0] != "/": 552 if path[0] != "/":
553 raise Error( 553 raise gclient_utils.Error(
554 "relative DEPS entry \"%s\" must begin with a slash" % d) 554 "relative DEPS entry \"%s\" must begin with a slash" % d)
555 # Create a scm just to query the full url. 555 # Create a scm just to query the full url.
556 scm = gclient_scm.CreateSCM(solution["url"], self._root_dir, 556 scm = gclient_scm.CreateSCM(solution["url"], self._root_dir,
557 None) 557 None)
558 url = scm.FullUrlForRelativeUrl(url) 558 url = scm.FullUrlForRelativeUrl(url)
559 if d in deps and deps[d] != url: 559 if d in deps and deps[d] != url:
560 raise Error( 560 raise gclient_utils.Error(
561 "Solutions have conflicting versions of dependency \"%s\"" % d) 561 "Solutions have conflicting versions of dependency \"%s\"" % d)
562 if d in solution_urls and solution_urls[d] != url: 562 if d in solution_urls and solution_urls[d] != url:
563 raise Error( 563 raise gclient_utils.Error(
564 "Dependency \"%s\" conflicts with specified solution" % d) 564 "Dependency \"%s\" conflicts with specified solution" % d)
565 # Grab the dependency. 565 # Grab the dependency.
566 deps[d] = url 566 deps[d] = url
567 return deps 567 return deps
568 568
569 def _RunHookAction(self, hook_dict, matching_file_list): 569 def _RunHookAction(self, hook_dict, matching_file_list):
570 """Runs the action from a single hook. 570 """Runs the action from a single hook.
571 """ 571 """
572 command = hook_dict['action'][:] 572 command = hook_dict['action'][:]
573 if command[0] == 'python': 573 if command[0] == 'python':
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
606 # changed so we always run all hooks. 606 # changed so we always run all hooks.
607 if self._options.force or is_using_git: 607 if self._options.force or is_using_git:
608 for hook_dict in hooks: 608 for hook_dict in hooks:
609 self._RunHookAction(hook_dict, []) 609 self._RunHookAction(hook_dict, [])
610 return 610 return
611 611
612 # Run hooks on the basis of whether the files from the gclient operation 612 # Run hooks on the basis of whether the files from the gclient operation
613 # match each hook's pattern. 613 # match each hook's pattern.
614 for hook_dict in hooks: 614 for hook_dict in hooks:
615 pattern = re.compile(hook_dict['pattern']) 615 pattern = re.compile(hook_dict['pattern'])
616 matching_file_list = [file for file in file_list if pattern.search(file)] 616 matching_file_list = [f for f in file_list if pattern.search(f)]
617 if matching_file_list: 617 if matching_file_list:
618 self._RunHookAction(hook_dict, matching_file_list) 618 self._RunHookAction(hook_dict, matching_file_list)
619 619
620 def RunOnDeps(self, command, args): 620 def RunOnDeps(self, command, args):
621 """Runs a command on each dependency in a client and its dependencies. 621 """Runs a command on each dependency in a client and its dependencies.
622 622
623 The module's dependencies are specified in its top-level DEPS files. 623 The module's dependencies are specified in its top-level DEPS files.
624 624
625 Args: 625 Args:
626 command: The command to use (e.g., 'status' or 'diff') 626 command: The command to use (e.g., 'status' or 'diff')
627 args: list of str - extra arguments to add to the command line. 627 args: list of str - extra arguments to add to the command line.
628 628
629 Raises: 629 Raises:
630 Error: If the client has conflicting entries. 630 Error: If the client has conflicting entries.
631 """ 631 """
632 if not command in self.supported_commands: 632 if not command in self.supported_commands:
633 raise Error("'%s' is an unsupported command" % command) 633 raise gclient_utils.Error("'%s' is an unsupported command" % command)
634 634
635 # Check for revision overrides. 635 # Check for revision overrides.
636 revision_overrides = {} 636 revision_overrides = {}
637 for revision in self._options.revisions: 637 for revision in self._options.revisions:
638 if revision.find("@") == -1: 638 if revision.find("@") == -1:
639 raise Error( 639 raise gclient_utils.Error(
640 "Specify the full dependency when specifying a revision number.") 640 "Specify the full dependency when specifying a revision number.")
641 revision_elem = revision.split("@") 641 revision_elem = revision.split("@")
642 # Disallow conflicting revs 642 # Disallow conflicting revs
643 if revision_overrides.has_key(revision_elem[0]) and \ 643 if revision_overrides.has_key(revision_elem[0]) and \
644 revision_overrides[revision_elem[0]] != revision_elem[1]: 644 revision_overrides[revision_elem[0]] != revision_elem[1]:
645 raise Error( 645 raise gclient_utils.Error(
646 "Conflicting revision numbers specified.") 646 "Conflicting revision numbers specified.")
647 revision_overrides[revision_elem[0]] = revision_elem[1] 647 revision_overrides[revision_elem[0]] = revision_elem[1]
648 648
649 solutions = self.GetVar("solutions") 649 solutions = self.GetVar("solutions")
650 if not solutions: 650 if not solutions:
651 raise Error("No solution specified") 651 raise gclient_utils.Error("No solution specified")
652 652
653 # When running runhooks --force, there's no need to consult the SCM. 653 # When running runhooks --force, there's no need to consult the SCM.
654 # All known hooks are expected to run unconditionally regardless of working 654 # All known hooks are expected to run unconditionally regardless of working
655 # copy state, so skip the SCM status check. 655 # copy state, so skip the SCM status check.
656 run_scm = not (command == 'runhooks' and self._options.force) 656 run_scm = not (command == 'runhooks' and self._options.force)
657 657
658 entries = {} 658 entries = {}
659 entries_deps_content = {} 659 entries_deps_content = {}
660 file_list = [] 660 file_list = []
661 # Run on the base solutions first. 661 # Run on the base solutions first.
662 for solution in solutions: 662 for solution in solutions:
663 name = solution["name"] 663 name = solution["name"]
664 deps_file = solution.get("deps_file", self._options.deps_file) 664 deps_file = solution.get("deps_file", self._options.deps_file)
665 if '/' in deps_file or '\\' in deps_file: 665 if '/' in deps_file or '\\' in deps_file:
666 raise Error("deps_file name must not be a path, just a filename.") 666 raise gclient_utils.Error('deps_file name must not be a path, just a '
667 'filename.')
667 if name in entries: 668 if name in entries:
668 raise Error("solution %s specified more than once" % name) 669 raise gclient_utils.Error("solution %s specified more than once" % name)
669 url = solution["url"] 670 url = solution["url"]
670 entries[name] = url 671 entries[name] = url
671 if run_scm and url: 672 if run_scm and url:
672 self._options.revision = revision_overrides.get(name) 673 self._options.revision = revision_overrides.get(name)
673 scm = gclient_scm.CreateSCM(url, self._root_dir, name) 674 scm = gclient_scm.CreateSCM(url, self._root_dir, name)
674 scm.RunCommand(command, self._options, args, file_list) 675 scm.RunCommand(command, self._options, args, file_list)
675 file_list = [os.path.join(name, file.strip()) for file in file_list] 676 file_list = [os.path.join(name, f.strip()) for f in file_list]
676 self._options.revision = None 677 self._options.revision = None
677 try: 678 try:
678 deps_content = FileRead(os.path.join(self._root_dir, name, 679 deps_content = gclient_utils.FileRead(
679 deps_file)) 680 os.path.join(self._root_dir, name, deps_file))
680 except IOError, e: 681 except IOError, e:
681 if e.errno != errno.ENOENT: 682 if e.errno != errno.ENOENT:
682 raise 683 raise
683 deps_content = "" 684 deps_content = ""
684 entries_deps_content[name] = deps_content 685 entries_deps_content[name] = deps_content
685 686
686 # Process the dependencies next (sort alphanumerically to ensure that 687 # Process the dependencies next (sort alphanumerically to ensure that
687 # containing directories get populated first and for readability) 688 # containing directories get populated first and for readability)
688 deps = self._ParseAllDeps(entries, entries_deps_content) 689 deps = self._ParseAllDeps(entries, entries_deps_content)
689 deps_to_process = deps.keys() 690 deps_to_process = deps.keys()
690 deps_to_process.sort() 691 deps_to_process.sort()
691 692
692 # First pass for direct dependencies. 693 # First pass for direct dependencies.
693 for d in deps_to_process: 694 for d in deps_to_process:
694 if type(deps[d]) == str: 695 if type(deps[d]) == str:
695 url = deps[d] 696 url = deps[d]
696 entries[d] = url 697 entries[d] = url
697 if run_scm: 698 if run_scm:
698 self._options.revision = revision_overrides.get(d) 699 self._options.revision = revision_overrides.get(d)
699 scm = gclient_scm.CreateSCM(url, self._root_dir, d) 700 scm = gclient_scm.CreateSCM(url, self._root_dir, d)
700 scm.RunCommand(command, self._options, args, file_list) 701 scm.RunCommand(command, self._options, args, file_list)
701 self._options.revision = None 702 self._options.revision = None
702 703
703 # Second pass for inherited deps (via the From keyword) 704 # Second pass for inherited deps (via the From keyword)
704 for d in deps_to_process: 705 for d in deps_to_process:
705 if type(deps[d]) != str: 706 if type(deps[d]) != str:
706 sub_deps = self._ParseSolutionDeps( 707 filename = os.path.join(self._root_dir,
707 deps[d].module_name, 708 deps[d].module_name,
708 FileRead(os.path.join(self._root_dir, 709 self._options.deps_file)
709 deps[d].module_name, 710 content = gclient_utils.FileRead(filename)
710 self._options.deps_file)), 711 sub_deps = self._ParseSolutionDeps(deps[d].module_name, content, {})
711 {})
712 url = sub_deps[d] 712 url = sub_deps[d]
713 entries[d] = url 713 entries[d] = url
714 if run_scm: 714 if run_scm:
715 self._options.revision = revision_overrides.get(d) 715 self._options.revision = revision_overrides.get(d)
716 scm = gclient_scm.CreateSCM(url, self._root_dir, d) 716 scm = gclient_scm.CreateSCM(url, self._root_dir, d)
717 scm.RunCommand(command, self._options, args, file_list) 717 scm.RunCommand(command, self._options, args, file_list)
718 self._options.revision = None 718 self._options.revision = None
719 719
720 # Convert all absolute paths to relative. 720 # Convert all absolute paths to relative.
721 for i in range(len(file_list)): 721 for i in range(len(file_list)):
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
782 NOTE: Unlike RunOnDeps this does not require a local checkout and is run 782 NOTE: Unlike RunOnDeps this does not require a local checkout and is run
783 on the Pulse master. It MUST NOT execute hooks. 783 on the Pulse master. It MUST NOT execute hooks.
784 784
785 Raises: 785 Raises:
786 Error: If the client has conflicting entries. 786 Error: If the client has conflicting entries.
787 """ 787 """
788 # Check for revision overrides. 788 # Check for revision overrides.
789 revision_overrides = {} 789 revision_overrides = {}
790 for revision in self._options.revisions: 790 for revision in self._options.revisions:
791 if revision.find("@") < 0: 791 if revision.find("@") < 0:
792 raise Error( 792 raise gclient_utils.Error(
793 "Specify the full dependency when specifying a revision number.") 793 "Specify the full dependency when specifying a revision number.")
794 revision_elem = revision.split("@") 794 revision_elem = revision.split("@")
795 # Disallow conflicting revs 795 # Disallow conflicting revs
796 if revision_overrides.has_key(revision_elem[0]) and \ 796 if revision_overrides.has_key(revision_elem[0]) and \
797 revision_overrides[revision_elem[0]] != revision_elem[1]: 797 revision_overrides[revision_elem[0]] != revision_elem[1]:
798 raise Error( 798 raise gclient_utils.Error(
799 "Conflicting revision numbers specified.") 799 "Conflicting revision numbers specified.")
800 revision_overrides[revision_elem[0]] = revision_elem[1] 800 revision_overrides[revision_elem[0]] = revision_elem[1]
801 801
802 solutions = self.GetVar("solutions") 802 solutions = self.GetVar("solutions")
803 if not solutions: 803 if not solutions:
804 raise Error("No solution specified") 804 raise gclient_utils.Error("No solution specified")
805 805
806 entries = {} 806 entries = {}
807 entries_deps_content = {} 807 entries_deps_content = {}
808 808
809 # Inner helper to generate base url and rev tuple (including honoring 809 # Inner helper to generate base url and rev tuple (including honoring
810 # |revision_overrides|) 810 # |revision_overrides|)
811 def GetURLAndRev(name, original_url): 811 def GetURLAndRev(name, original_url):
812 if original_url.find("@") < 0: 812 if original_url.find("@") < 0:
813 if revision_overrides.has_key(name): 813 if revision_overrides.has_key(name):
814 return (original_url, revision_overrides[name]) 814 return (original_url, revision_overrides[name])
815 else: 815 else:
816 scm = gclient_scm.CreateSCM(solution["url"], self._root_dir, name) 816 scm = gclient_scm.CreateSCM(solution["url"], self._root_dir, name)
817 return (original_url, scm.revinfo(self._options, [], None)) 817 return (original_url, scm.revinfo(self._options, [], None))
818 else: 818 else:
819 url_components = original_url.split("@") 819 url_components = original_url.split("@")
820 if revision_overrides.has_key(name): 820 if revision_overrides.has_key(name):
821 return (url_components[0], revision_overrides[name]) 821 return (url_components[0], revision_overrides[name])
822 else: 822 else:
823 return (url_components[0], url_components[1]) 823 return (url_components[0], url_components[1])
824 824
825 # Run on the base solutions first. 825 # Run on the base solutions first.
826 for solution in solutions: 826 for solution in solutions:
827 name = solution["name"] 827 name = solution["name"]
828 if name in entries: 828 if name in entries:
829 raise Error("solution %s specified more than once" % name) 829 raise gclient_utils.Error("solution %s specified more than once" % name)
830 (url, rev) = GetURLAndRev(name, solution["url"]) 830 (url, rev) = GetURLAndRev(name, solution["url"])
831 entries[name] = "%s@%s" % (url, rev) 831 entries[name] = "%s@%s" % (url, rev)
832 # TODO(aharper): SVN/SCMWrapper cleanup (non-local commandset) 832 # TODO(aharper): SVN/SCMWrapper cleanup (non-local commandset)
833 entries_deps_content[name] = gclient_scm.CaptureSVN( 833 entries_deps_content[name] = gclient_scm.CaptureSVN(
834 ["cat", 834 ["cat",
835 "%s/%s@%s" % (url, 835 "%s/%s@%s" % (url,
836 self._options.deps_file, 836 self._options.deps_file,
837 rev)], 837 rev)],
838 os.getcwd()) 838 os.getcwd())
839 839
840 # Process the dependencies next (sort alphanumerically to ensure that 840 # Process the dependencies next (sort alphanumerically to ensure that
841 # containing directories get populated first and for readability) 841 # containing directories get populated first and for readability)
842 deps = self._ParseAllDeps(entries, entries_deps_content) 842 deps = self._ParseAllDeps(entries, entries_deps_content)
843 deps_to_process = deps.keys() 843 deps_to_process = deps.keys()
844 deps_to_process.sort() 844 deps_to_process.sort()
845 845
846 # First pass for direct dependencies. 846 # First pass for direct dependencies.
847 for d in deps_to_process: 847 for d in deps_to_process:
848 if type(deps[d]) == str: 848 if type(deps[d]) == str:
849 (url, rev) = GetURLAndRev(d, deps[d]) 849 (url, rev) = GetURLAndRev(d, deps[d])
850 entries[d] = "%s@%s" % (url, rev) 850 entries[d] = "%s@%s" % (url, rev)
851 851
852 # Second pass for inherited deps (via the From keyword) 852 # Second pass for inherited deps (via the From keyword)
853 for d in deps_to_process: 853 for d in deps_to_process:
854 if type(deps[d]) != str: 854 if type(deps[d]) != str:
855 deps_parent_url = entries[deps[d].module_name] 855 deps_parent_url = entries[deps[d].module_name]
856 if deps_parent_url.find("@") < 0: 856 if deps_parent_url.find("@") < 0:
857 raise Error("From %s missing revisioned url" % deps[d].module_name) 857 raise gclient_utils.Error("From %s missing revisioned url" %
858 deps_parent_url_components = deps_parent_url.split("@") 858 deps[d].module_name)
859 # TODO(aharper): SVN/SCMWrapper cleanup (non-local commandset) 859 content = gclient_utils.FileRead(os.path.join(self._root_dir,
860 deps_parent_content = gclient_scm.CaptureSVN( 860 deps[d].module_name,
Dirk Pranke 2009/11/10 19:49:24 You're sure this file will already be local? (I'm
M-A Ruel 2009/11/10 20:02:23 If you look at the old code, it was running [svn c
861 ["cat", 861 self._options.deps_file))
862 "%s/%s@%s" % (deps_parent_url_components[0], 862 sub_deps = self._ParseSolutionDeps(deps[d].module_name, content, {})
863 self._options.deps_file,
864 deps_parent_url_components[1])],
865 os.getcwd())
866 sub_deps = self._ParseSolutionDeps(
867 deps[d].module_name,
868 FileRead(os.path.join(self._root_dir,
869 deps[d].module_name,
870 self._options.deps_file)),
871 {})
872 (url, rev) = GetURLAndRev(d, sub_deps[d]) 863 (url, rev) = GetURLAndRev(d, sub_deps[d])
873 entries[d] = "%s@%s" % (url, rev) 864 entries[d] = "%s@%s" % (url, rev)
874 print(";\n\n".join(["%s: %s" % (x, entries[x]) 865 print(";\n\n".join(["%s: %s" % (x, entries[x])
875 for x in sorted(entries.keys())])) 866 for x in sorted(entries.keys())]))
876 867
877 868
878 ## gclient commands. 869 ## gclient commands.
879 870
880 871
881 def DoCleanup(options, args): 872 def DoCleanup(options, args):
882 """Handle the cleanup subcommand. 873 """Handle the cleanup subcommand.
883 874
884 Raises: 875 Raises:
885 Error: if client isn't configured properly. 876 Error: if client isn't configured properly.
886 """ 877 """
887 client = GClient.LoadCurrentConfig(options) 878 client = GClient.LoadCurrentConfig(options)
888 if not client: 879 if not client:
889 raise Error("client not configured; see 'gclient config'") 880 raise gclient_utils.Error("client not configured; see 'gclient config'")
890 if options.verbose: 881 if options.verbose:
891 # Print out the .gclient file. This is longer than if we just printed the 882 # Print out the .gclient file. This is longer than if we just printed the
892 # client dict, but more legible, and it might contain helpful comments. 883 # client dict, but more legible, and it might contain helpful comments.
893 print(client.ConfigContent()) 884 print(client.ConfigContent())
894 return client.RunOnDeps('cleanup', args) 885 return client.RunOnDeps('cleanup', args)
895 886
896 887
897 def DoConfig(options, args): 888 def DoConfig(options, args):
898 """Handle the config subcommand. 889 """Handle the config subcommand.
899 890
900 Args: 891 Args:
901 options: If options.spec set, a string providing contents of config file. 892 options: If options.spec set, a string providing contents of config file.
902 args: The command line args. If spec is not set, 893 args: The command line args. If spec is not set,
903 then args[0] is a string URL to get for config file. 894 then args[0] is a string URL to get for config file.
904 895
905 Raises: 896 Raises:
906 Error: on usage error 897 Error: on usage error
907 """ 898 """
908 if len(args) < 1 and not options.spec: 899 if len(args) < 1 and not options.spec:
909 raise Error("required argument missing; see 'gclient help config'") 900 raise gclient_utils.Error("required argument missing; see 'gclient help "
901 "config'")
910 if os.path.exists(options.config_filename): 902 if os.path.exists(options.config_filename):
911 raise Error("%s file already exists in the current directory" % 903 raise gclient_utils.Error("%s file already exists in the current directory"
912 options.config_filename) 904 % options.config_filename)
913 client = GClient('.', options) 905 client = GClient('.', options)
914 if options.spec: 906 if options.spec:
915 client.SetConfig(options.spec) 907 client.SetConfig(options.spec)
916 else: 908 else:
917 # TODO(darin): it would be nice to be able to specify an alternate relpath 909 # TODO(darin): it would be nice to be able to specify an alternate relpath
918 # for the given URL. 910 # for the given URL.
919 base_url = args[0].rstrip('/') 911 base_url = args[0].rstrip('/')
920 name = base_url.split("/")[-1] 912 name = base_url.split("/")[-1]
921 safesync_url = "" 913 safesync_url = ""
922 if len(args) > 1: 914 if len(args) > 1:
923 safesync_url = args[1] 915 safesync_url = args[1]
924 client.SetDefaultConfig(name, base_url, safesync_url) 916 client.SetDefaultConfig(name, base_url, safesync_url)
925 client.SaveConfig() 917 client.SaveConfig()
926 918
927 919
928 def DoExport(options, args): 920 def DoExport(options, args):
929 """Handle the export subcommand. 921 """Handle the export subcommand.
930 922
931 Raises: 923 Raises:
932 Error: on usage error 924 Error: on usage error
933 """ 925 """
934 if len(args) != 1: 926 if len(args) != 1:
935 raise Error("Need directory name") 927 raise gclient_utils.Error("Need directory name")
936 client = GClient.LoadCurrentConfig(options) 928 client = GClient.LoadCurrentConfig(options)
937 929
938 if not client: 930 if not client:
939 raise Error("client not configured; see 'gclient config'") 931 raise gclient_utils.Error("client not configured; see 'gclient config'")
940 932
941 if options.verbose: 933 if options.verbose:
942 # Print out the .gclient file. This is longer than if we just printed the 934 # Print out the .gclient file. This is longer than if we just printed the
943 # client dict, but more legible, and it might contain helpful comments. 935 # client dict, but more legible, and it might contain helpful comments.
944 print(client.ConfigContent()) 936 print(client.ConfigContent())
945 return client.RunOnDeps('export', args) 937 return client.RunOnDeps('export', args)
946 938
947 def DoHelp(options, args): 939 def DoHelp(options, args):
948 """Handle the help subcommand giving help for another subcommand. 940 """Handle the help subcommand giving help for another subcommand.
949 941
950 Raises: 942 Raises:
951 Error: if the command is unknown. 943 Error: if the command is unknown.
952 """ 944 """
945 __pychecker__ = 'unusednames=options'
953 if len(args) == 1 and args[0] in COMMAND_USAGE_TEXT: 946 if len(args) == 1 and args[0] in COMMAND_USAGE_TEXT:
954 print(COMMAND_USAGE_TEXT[args[0]]) 947 print(COMMAND_USAGE_TEXT[args[0]])
955 else: 948 else:
956 raise Error("unknown subcommand '%s'; see 'gclient help'" % args[0]) 949 raise gclient_utils.Error("unknown subcommand '%s'; see 'gclient help'" %
950 args[0])
957 951
958 952
959 def DoPack(options, args): 953 def DoPack(options, args):
960 """Handle the pack subcommand. 954 """Handle the pack subcommand.
961 955
962 Raises: 956 Raises:
963 Error: if client isn't configured properly. 957 Error: if client isn't configured properly.
964 """ 958 """
965 client = GClient.LoadCurrentConfig(options) 959 client = GClient.LoadCurrentConfig(options)
966 if not client: 960 if not client:
967 raise Error("client not configured; see 'gclient config'") 961 raise gclient_utils.Error("client not configured; see 'gclient config'")
968 if options.verbose: 962 if options.verbose:
969 # Print out the .gclient file. This is longer than if we just printed the 963 # Print out the .gclient file. This is longer than if we just printed the
970 # client dict, but more legible, and it might contain helpful comments. 964 # client dict, but more legible, and it might contain helpful comments.
971 print(client.ConfigContent()) 965 print(client.ConfigContent())
972 return client.RunOnDeps('pack', args) 966 return client.RunOnDeps('pack', args)
973 967
974 968
975 def DoStatus(options, args): 969 def DoStatus(options, args):
976 """Handle the status subcommand. 970 """Handle the status subcommand.
977 971
978 Raises: 972 Raises:
979 Error: if client isn't configured properly. 973 Error: if client isn't configured properly.
980 """ 974 """
981 client = GClient.LoadCurrentConfig(options) 975 client = GClient.LoadCurrentConfig(options)
982 if not client: 976 if not client:
983 raise Error("client not configured; see 'gclient config'") 977 raise gclient_utils.Error("client not configured; see 'gclient config'")
984 if options.verbose: 978 if options.verbose:
985 # Print out the .gclient file. This is longer than if we just printed the 979 # Print out the .gclient file. This is longer than if we just printed the
986 # client dict, but more legible, and it might contain helpful comments. 980 # client dict, but more legible, and it might contain helpful comments.
987 print(client.ConfigContent()) 981 print(client.ConfigContent())
988 return client.RunOnDeps('status', args) 982 return client.RunOnDeps('status', args)
989 983
990 984
991 def DoUpdate(options, args): 985 def DoUpdate(options, args):
992 """Handle the update and sync subcommands. 986 """Handle the update and sync subcommands.
993 987
994 Raises: 988 Raises:
995 Error: if client isn't configured properly. 989 Error: if client isn't configured properly.
996 """ 990 """
997 client = GClient.LoadCurrentConfig(options) 991 client = GClient.LoadCurrentConfig(options)
998 992
999 if not client: 993 if not client:
1000 raise Error("client not configured; see 'gclient config'") 994 raise gclient_utils.Error("client not configured; see 'gclient config'")
1001 995
1002 if not options.head: 996 if not options.head:
1003 solutions = client.GetVar('solutions') 997 solutions = client.GetVar('solutions')
1004 if solutions: 998 if solutions:
1005 for s in solutions: 999 for s in solutions:
1006 if s.get('safesync_url', ''): 1000 if s.get('safesync_url', ''):
1007 # rip through revisions and make sure we're not over-riding 1001 # rip through revisions and make sure we're not over-riding
1008 # something that was explicitly passed 1002 # something that was explicitly passed
1009 has_key = False 1003 has_key = False
1010 for r in options.revisions: 1004 for r in options.revisions:
(...skipping 16 matching lines...) Expand all
1027 1021
1028 1022
1029 def DoDiff(options, args): 1023 def DoDiff(options, args):
1030 """Handle the diff subcommand. 1024 """Handle the diff subcommand.
1031 1025
1032 Raises: 1026 Raises:
1033 Error: if client isn't configured properly. 1027 Error: if client isn't configured properly.
1034 """ 1028 """
1035 client = GClient.LoadCurrentConfig(options) 1029 client = GClient.LoadCurrentConfig(options)
1036 if not client: 1030 if not client:
1037 raise Error("client not configured; see 'gclient config'") 1031 raise gclient_utils.Error("client not configured; see 'gclient config'")
1038 if options.verbose: 1032 if options.verbose:
1039 # Print out the .gclient file. This is longer than if we just printed the 1033 # Print out the .gclient file. This is longer than if we just printed the
1040 # client dict, but more legible, and it might contain helpful comments. 1034 # client dict, but more legible, and it might contain helpful comments.
1041 print(client.ConfigContent()) 1035 print(client.ConfigContent())
1042 return client.RunOnDeps('diff', args) 1036 return client.RunOnDeps('diff', args)
1043 1037
1044 1038
1045 def DoRevert(options, args): 1039 def DoRevert(options, args):
1046 """Handle the revert subcommand. 1040 """Handle the revert subcommand.
1047 1041
1048 Raises: 1042 Raises:
1049 Error: if client isn't configured properly. 1043 Error: if client isn't configured properly.
1050 """ 1044 """
1051 client = GClient.LoadCurrentConfig(options) 1045 client = GClient.LoadCurrentConfig(options)
1052 if not client: 1046 if not client:
1053 raise Error("client not configured; see 'gclient config'") 1047 raise gclient_utils.Error("client not configured; see 'gclient config'")
1054 return client.RunOnDeps('revert', args) 1048 return client.RunOnDeps('revert', args)
1055 1049
1056 1050
1057 def DoRunHooks(options, args): 1051 def DoRunHooks(options, args):
1058 """Handle the runhooks subcommand. 1052 """Handle the runhooks subcommand.
1059 1053
1060 Raises: 1054 Raises:
1061 Error: if client isn't configured properly. 1055 Error: if client isn't configured properly.
1062 """ 1056 """
1063 client = GClient.LoadCurrentConfig(options) 1057 client = GClient.LoadCurrentConfig(options)
1064 if not client: 1058 if not client:
1065 raise Error("client not configured; see 'gclient config'") 1059 raise gclient_utils.Error("client not configured; see 'gclient config'")
1066 if options.verbose: 1060 if options.verbose:
1067 # Print out the .gclient file. This is longer than if we just printed the 1061 # Print out the .gclient file. This is longer than if we just printed the
1068 # client dict, but more legible, and it might contain helpful comments. 1062 # client dict, but more legible, and it might contain helpful comments.
1069 print(client.ConfigContent()) 1063 print(client.ConfigContent())
1070 options.force = True 1064 options.force = True
1071 return client.RunOnDeps('runhooks', args) 1065 return client.RunOnDeps('runhooks', args)
1072 1066
1073 1067
1074 def DoRevInfo(options, args): 1068 def DoRevInfo(options, args):
1075 """Handle the revinfo subcommand. 1069 """Handle the revinfo subcommand.
1076 1070
1077 Raises: 1071 Raises:
1078 Error: if client isn't configured properly. 1072 Error: if client isn't configured properly.
1079 """ 1073 """
1074 __pychecker__ = 'unusednames=args'
1080 client = GClient.LoadCurrentConfig(options) 1075 client = GClient.LoadCurrentConfig(options)
1081 if not client: 1076 if not client:
1082 raise Error("client not configured; see 'gclient config'") 1077 raise gclient_utils.Error("client not configured; see 'gclient config'")
1083 client.PrintRevInfo() 1078 client.PrintRevInfo()
1084 1079
1085 1080
1086 gclient_command_map = { 1081 gclient_command_map = {
1087 "cleanup": DoCleanup, 1082 "cleanup": DoCleanup,
1088 "config": DoConfig, 1083 "config": DoConfig,
1089 "diff": DoDiff, 1084 "diff": DoDiff,
1090 "export": DoExport, 1085 "export": DoExport,
1091 "help": DoHelp, 1086 "help": DoHelp,
1092 "pack": DoPack, 1087 "pack": DoPack,
1093 "status": DoStatus, 1088 "status": DoStatus,
1094 "sync": DoUpdate, 1089 "sync": DoUpdate,
1095 "update": DoUpdate, 1090 "update": DoUpdate,
1096 "revert": DoRevert, 1091 "revert": DoRevert,
1097 "runhooks": DoRunHooks, 1092 "runhooks": DoRunHooks,
1098 "revinfo" : DoRevInfo, 1093 "revinfo" : DoRevInfo,
1099 } 1094 }
1100 1095
1101 1096
1102 def DispatchCommand(command, options, args, command_map=None): 1097 def DispatchCommand(command, options, args, command_map=None):
1103 """Dispatches the appropriate subcommand based on command line arguments.""" 1098 """Dispatches the appropriate subcommand based on command line arguments."""
1104 if command_map is None: 1099 if command_map is None:
1105 command_map = gclient_command_map 1100 command_map = gclient_command_map
1106 1101
1107 if command in command_map: 1102 if command in command_map:
1108 return command_map[command](options, args) 1103 return command_map[command](options, args)
1109 else: 1104 else:
1110 raise Error("unknown subcommand '%s'; see 'gclient help'" % command) 1105 raise gclient_utils.Error("unknown subcommand '%s'; see 'gclient help'" %
1106 command)
1111 1107
1112 1108
1113 def Main(argv): 1109 def Main(argv):
1114 """Parse command line arguments and dispatch command.""" 1110 """Parse command line arguments and dispatch command."""
1115 1111
1116 option_parser = optparse.OptionParser(usage=DEFAULT_USAGE_TEXT, 1112 option_parser = optparse.OptionParser(usage=DEFAULT_USAGE_TEXT,
1117 version=__version__) 1113 version=__version__)
1118 option_parser.disable_interspersed_args() 1114 option_parser.disable_interspersed_args()
1119 option_parser.add_option("", "--force", action="store_true", default=False, 1115 option_parser.add_option("", "--force", action="store_true", default=False,
1120 help=("(update/sync only) force update even " 1116 help=("(update/sync only) force update even "
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1178 options.entries_filename = ".gclient_entries" 1174 options.entries_filename = ".gclient_entries"
1179 options.deps_file = "DEPS" 1175 options.deps_file = "DEPS"
1180 1176
1181 options.platform = sys.platform 1177 options.platform = sys.platform
1182 return DispatchCommand(command, options, args) 1178 return DispatchCommand(command, options, args)
1183 1179
1184 1180
1185 if "__main__" == __name__: 1181 if "__main__" == __name__:
1186 try: 1182 try:
1187 result = Main(sys.argv) 1183 result = Main(sys.argv)
1188 except Error, e: 1184 except gclient_utils.Error, e:
1189 print >> sys.stderr, "Error: %s" % str(e) 1185 print >> sys.stderr, "Error: %s" % str(e)
1190 result = 1 1186 result = 1
1191 sys.exit(result) 1187 sys.exit(result)
1192 1188
1193 # vim: ts=2:sw=2:tw=80:et: 1189 # vim: ts=2:sw=2:tw=80:et:
OLDNEW
« no previous file with comments | « gcl.py ('k') | gclient_scm.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698