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