OLD | NEW |
---|---|
1 #!/usr/bin/python | 1 #!/usr/bin/python |
2 # Copyright (c) 2010 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2010 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 148 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
159 self.parent = parent | 159 self.parent = parent |
160 self.name = name | 160 self.name = name |
161 self.url = url | 161 self.url = url |
162 # These 2 are only set in .gclient and not in DEPS files. | 162 # These 2 are only set in .gclient and not in DEPS files. |
163 self.safesync_url = safesync_url | 163 self.safesync_url = safesync_url |
164 self.custom_vars = custom_vars or {} | 164 self.custom_vars = custom_vars or {} |
165 self.custom_deps = custom_deps or {} | 165 self.custom_deps = custom_deps or {} |
166 self.deps_hooks = [] | 166 self.deps_hooks = [] |
167 self.dependencies = [] | 167 self.dependencies = [] |
168 self.deps_file = deps_file or self.DEPS_FILE | 168 self.deps_file = deps_file or self.DEPS_FILE |
169 self.deps_parsed = False | |
170 self.direct_reference = False | |
171 | 169 |
172 # Sanity checks | 170 # Sanity checks |
173 if not self.name and self.parent: | 171 if not self.name and self.parent: |
174 raise gclient_utils.Error('Dependency without name') | 172 raise gclient_utils.Error('Dependency without name') |
175 if not isinstance(self.url, | 173 if not isinstance(self.url, |
176 (basestring, self.FromImpl, self.FileImpl, None.__class__)): | 174 (basestring, self.FromImpl, self.FileImpl, None.__class__)): |
177 raise gclient_utils.Error('dependency url must be either a string, None, ' | 175 raise gclient_utils.Error('dependency url must be either a string, None, ' |
178 'File() or From() instead of %s' % | 176 'File() or From() instead of %s' % |
179 self.url.__class__.__name__) | 177 self.url.__class__.__name__) |
180 if '/' in self.deps_file or '\\' in self.deps_file: | 178 if '/' in self.deps_file or '\\' in self.deps_file: |
181 raise gclient_utils.Error('deps_file name must not be a path, just a ' | 179 raise gclient_utils.Error('deps_file name must not be a path, just a ' |
182 'filename. %s' % self.deps_file) | 180 'filename. %s' % self.deps_file) |
183 | 181 |
184 def ParseDepsFile(self, direct_reference): | 182 def _ParseSolutionDeps(self, solution_name, solution_deps_content, |
185 """Parses the DEPS file for this dependency.""" | 183 custom_vars, parse_hooks): |
186 if direct_reference: | 184 """Parses the DEPS file for the specified solution. |
187 # Maybe it was referenced earlier by a From() keyword but it's now | |
188 # directly referenced. | |
189 self.direct_reference = direct_reference | |
190 if self.deps_parsed: | |
191 return | |
192 self.deps_parsed = True | |
193 filepath = os.path.join(self.root_dir(), self.name, self.deps_file) | |
194 if not os.path.isfile(filepath): | |
195 return | |
196 deps_content = gclient_utils.FileRead(filepath) | |
197 | 185 |
198 # Eval the content. | 186 Args: |
199 # One thing is unintuitive, vars= {} must happen before Var() use. | 187 solution_name: The name of the solution to query. |
188 solution_deps_content: Content of the DEPS file for the solution | |
189 custom_vars: A dict of vars to override any vars defined in the DEPS file. | |
bradn
2010/06/22 04:51:00
Missing some args here.
M-A Ruel
2010/06/22 14:29:11
Well, the goal is to delete this code if I can sto
| |
190 | |
191 Returns: | |
192 A dict mapping module names (as relative paths) to URLs or an empty | |
193 dict if the solution does not have a DEPS file. | |
194 """ | |
195 # Skip empty | |
196 if not solution_deps_content: | |
197 return {} | |
198 # Eval the content | |
200 local_scope = {} | 199 local_scope = {} |
201 var = self.VarImpl(self.custom_vars, local_scope) | 200 var = self.VarImpl(custom_vars, local_scope) |
202 global_scope = { | 201 global_scope = { |
203 'File': self.FileImpl, | 202 "File": self.FileImpl, |
204 'From': self.FromImpl, | 203 "From": self.FromImpl, |
205 'Var': var.Lookup, | 204 "Var": var.Lookup, |
206 'deps_os': {}, | 205 "deps_os": {}, |
207 } | 206 } |
208 exec(deps_content, global_scope, local_scope) | 207 exec(solution_deps_content, global_scope, local_scope) |
209 deps = local_scope.get('deps', {}) | 208 deps = local_scope.get("deps", {}) |
209 | |
210 # load os specific dependencies if defined. these dependencies may | 210 # load os specific dependencies if defined. these dependencies may |
211 # override or extend the values defined by the 'deps' member. | 211 # override or extend the values defined by the 'deps' member. |
212 if 'deps_os' in local_scope: | 212 if "deps_os" in local_scope: |
213 for deps_os_key in self.enforced_os(): | 213 if self._options.deps_os is not None: |
214 os_deps = local_scope['deps_os'].get(deps_os_key, {}) | 214 deps_to_include = self._options.deps_os.split(",") |
215 if len(self.enforced_os()) > 1: | 215 if "all" in deps_to_include: |
216 # Ignore any conflict when including deps for more than one | 216 deps_to_include = list(set(self.DEPS_OS_CHOICES.itervalues())) |
217 else: | |
218 deps_to_include = [self.DEPS_OS_CHOICES.get(sys.platform, "unix")] | |
219 | |
220 deps_to_include = set(deps_to_include) | |
221 for deps_os_key in deps_to_include: | |
222 os_deps = local_scope["deps_os"].get(deps_os_key, {}) | |
223 if len(deps_to_include) > 1: | |
224 # Ignore any overrides when including deps for more than one | |
217 # platform, so we collect the broadest set of dependencies available. | 225 # platform, so we collect the broadest set of dependencies available. |
218 # We may end up with the wrong revision of something for our | 226 # We may end up with the wrong revision of something for our |
219 # platform, but this is the best we can do. | 227 # platform, but this is the best we can do. |
220 deps.update([x for x in os_deps.items() if not x[0] in deps]) | 228 deps.update([x for x in os_deps.items() if not x[0] in deps]) |
221 else: | 229 else: |
222 deps.update(os_deps) | 230 deps.update(os_deps) |
223 | 231 |
224 self.deps_hooks.extend(local_scope.get('hooks', [])) | 232 if 'hooks' in local_scope and parse_hooks: |
225 | 233 # TODO(maruel): Temporary Hack. Since this function is misplaced, find the |
226 # If a line is in custom_deps, but not in the solution, we want to append | 234 # right 'self' to add the hooks. |
227 # this line to the solution. | 235 for d in self.dependencies: |
228 for d in self.custom_deps: | 236 if d.name == solution_name: |
229 if d not in deps: | 237 d.deps_hooks.extend(local_scope['hooks']) |
230 deps[d] = self.custom_deps[d] | 238 break |
231 | 239 |
232 # If use_relative_paths is set in the DEPS file, regenerate | 240 # If use_relative_paths is set in the DEPS file, regenerate |
233 # the dictionary using paths relative to the directory containing | 241 # the dictionary using paths relative to the directory containing |
234 # the DEPS file. | 242 # the DEPS file. |
235 use_relative_paths = local_scope.get('use_relative_paths', False) | 243 if local_scope.get('use_relative_paths'): |
236 if use_relative_paths: | |
237 rel_deps = {} | 244 rel_deps = {} |
238 for d, url in deps.items(): | 245 for d, url in deps.items(): |
239 # normpath is required to allow DEPS to use .. in their | 246 # normpath is required to allow DEPS to use .. in their |
240 # dependency local path. | 247 # dependency local path. |
241 rel_deps[os.path.normpath(os.path.join(self.name, d))] = url | 248 rel_deps[os.path.normpath(os.path.join(solution_name, d))] = url |
242 deps = rel_deps | 249 return rel_deps |
243 # TODO(maruel): Add these dependencies into self.dependencies. | 250 else: |
244 return deps | 251 return deps |
245 | 252 |
246 def _ParseAllDeps(self, solution_urls): | 253 def _ParseAllDeps(self, solution_urls, solution_deps_content): |
247 """Parse the complete list of dependencies for the client. | 254 """Parse the complete list of dependencies for the client. |
248 | 255 |
249 Args: | 256 Args: |
250 solution_urls: A dict mapping module names (as relative paths) to URLs | 257 solution_urls: A dict mapping module names (as relative paths) to URLs |
251 corresponding to the solutions specified by the client. This parameter | 258 corresponding to the solutions specified by the client. This parameter |
252 is passed as an optimization. | 259 is passed as an optimization. |
260 solution_deps_content: A dict mapping module names to the content | |
261 of their DEPS files | |
253 | 262 |
254 Returns: | 263 Returns: |
255 A dict mapping module names (as relative paths) to URLs corresponding | 264 A dict mapping module names (as relative paths) to URLs corresponding |
256 to the entire set of dependencies to checkout for the given client. | 265 to the entire set of dependencies to checkout for the given client. |
257 | 266 |
258 Raises: | 267 Raises: |
259 Error: If a dependency conflicts with another dependency or of a solution. | 268 Error: If a dependency conflicts with another dependency or of a solution. |
260 """ | 269 """ |
261 deps = {} | 270 deps = {} |
262 for solution in self.dependencies: | 271 for solution in self.dependencies: |
263 solution_deps = solution.ParseDepsFile(True) | 272 solution_deps = self._ParseSolutionDeps( |
273 solution.name, | |
274 solution_deps_content[solution.name], | |
275 solution.custom_vars, | |
276 True) | |
264 | 277 |
265 # If a line is in custom_deps, but not in the solution, we want to append | 278 # If a line is in custom_deps, but not in the solution, we want to append |
266 # this line to the solution. | 279 # this line to the solution. |
267 for d in solution.custom_deps: | 280 for d in solution.custom_deps: |
268 if d not in solution_deps: | 281 if d not in solution_deps: |
269 solution_deps[d] = solution.custom_deps[d] | 282 solution_deps[d] = solution.custom_deps[d] |
270 | 283 |
271 for d in solution_deps: | 284 for d in solution_deps: |
272 if d in solution.custom_deps: | 285 if d in solution.custom_deps: |
273 # Dependency is overriden. | 286 # Dependency is overriden. |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
359 return | 372 return |
360 | 373 |
361 # Run hooks on the basis of whether the files from the gclient operation | 374 # Run hooks on the basis of whether the files from the gclient operation |
362 # match each hook's pattern. | 375 # match each hook's pattern. |
363 for hook_dict in hooks: | 376 for hook_dict in hooks: |
364 pattern = re.compile(hook_dict['pattern']) | 377 pattern = re.compile(hook_dict['pattern']) |
365 matching_file_list = [f for f in file_list if pattern.search(f)] | 378 matching_file_list = [f for f in file_list if pattern.search(f)] |
366 if matching_file_list: | 379 if matching_file_list: |
367 self._RunHookAction(hook_dict, matching_file_list) | 380 self._RunHookAction(hook_dict, matching_file_list) |
368 | 381 |
369 def root_dir(self): | |
370 return self.parent.root_dir() | |
371 | |
372 def enforced_os(self): | |
373 return self.parent.enforced_os() | |
374 | |
375 | 382 |
376 class GClient(Dependency): | 383 class GClient(Dependency): |
377 """Main gclient checkout root where .gclient resides.""" | 384 """Main gclient checkout root where .gclient resides.""" |
378 SUPPORTED_COMMANDS = [ | 385 SUPPORTED_COMMANDS = [ |
379 'cleanup', 'diff', 'export', 'pack', 'revert', 'status', 'update', | 386 'cleanup', 'diff', 'export', 'pack', 'revert', 'status', 'update', |
380 'runhooks' | 387 'runhooks' |
381 ] | 388 ] |
382 | 389 |
383 DEPS_OS_CHOICES = { | 390 DEPS_OS_CHOICES = { |
384 "win32": "win", | 391 "win32": "win", |
(...skipping 29 matching lines...) Expand all Loading... | |
414 | 421 |
415 DEFAULT_SNAPSHOT_FILE_TEXT = ("""\ | 422 DEFAULT_SNAPSHOT_FILE_TEXT = ("""\ |
416 # Snapshot generated with gclient revinfo --snapshot | 423 # Snapshot generated with gclient revinfo --snapshot |
417 solutions = [ | 424 solutions = [ |
418 %(solution_list)s | 425 %(solution_list)s |
419 ] | 426 ] |
420 """) | 427 """) |
421 | 428 |
422 def __init__(self, root_dir, options): | 429 def __init__(self, root_dir, options): |
423 Dependency.__init__(self, None, None, None) | 430 Dependency.__init__(self, None, None, None) |
431 self._root_dir = root_dir | |
424 self._options = options | 432 self._options = options |
425 if options.deps_os: | |
426 enforced_os = options.deps_os.split(',') | |
427 else: | |
428 enforced_os = [self.DEPS_OS_CHOICES.get(sys.platform, 'unix')] | |
429 if 'all' in enforced_os: | |
430 enforced_os = self.DEPS_OS_CHOICES.itervalues() | |
431 self._enforced_os = list(set(enforced_os)) | |
432 self._root_dir = root_dir | |
433 self.config_content = None | 433 self.config_content = None |
434 | 434 |
435 def SetConfig(self, content): | 435 def SetConfig(self, content): |
436 assert self.dependencies == [] | 436 assert self.dependencies == [] |
437 config_dict = {} | 437 config_dict = {} |
438 self.config_content = content | 438 self.config_content = content |
439 try: | 439 try: |
440 exec(content, config_dict) | 440 exec(content, config_dict) |
441 except SyntaxError, e: | 441 except SyntaxError, e: |
442 try: | 442 try: |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
560 if not self.dependencies: | 560 if not self.dependencies: |
561 raise gclient_utils.Error("No solution specified") | 561 raise gclient_utils.Error("No solution specified") |
562 revision_overrides = self._EnforceRevisions() | 562 revision_overrides = self._EnforceRevisions() |
563 | 563 |
564 # When running runhooks --force, there's no need to consult the SCM. | 564 # When running runhooks --force, there's no need to consult the SCM. |
565 # All known hooks are expected to run unconditionally regardless of working | 565 # All known hooks are expected to run unconditionally regardless of working |
566 # copy state, so skip the SCM status check. | 566 # copy state, so skip the SCM status check. |
567 run_scm = not (command == 'runhooks' and self._options.force) | 567 run_scm = not (command == 'runhooks' and self._options.force) |
568 | 568 |
569 entries = {} | 569 entries = {} |
570 entries_deps_content = {} | |
570 file_list = [] | 571 file_list = [] |
571 # Run on the base solutions first. | 572 # Run on the base solutions first. |
572 for solution in self.dependencies: | 573 for solution in self.dependencies: |
573 name = solution.name | 574 name = solution.name |
574 if name in entries: | 575 if name in entries: |
575 raise gclient_utils.Error("solution %s specified more than once" % name) | 576 raise gclient_utils.Error("solution %s specified more than once" % name) |
576 url = solution.url | 577 url = solution.url |
577 entries[name] = url | 578 entries[name] = url |
578 if run_scm and url: | 579 if run_scm and url: |
579 self._options.revision = revision_overrides.get(name) | 580 self._options.revision = revision_overrides.get(name) |
580 scm = gclient_scm.CreateSCM(url, self.root_dir(), name) | 581 scm = gclient_scm.CreateSCM(url, self.root_dir(), name) |
581 scm.RunCommand(command, self._options, args, file_list) | 582 scm.RunCommand(command, self._options, args, file_list) |
582 file_list = [os.path.join(name, f.strip()) for f in file_list] | 583 file_list = [os.path.join(name, f.strip()) for f in file_list] |
583 self._options.revision = None | 584 self._options.revision = None |
585 try: | |
586 deps_content = gclient_utils.FileRead( | |
587 os.path.join(self.root_dir(), name, solution.deps_file)) | |
588 except IOError, e: | |
589 if e.errno != errno.ENOENT: | |
590 raise | |
591 deps_content = "" | |
592 entries_deps_content[name] = deps_content | |
584 | 593 |
585 # Process the dependencies next (sort alphanumerically to ensure that | 594 # Process the dependencies next (sort alphanumerically to ensure that |
586 # containing directories get populated first and for readability) | 595 # containing directories get populated first and for readability) |
587 deps = self._ParseAllDeps(entries) | 596 deps = self._ParseAllDeps(entries, entries_deps_content) |
588 deps_to_process = deps.keys() | 597 deps_to_process = deps.keys() |
589 deps_to_process.sort() | 598 deps_to_process.sort() |
590 | 599 |
591 # First pass for direct dependencies. | 600 # First pass for direct dependencies. |
592 if command == 'update' and not self._options.verbose: | 601 if command == 'update' and not self._options.verbose: |
593 pm = Progress('Syncing projects', len(deps_to_process)) | 602 pm = Progress('Syncing projects', len(deps_to_process)) |
594 for d in deps_to_process: | 603 for d in deps_to_process: |
595 if command == 'update' and not self._options.verbose: | 604 if command == 'update' and not self._options.verbose: |
596 pm.update() | 605 pm.update() |
597 if type(deps[d]) == str: | 606 if type(deps[d]) == str: |
(...skipping 11 matching lines...) Expand all Loading... | |
609 scm = gclient_scm.CreateSCM(file_dep.GetPath(), self.root_dir(), d) | 618 scm = gclient_scm.CreateSCM(file_dep.GetPath(), self.root_dir(), d) |
610 scm.RunCommand("updatesingle", self._options, | 619 scm.RunCommand("updatesingle", self._options, |
611 args + [file_dep.GetFilename()], file_list) | 620 args + [file_dep.GetFilename()], file_list) |
612 | 621 |
613 if command == 'update' and not self._options.verbose: | 622 if command == 'update' and not self._options.verbose: |
614 pm.end() | 623 pm.end() |
615 | 624 |
616 # Second pass for inherited deps (via the From keyword) | 625 # Second pass for inherited deps (via the From keyword) |
617 for d in deps_to_process: | 626 for d in deps_to_process: |
618 if isinstance(deps[d], self.FromImpl): | 627 if isinstance(deps[d], self.FromImpl): |
628 filename = os.path.join(self.root_dir(), | |
629 deps[d].module_name, | |
630 self.DEPS_FILE) | |
631 content = gclient_utils.FileRead(filename) | |
632 sub_deps = self._ParseSolutionDeps(deps[d].module_name, content, {}, | |
633 False) | |
619 # Getting the URL from the sub_deps file can involve having to resolve | 634 # Getting the URL from the sub_deps file can involve having to resolve |
620 # a File() or having to resolve a relative URL. To resolve relative | 635 # a File() or having to resolve a relative URL. To resolve relative |
621 # URLs, we need to pass in the orignal sub deps URL. | 636 # URLs, we need to pass in the orignal sub deps URL. |
622 sub_deps_base_url = deps[deps[d].module_name] | 637 sub_deps_base_url = deps[deps[d].module_name] |
623 sub_deps = Dependency(self, deps[d].module_name, sub_deps_base_url | |
624 ).ParseDepsFile(False) | |
625 url = deps[d].GetUrl(d, sub_deps_base_url, self.root_dir(), sub_deps) | 638 url = deps[d].GetUrl(d, sub_deps_base_url, self.root_dir(), sub_deps) |
626 entries[d] = url | 639 entries[d] = url |
627 if run_scm: | 640 if run_scm: |
628 self._options.revision = revision_overrides.get(d) | 641 self._options.revision = revision_overrides.get(d) |
629 scm = gclient_scm.CreateSCM(url, self.root_dir(), d) | 642 scm = gclient_scm.CreateSCM(url, self.root_dir(), d) |
630 scm.RunCommand(command, self._options, args, file_list) | 643 scm.RunCommand(command, self._options, args, file_list) |
631 self._options.revision = None | 644 self._options.revision = None |
632 | 645 |
633 # Convert all absolute paths to relative. | 646 # Convert all absolute paths to relative. |
634 for i in range(len(file_list)): | 647 for i in range(len(file_list)): |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
702 def GetURLAndRev(name, original_url): | 715 def GetURLAndRev(name, original_url): |
703 url, _ = gclient_utils.SplitUrlRevision(original_url) | 716 url, _ = gclient_utils.SplitUrlRevision(original_url) |
704 scm = gclient_scm.CreateSCM(original_url, self.root_dir(), name) | 717 scm = gclient_scm.CreateSCM(original_url, self.root_dir(), name) |
705 return (url, scm.revinfo(self._options, [], None)) | 718 return (url, scm.revinfo(self._options, [], None)) |
706 | 719 |
707 # text of the snapshot gclient file | 720 # text of the snapshot gclient file |
708 new_gclient = "" | 721 new_gclient = "" |
709 # Dictionary of { path : SCM url } to ensure no duplicate solutions | 722 # Dictionary of { path : SCM url } to ensure no duplicate solutions |
710 solution_names = {} | 723 solution_names = {} |
711 entries = {} | 724 entries = {} |
725 entries_deps_content = {} | |
712 # Run on the base solutions first. | 726 # Run on the base solutions first. |
713 for solution in self.dependencies: | 727 for solution in self.dependencies: |
714 # Dictionary of { path : SCM url } to describe the gclient checkout | 728 # Dictionary of { path : SCM url } to describe the gclient checkout |
715 name = solution.name | 729 name = solution.name |
716 if name in solution_names: | 730 if name in solution_names: |
717 raise gclient_utils.Error("solution %s specified more than once" % name) | 731 raise gclient_utils.Error("solution %s specified more than once" % name) |
718 (url, rev) = GetURLAndRev(name, solution.url) | 732 (url, rev) = GetURLAndRev(name, solution.url) |
719 entries[name] = "%s@%s" % (url, rev) | 733 entries[name] = "%s@%s" % (url, rev) |
720 solution_names[name] = "%s@%s" % (url, rev) | 734 solution_names[name] = "%s@%s" % (url, rev) |
735 deps_file = solution.deps_file | |
736 if '/' in deps_file or '\\' in deps_file: | |
737 raise gclient_utils.Error('deps_file name must not be a path, just a ' | |
738 'filename.') | |
739 try: | |
740 deps_content = gclient_utils.FileRead( | |
741 os.path.join(self.root_dir(), name, deps_file)) | |
742 except IOError, e: | |
743 if e.errno != errno.ENOENT: | |
744 raise | |
745 deps_content = "" | |
746 entries_deps_content[name] = deps_content | |
721 | 747 |
722 # Process the dependencies next (sort alphanumerically to ensure that | 748 # Process the dependencies next (sort alphanumerically to ensure that |
723 # containing directories get populated first and for readability) | 749 # containing directories get populated first and for readability) |
724 deps = self._ParseAllDeps(entries) | 750 deps = self._ParseAllDeps(entries, entries_deps_content) |
725 deps_to_process = deps.keys() | 751 deps_to_process = deps.keys() |
726 deps_to_process.sort() | 752 deps_to_process.sort() |
727 | 753 |
728 # First pass for direct dependencies. | 754 # First pass for direct dependencies. |
729 for d in deps_to_process: | 755 for d in deps_to_process: |
730 if type(deps[d]) == str: | 756 if type(deps[d]) == str: |
731 (url, rev) = GetURLAndRev(d, deps[d]) | 757 (url, rev) = GetURLAndRev(d, deps[d]) |
732 entries[d] = "%s@%s" % (url, rev) | 758 entries[d] = "%s@%s" % (url, rev) |
733 | 759 |
734 # Second pass for inherited deps (via the From keyword) | 760 # Second pass for inherited deps (via the From keyword) |
735 for d in deps_to_process: | 761 for d in deps_to_process: |
736 if isinstance(deps[d], self.FromImpl): | 762 if isinstance(deps[d], self.FromImpl): |
737 deps_parent_url = entries[deps[d].module_name] | 763 deps_parent_url = entries[deps[d].module_name] |
738 if deps_parent_url.find("@") < 0: | 764 if deps_parent_url.find("@") < 0: |
739 raise gclient_utils.Error("From %s missing revisioned url" % | 765 raise gclient_utils.Error("From %s missing revisioned url" % |
740 deps[d].module_name) | 766 deps[d].module_name) |
741 sub_deps_base_url = deps[deps[d].module_name] | 767 content = gclient_utils.FileRead(os.path.join( |
742 sub_deps = Dependency(self, deps[d].module_name, sub_deps_base_url | 768 self.root_dir(), |
743 ).ParseDepsFile(False) | 769 deps[d].module_name, |
744 url = deps[d].GetUrl(d, sub_deps_base_url, self.root_dir(), sub_deps) | 770 self.DEPS_FILE)) |
745 (url, rev) = GetURLAndRev(d, url) | 771 sub_deps = self._ParseSolutionDeps(deps[d].module_name, content, {}, |
772 False) | |
773 (url, rev) = GetURLAndRev(d, sub_deps[d]) | |
746 entries[d] = "%s@%s" % (url, rev) | 774 entries[d] = "%s@%s" % (url, rev) |
747 | 775 |
748 # Build the snapshot configuration string | 776 # Build the snapshot configuration string |
749 if self._options.snapshot: | 777 if self._options.snapshot: |
750 url = entries.pop(name) | 778 url = entries.pop(name) |
751 custom_deps = ",\n ".join(["\"%s\": \"%s\"" % (x, entries[x]) | 779 custom_deps = ",\n ".join(["\"%s\": \"%s\"" % (x, entries[x]) |
752 for x in sorted(entries.keys())]) | 780 for x in sorted(entries.keys())]) |
753 | 781 |
754 new_gclient += self.DEFAULT_SNAPSHOT_SOLUTION_TEXT % { | 782 new_gclient += self.DEFAULT_SNAPSHOT_SOLUTION_TEXT % { |
755 'solution_name': name, | 783 'solution_name': name, |
756 'solution_url': url, | 784 'solution_url': url, |
757 'safesync_url' : "", | 785 'safesync_url' : "", |
758 'solution_deps': custom_deps, | 786 'solution_deps': custom_deps, |
759 } | 787 } |
760 else: | 788 else: |
761 print(";\n".join(["%s: %s" % (x, entries[x]) | 789 print(";\n".join(["%s: %s" % (x, entries[x]) |
762 for x in sorted(entries.keys())])) | 790 for x in sorted(entries.keys())])) |
763 | 791 |
764 # Print the snapshot configuration file | 792 # Print the snapshot configuration file |
765 if self._options.snapshot: | 793 if self._options.snapshot: |
766 config = self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient} | 794 config = self.DEFAULT_SNAPSHOT_FILE_TEXT % {'solution_list': new_gclient} |
767 snapclient = GClient(self.root_dir(), self._options) | 795 snapclient = GClient(self.root_dir(), self._options) |
768 snapclient.SetConfig(config) | 796 snapclient.SetConfig(config) |
769 print(snapclient.config_content) | 797 print(snapclient.config_content) |
770 | 798 |
771 def root_dir(self): | 799 def root_dir(self): |
772 return self._root_dir | 800 return self._root_dir |
773 | 801 |
774 def enforced_os(self): | |
775 return self._enforced_os | |
776 | |
777 | 802 |
778 #### gclient commands. | 803 #### gclient commands. |
779 | 804 |
780 | 805 |
781 def CMDcleanup(parser, args): | 806 def CMDcleanup(parser, args): |
782 """Cleans up all working copies. | 807 """Cleans up all working copies. |
783 | 808 |
784 Mostly svn-specific. Simply runs 'svn cleanup' for each module. | 809 Mostly svn-specific. Simply runs 'svn cleanup' for each module. |
785 """ | 810 """ |
786 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', | 811 parser.add_option('--deps', dest='deps_os', metavar='OS_LIST', |
(...skipping 333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1120 return CMDhelp(parser, argv) | 1145 return CMDhelp(parser, argv) |
1121 except gclient_utils.Error, e: | 1146 except gclient_utils.Error, e: |
1122 print >> sys.stderr, 'Error: %s' % str(e) | 1147 print >> sys.stderr, 'Error: %s' % str(e) |
1123 return 1 | 1148 return 1 |
1124 | 1149 |
1125 | 1150 |
1126 if '__main__' == __name__: | 1151 if '__main__' == __name__: |
1127 sys.exit(Main(sys.argv[1:])) | 1152 sys.exit(Main(sys.argv[1:])) |
1128 | 1153 |
1129 # vim: ts=2:sw=2:tw=80:et: | 1154 # vim: ts=2:sw=2:tw=80:et: |
OLD | NEW |