Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2011 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2011 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 """Meta checkout manager supporting both Subversion and GIT. | 6 """Meta checkout manager supporting both Subversion and GIT. |
| 7 | 7 |
| 8 Files | 8 Files |
| 9 .gclient : Current client configuration, written by 'config' command. | 9 .gclient : Current client configuration, written by 'config' command. |
| 10 Format is a Python script defining 'solutions', a list whose | 10 Format is a Python script defining 'solutions', a list whose |
| (...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 259 local_scope = {} | 259 local_scope = {} |
| 260 var = self.VarImpl(self.custom_vars, local_scope) | 260 var = self.VarImpl(self.custom_vars, local_scope) |
| 261 global_scope = { | 261 global_scope = { |
| 262 'File': self.FileImpl, | 262 'File': self.FileImpl, |
| 263 'From': self.FromImpl, | 263 'From': self.FromImpl, |
| 264 'Var': var.Lookup, | 264 'Var': var.Lookup, |
| 265 'deps_os': {}, | 265 'deps_os': {}, |
| 266 } | 266 } |
| 267 filepath = os.path.join(self.root_dir(), self.name, self.deps_file) | 267 filepath = os.path.join(self.root_dir(), self.name, self.deps_file) |
| 268 if not os.path.isfile(filepath): | 268 if not os.path.isfile(filepath): |
| 269 logging.info('%s: No DEPS file found at %s' % (self.name, filepath)) | 269 logging.info('%s: No %s file found at %s' % (self.name, self.deps_file, |
| 270 filepath)) | |
| 270 else: | 271 else: |
| 271 deps_content = gclient_utils.FileRead(filepath) | 272 deps_content = gclient_utils.FileRead(filepath) |
| 272 logging.debug(deps_content) | 273 logging.debug(deps_content) |
| 273 # Eval the content. | 274 # Eval the content. |
| 274 try: | 275 try: |
| 275 exec(deps_content, global_scope, local_scope) | 276 exec(deps_content, global_scope, local_scope) |
| 276 except SyntaxError, e: | 277 except SyntaxError, e: |
| 277 gclient_utils.SyntaxErrorToError(filepath, e) | 278 gclient_utils.SyntaxErrorToError(filepath, e) |
| 278 deps = local_scope.get('deps', {}) | 279 deps = local_scope.get('deps', {}) |
| 279 # load os specific dependencies if defined. these dependencies may | 280 # load os specific dependencies if defined. these dependencies may |
| (...skipping 298 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 578 "mac": "mac", | 579 "mac": "mac", |
| 579 "unix": "unix", | 580 "unix": "unix", |
| 580 "linux": "unix", | 581 "linux": "unix", |
| 581 "linux2": "unix", | 582 "linux2": "unix", |
| 582 } | 583 } |
| 583 | 584 |
| 584 DEFAULT_CLIENT_FILE_TEXT = ("""\ | 585 DEFAULT_CLIENT_FILE_TEXT = ("""\ |
| 585 solutions = [ | 586 solutions = [ |
| 586 { "name" : "%(solution_name)s", | 587 { "name" : "%(solution_name)s", |
| 587 "url" : "%(solution_url)s", | 588 "url" : "%(solution_url)s", |
| 589 "deps_file" : "%(deps_file)s", | |
| 588 "custom_deps" : { | 590 "custom_deps" : { |
| 589 }, | 591 }, |
| 590 "safesync_url": "%(safesync_url)s", | 592 "safesync_url": "%(safesync_url)s", |
| 591 }, | 593 }, |
| 592 ] | 594 ] |
| 593 """) | 595 """) |
| 594 | 596 |
| 595 DEFAULT_SNAPSHOT_SOLUTION_TEXT = ("""\ | 597 DEFAULT_SNAPSHOT_SOLUTION_TEXT = ("""\ |
| 596 { "name" : "%(solution_name)s", | 598 { "name" : "%(solution_name)s", |
| 597 "url" : "%(solution_url)s", | 599 "url" : "%(solution_url)s", |
| 600 "deps_file" : "%(deps_file)s", | |
| 598 "custom_deps" : { | 601 "custom_deps" : { |
| 599 %(solution_deps)s }, | 602 %(solution_deps)s }, |
| 600 "safesync_url": "%(safesync_url)s", | 603 "safesync_url": "%(safesync_url)s", |
| 601 }, | 604 }, |
| 602 """) | 605 """) |
| 603 | 606 |
| 604 DEFAULT_SNAPSHOT_FILE_TEXT = ("""\ | 607 DEFAULT_SNAPSHOT_FILE_TEXT = ("""\ |
| 605 # Snapshot generated with gclient revinfo --snapshot | 608 # Snapshot generated with gclient revinfo --snapshot |
| 606 solutions = [ | 609 solutions = [ |
| 607 %(solution_list)s] | 610 %(solution_list)s] |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 635 try: | 638 try: |
| 636 tree = dict((d.name, d) for d in self.tree(False)) | 639 tree = dict((d.name, d) for d in self.tree(False)) |
| 637 if s['name'] in tree: | 640 if s['name'] in tree: |
| 638 raise gclient_utils.Error( | 641 raise gclient_utils.Error( |
| 639 'Dependency %s specified more than once in .gclient' % s['name']) | 642 'Dependency %s specified more than once in .gclient' % s['name']) |
| 640 self.dependencies.append(Dependency( | 643 self.dependencies.append(Dependency( |
| 641 self, s['name'], s['url'], | 644 self, s['name'], s['url'], |
| 642 s.get('safesync_url', None), | 645 s.get('safesync_url', None), |
| 643 s.get('custom_deps', {}), | 646 s.get('custom_deps', {}), |
| 644 s.get('custom_vars', {}), | 647 s.get('custom_vars', {}), |
| 645 None, | 648 s.get('deps_file', None), |
| 646 True)) | 649 True)) |
| 647 except KeyError: | 650 except KeyError: |
| 648 raise gclient_utils.Error('Invalid .gclient file. Solution is ' | 651 raise gclient_utils.Error('Invalid .gclient file. Solution is ' |
| 649 'incomplete: %s' % s) | 652 'incomplete: %s' % s) |
| 650 # .gclient can have hooks. | 653 # .gclient can have hooks. |
| 651 self.deps_hooks = config_dict.get('hooks', []) | 654 self.deps_hooks = config_dict.get('hooks', []) |
| 652 self.deps_parsed = True | 655 self.deps_parsed = True |
| 653 | 656 |
| 654 def SaveConfig(self): | 657 def SaveConfig(self): |
| 655 gclient_utils.FileWrite(os.path.join(self.root_dir(), | 658 gclient_utils.FileWrite(os.path.join(self.root_dir(), |
| 656 self._options.config_filename), | 659 self._options.config_filename), |
| 657 self.config_content) | 660 self.config_content) |
| 658 | 661 |
| 659 @staticmethod | 662 @staticmethod |
| 660 def LoadCurrentConfig(options): | 663 def LoadCurrentConfig(options): |
| 661 """Searches for and loads a .gclient file relative to the current working | 664 """Searches for and loads a .gclient file relative to the current working |
| 662 dir. Returns a GClient object.""" | 665 dir. Returns a GClient object.""" |
| 663 path = gclient_utils.FindGclientRoot(os.getcwd(), options.config_filename) | 666 path = gclient_utils.FindGclientRoot(os.getcwd(), options.config_filename) |
| 664 if not path: | 667 if not path: |
| 665 return None | 668 return None |
| 666 client = GClient(path, options) | 669 client = GClient(path, options) |
| 667 client.SetConfig(gclient_utils.FileRead( | 670 client.SetConfig(gclient_utils.FileRead( |
| 668 os.path.join(path, options.config_filename))) | 671 os.path.join(path, options.config_filename))) |
| 669 return client | 672 return client |
| 670 | 673 |
| 671 def SetDefaultConfig(self, solution_name, solution_url, safesync_url): | 674 def SetDefaultConfig(self, solution_name, deps_file, solution_url, |
| 675 safesync_url): | |
| 672 self.SetConfig(self.DEFAULT_CLIENT_FILE_TEXT % { | 676 self.SetConfig(self.DEFAULT_CLIENT_FILE_TEXT % { |
| 673 'solution_name': solution_name, | 677 'solution_name': solution_name, |
| 674 'solution_url': solution_url, | 678 'solution_url': solution_url, |
| 679 'deps_file': deps_file, | |
| 675 'safesync_url' : safesync_url, | 680 'safesync_url' : safesync_url, |
| 676 }) | 681 }) |
| 677 | 682 |
| 678 def _SaveEntries(self): | 683 def _SaveEntries(self): |
| 679 """Creates a .gclient_entries file to record the list of unique checkouts. | 684 """Creates a .gclient_entries file to record the list of unique checkouts. |
| 680 | 685 |
| 681 The .gclient_entries file lives in the same directory as .gclient. | 686 The .gclient_entries file lives in the same directory as .gclient. |
| 682 """ | 687 """ |
| 683 # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It | 688 # Sometimes pprint.pformat will use {', sometimes it'll use { ' ... It |
| 684 # makes testing a bit too fun. | 689 # makes testing a bit too fun. |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 839 custom_deps = [] | 844 custom_deps = [] |
| 840 for k in sorted(entries.keys()): | 845 for k in sorted(entries.keys()): |
| 841 if entries[k]: | 846 if entries[k]: |
| 842 # Quotes aren't escaped... | 847 # Quotes aren't escaped... |
| 843 custom_deps.append(' \"%s\": \'%s\',\n' % (k, entries[k])) | 848 custom_deps.append(' \"%s\": \'%s\',\n' % (k, entries[k])) |
| 844 else: | 849 else: |
| 845 custom_deps.append(' \"%s\": None,\n' % k) | 850 custom_deps.append(' \"%s\": None,\n' % k) |
| 846 new_gclient += self.DEFAULT_SNAPSHOT_SOLUTION_TEXT % { | 851 new_gclient += self.DEFAULT_SNAPSHOT_SOLUTION_TEXT % { |
| 847 'solution_name': d.name, | 852 'solution_name': d.name, |
| 848 'solution_url': d.url, | 853 'solution_url': d.url, |
| 854 'deps_file': d.deps_file, | |
| 849 'safesync_url' : d.safesync_url or '', | 855 'safesync_url' : d.safesync_url or '', |
| 850 'solution_deps': ''.join(custom_deps), | 856 'solution_deps': ''.join(custom_deps), |
| 851 } | 857 } |
| 852 # Print the snapshot configuration file | 858 # Print the snapshot configuration file |
| 853 print(self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient}) | 859 print(self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient}) |
| 854 else: | 860 else: |
| 855 entries = {} | 861 entries = {} |
| 856 for d in self.tree(False): | 862 for d in self.tree(False): |
| 857 if self._options.actual: | 863 if self._options.actual: |
| 858 entries[d.name] = GetURLAndRev(d) | 864 entries[d.name] = GetURLAndRev(d) |
| (...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 957 modules to operate on as well. If optional [url] parameter is | 963 modules to operate on as well. If optional [url] parameter is |
| 958 provided, then configuration is read from a specified Subversion server | 964 provided, then configuration is read from a specified Subversion server |
| 959 URL. | 965 URL. |
| 960 """ | 966 """ |
| 961 parser.add_option('--spec', | 967 parser.add_option('--spec', |
| 962 help='create a gclient file containing the provided ' | 968 help='create a gclient file containing the provided ' |
| 963 'string. Due to Cygwin/Python brokenness, it ' | 969 'string. Due to Cygwin/Python brokenness, it ' |
| 964 'probably can\'t contain any newlines.') | 970 'probably can\'t contain any newlines.') |
| 965 parser.add_option('--name', | 971 parser.add_option('--name', |
| 966 help='overrides the default name for the solution') | 972 help='overrides the default name for the solution') |
| 973 parser.add_option('--deps-file', default='DEPS', | |
| 974 help='overrides the default name for the DEPS file') | |
|
cmp
2011/05/26 21:04:20
Can we add '--git-deps'? It would be a boolean fl
nsylvain
2011/05/26 21:13:28
Done.
| |
| 967 (options, args) = parser.parse_args(args) | 975 (options, args) = parser.parse_args(args) |
| 968 if ((options.spec and args) or len(args) > 2 or | 976 if ((options.spec and args) or len(args) > 2 or |
| 969 (not options.spec and not args)): | 977 (not options.spec and not args)): |
| 970 parser.error('Inconsistent arguments. Use either --spec or one or 2 args') | 978 parser.error('Inconsistent arguments. Use either --spec or one or 2 args') |
| 971 | 979 |
| 972 if os.path.exists(options.config_filename): | 980 if os.path.exists(options.config_filename): |
| 973 raise gclient_utils.Error('%s file already exists in the current directory' | 981 raise gclient_utils.Error('%s file already exists in the current directory' |
| 974 % options.config_filename) | 982 % options.config_filename) |
| 975 client = GClient('.', options) | 983 client = GClient('.', options) |
| 976 if options.spec: | 984 if options.spec: |
| 977 client.SetConfig(options.spec) | 985 client.SetConfig(options.spec) |
| 978 else: | 986 else: |
| 979 base_url = args[0].rstrip('/') | 987 base_url = args[0].rstrip('/') |
| 980 if not options.name: | 988 if not options.name: |
| 981 name = base_url.split('/')[-1] | 989 name = base_url.split('/')[-1] |
| 982 else: | 990 else: |
| 983 # specify an alternate relpath for the given URL. | 991 # specify an alternate relpath for the given URL. |
| 984 name = options.name | 992 name = options.name |
| 985 safesync_url = '' | 993 safesync_url = '' |
| 986 if len(args) > 1: | 994 if len(args) > 1: |
| 987 safesync_url = args[1] | 995 safesync_url = args[1] |
| 988 client.SetDefaultConfig(name, base_url, safesync_url) | 996 client.SetDefaultConfig(name, options.deps_file, base_url, safesync_url) |
| 989 client.SaveConfig() | 997 client.SaveConfig() |
| 990 return 0 | 998 return 0 |
| 991 | 999 |
| 992 | 1000 |
| 993 @attr('epilog', """Example: | 1001 @attr('epilog', """Example: |
| 994 gclient pack > patch.txt | 1002 gclient pack > patch.txt |
| 995 generate simple patch for configured client and dependences | 1003 generate simple patch for configured client and dependences |
| 996 """) | 1004 """) |
| 997 def CMDpack(parser, args): | 1005 def CMDpack(parser, args): |
| 998 """Generate a patch which can be applied at the root of the tree. | 1006 """Generate a patch which can be applied at the root of the tree. |
| (...skipping 286 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1285 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 1293 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
| 1286 print >> sys.stderr, 'Error: %s' % str(e) | 1294 print >> sys.stderr, 'Error: %s' % str(e) |
| 1287 return 1 | 1295 return 1 |
| 1288 | 1296 |
| 1289 | 1297 |
| 1290 if '__main__' == __name__: | 1298 if '__main__' == __name__: |
| 1291 fix_encoding.fix_encoding() | 1299 fix_encoding.fix_encoding() |
| 1292 sys.exit(Main(sys.argv[1:])) | 1300 sys.exit(Main(sys.argv[1:])) |
| 1293 | 1301 |
| 1294 # vim: ts=2:sw=2:tw=80:et: | 1302 # vim: ts=2:sw=2:tw=80:et: |
| OLD | NEW |