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

Side by Side Diff: gclient.py

Issue 2837001: Make each solution dictionary an object. (Closed)
Patch Set: Include a fix in GetScmName() Created 10 years, 6 months 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 | « no previous file | 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 # 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 """A wrapper script to manage a set of client modules in different SCM. 6 """A wrapper script to manage a set of client modules in different SCM.
7 7
8 This script is intended to be used to help basic management of client 8 This script is intended to be used to help basic management of client
9 program sources residing in one or more Subversion modules and Git 9 program sources residing in one or more Subversion modules and Git
10 repositories, along with other modules it depends on, also in Subversion or Git, 10 repositories, along with other modules it depends on, also in Subversion or Git,
(...skipping 137 matching lines...) Expand 10 before | Expand all | Expand 10 after
148 148
149 def Lookup(self, var_name): 149 def Lookup(self, var_name):
150 """Implements the Var syntax.""" 150 """Implements the Var syntax."""
151 if var_name in self._custom_vars: 151 if var_name in self._custom_vars:
152 return self._custom_vars[var_name] 152 return self._custom_vars[var_name]
153 elif var_name in self._local_scope.get("vars", {}): 153 elif var_name in self._local_scope.get("vars", {}):
154 return self._local_scope["vars"][var_name] 154 return self._local_scope["vars"][var_name]
155 raise gclient_utils.Error("Var is not defined: %s" % var_name) 155 raise gclient_utils.Error("Var is not defined: %s" % var_name)
156 156
157 157
158 class GClient(GClientKeywords): 158 class Dependency(GClientKeywords):
159 """Object that represent a gclient checkout.""" 159 """Object that represents a dependency checkout."""
160 DEPS_FILE = 'DEPS' 160 DEPS_FILE = 'DEPS'
161 def __init__(self, parent, name, url, safesync_url=None, custom_deps=None,
162 custom_vars=None, deps_file=None):
163 GClientKeywords.__init__(self)
164 self.parent = parent
165 self.name = name
166 self.url = url
167 # These 2 are only set in .gclient and not in DEPS files.
168 self.safesync_url = safesync_url
169 self.custom_vars = custom_vars or {}
170 self.custom_deps = custom_deps or {}
171 self.dependencies = []
172 self.deps_file = deps_file or self.DEPS_FILE
173 self._deps_hooks = []
161 174
175 # Sanity checks
176 if not self.name and self.parent:
177 raise gclient_utils.Error('Dependency without name')
178 if not isinstance(self.url,
179 (basestring, self.FromImpl, self.FileImpl, None.__class__)):
180 raise gclient_utils.Error('dependency url must be either a string, None, '
181 'File() or From() instead of %s' %
182 self.url.__class__.__name__)
183 if '/' in self.deps_file or '\\' in self.deps_file:
184 raise gclient_utils.Error('deps_file name must not be a path, just a '
185 'filename. %s' % self.deps_file)
186
187
188 class GClient(Dependency):
189 """Main gclient checkout root where .gclient resides."""
162 SUPPORTED_COMMANDS = [ 190 SUPPORTED_COMMANDS = [
163 'cleanup', 'diff', 'export', 'pack', 'revert', 'status', 'update', 191 'cleanup', 'diff', 'export', 'pack', 'revert', 'status', 'update',
164 'runhooks' 192 'runhooks'
165 ] 193 ]
166 194
167 DEPS_OS_CHOICES = { 195 DEPS_OS_CHOICES = {
168 "win32": "win", 196 "win32": "win",
169 "win": "win", 197 "win": "win",
170 "cygwin": "win", 198 "cygwin": "win",
171 "darwin": "mac", 199 "darwin": "mac",
(...skipping 25 matching lines...) Expand all
197 """) 225 """)
198 226
199 DEFAULT_SNAPSHOT_FILE_TEXT = ("""\ 227 DEFAULT_SNAPSHOT_FILE_TEXT = ("""\
200 # Snapshot generated with gclient revinfo --snapshot 228 # Snapshot generated with gclient revinfo --snapshot
201 solutions = [ 229 solutions = [
202 %(solution_list)s 230 %(solution_list)s
203 ] 231 ]
204 """) 232 """)
205 233
206 def __init__(self, root_dir, options): 234 def __init__(self, root_dir, options):
235 Dependency.__init__(self, None, None, None)
207 self._root_dir = root_dir 236 self._root_dir = root_dir
208 self._options = options 237 self._options = options
209 self.config_content = None 238 self.config_content = None
210 self._config_dict = {}
211 self._deps_hooks = []
212 239
213 def SetConfig(self, content): 240 def SetConfig(self, content):
214 self._config_dict = {} 241 config_dict = {}
215 self.config_content = content 242 self.config_content = content
216 try: 243 try:
217 exec(content, self._config_dict) 244 exec(content, config_dict)
218 except SyntaxError, e: 245 except SyntaxError, e:
219 try: 246 try:
220 # Try to construct a human readable error message 247 # Try to construct a human readable error message
221 error_message = [ 248 error_message = [
222 'There is a syntax error in your configuration file.', 249 'There is a syntax error in your configuration file.',
223 'Line #%s, character %s:' % (e.lineno, e.offset), 250 'Line #%s, character %s:' % (e.lineno, e.offset),
224 '"%s"' % re.sub(r'[\r\n]*$', '', e.text) ] 251 '"%s"' % re.sub(r'[\r\n]*$', '', e.text) ]
225 except: 252 except:
226 # Something went wrong, re-raise the original exception 253 # Something went wrong, re-raise the original exception
227 raise e 254 raise e
228 else: 255 else:
229 # Raise a new exception with the human readable message: 256 # Raise a new exception with the human readable message:
230 raise gclient_utils.Error('\n'.join(error_message)) 257 raise gclient_utils.Error('\n'.join(error_message))
258 for s in config_dict.get('solutions', []):
259 self.dependencies.append(Dependency(
260 self, s['name'], s['url'],
261 s.get('safesync_url', None),
262 s.get('custom_deps', {}),
263 s.get('custom_vars', {})))
264 # .gclient can have hooks.
265 self._deps_hooks = config_dict.get('hooks', [])
231 266
232 def SaveConfig(self): 267 def SaveConfig(self):
233 gclient_utils.FileWrite(os.path.join(self.root_dir(), 268 gclient_utils.FileWrite(os.path.join(self.root_dir(),
234 self._options.config_filename), 269 self._options.config_filename),
235 self.config_content) 270 self.config_content)
236 271
237 def _LoadConfig(self): 272 def _LoadConfig(self):
238 client_source = gclient_utils.FileRead( 273 client_source = gclient_utils.FileRead(
239 os.path.join(self.root_dir(), self._options.config_filename)) 274 os.path.join(self.root_dir(), self._options.config_filename))
240 self.SetConfig(client_source) 275 self.SetConfig(client_source)
241 276
242 def GetVar(self, key, default=None):
243 return self._config_dict.get(key, default)
244
245 @staticmethod 277 @staticmethod
246 def LoadCurrentConfig(options, from_dir=None): 278 def LoadCurrentConfig(options, from_dir=None):
247 """Searches for and loads a .gclient file relative to the current working 279 """Searches for and loads a .gclient file relative to the current working
248 dir. 280 dir.
249 281
250 Returns: 282 Returns:
251 A dict representing the contents of the .gclient file or an empty dict if 283 A dict representing the contents of the .gclient file or an empty dict if
252 the .gclient file doesn't exist. 284 the .gclient file doesn't exist.
253 """ 285 """
254 if not from_dir: 286 if not from_dir:
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
348 if len(deps_to_include) > 1: 380 if len(deps_to_include) > 1:
349 # Ignore any overrides when including deps for more than one 381 # Ignore any overrides when including deps for more than one
350 # platform, so we collect the broadest set of dependencies available. 382 # platform, so we collect the broadest set of dependencies available.
351 # We may end up with the wrong revision of something for our 383 # We may end up with the wrong revision of something for our
352 # platform, but this is the best we can do. 384 # platform, but this is the best we can do.
353 deps.update([x for x in os_deps.items() if not x[0] in deps]) 385 deps.update([x for x in os_deps.items() if not x[0] in deps])
354 else: 386 else:
355 deps.update(os_deps) 387 deps.update(os_deps)
356 388
357 if 'hooks' in local_scope and parse_hooks: 389 if 'hooks' in local_scope and parse_hooks:
358 self._deps_hooks.extend(local_scope['hooks']) 390 # TODO(maruel): Temporary Hack. Since this function is misplaced, find the
391 # right 'self' to add the hooks.
392 for d in self.dependencies:
393 if d.name == solution_name:
394 d._deps_hooks.extend(local_scope['hooks'])
395 break
359 396
360 # If use_relative_paths is set in the DEPS file, regenerate 397 # If use_relative_paths is set in the DEPS file, regenerate
361 # the dictionary using paths relative to the directory containing 398 # the dictionary using paths relative to the directory containing
362 # the DEPS file. 399 # the DEPS file.
363 if local_scope.get('use_relative_paths'): 400 if local_scope.get('use_relative_paths'):
364 rel_deps = {} 401 rel_deps = {}
365 for d, url in deps.items(): 402 for d, url in deps.items():
366 # normpath is required to allow DEPS to use .. in their 403 # normpath is required to allow DEPS to use .. in their
367 # dependency local path. 404 # dependency local path.
368 rel_deps[os.path.normpath(os.path.join(solution_name, d))] = url 405 rel_deps[os.path.normpath(os.path.join(solution_name, d))] = url
(...skipping 12 matching lines...) Expand all
381 of their DEPS files 418 of their DEPS files
382 419
383 Returns: 420 Returns:
384 A dict mapping module names (as relative paths) to URLs corresponding 421 A dict mapping module names (as relative paths) to URLs corresponding
385 to the entire set of dependencies to checkout for the given client. 422 to the entire set of dependencies to checkout for the given client.
386 423
387 Raises: 424 Raises:
388 Error: If a dependency conflicts with another dependency or of a solution. 425 Error: If a dependency conflicts with another dependency or of a solution.
389 """ 426 """
390 deps = {} 427 deps = {}
391 for solution in self.GetVar("solutions"): 428 for solution in self.dependencies:
392 custom_vars = solution.get("custom_vars", {})
393 solution_deps = self._ParseSolutionDeps( 429 solution_deps = self._ParseSolutionDeps(
394 solution["name"], 430 solution.name,
395 solution_deps_content[solution["name"]], 431 solution_deps_content[solution.name],
396 custom_vars, 432 solution.custom_vars,
397 True) 433 True)
398 434
399 # If a line is in custom_deps, but not in the solution, we want to append 435 # If a line is in custom_deps, but not in the solution, we want to append
400 # this line to the solution. 436 # this line to the solution.
401 if "custom_deps" in solution: 437 for d in solution.custom_deps:
402 for d in solution["custom_deps"]: 438 if d not in solution_deps:
403 if d not in solution_deps: 439 solution_deps[d] = solution.custom_deps[d]
404 solution_deps[d] = solution["custom_deps"][d]
405 440
406 for d in solution_deps: 441 for d in solution_deps:
407 if "custom_deps" in solution and d in solution["custom_deps"]: 442 if d in solution.custom_deps:
408 # Dependency is overriden. 443 # Dependency is overriden.
409 url = solution["custom_deps"][d] 444 url = solution.custom_deps[d]
410 if url is None: 445 if url is None:
411 continue 446 continue
412 else: 447 else:
413 url = solution_deps[d] 448 url = solution_deps[d]
414 # if we have a From reference dependent on another solution, then 449 # if we have a From reference dependent on another solution, then
415 # just skip the From reference. When we pull deps for the solution, 450 # just skip the From reference. When we pull deps for the solution,
416 # we will take care of this dependency. 451 # we will take care of this dependency.
417 # 452 #
418 # If multiple solutions all have the same From reference, then we 453 # If multiple solutions all have the same From reference, then we
419 # should only add one to our list of dependencies. 454 # should only add one to our list of dependencies.
420 if isinstance(url, self.FromImpl): 455 if isinstance(url, self.FromImpl):
421 if url.module_name in solution_urls: 456 if url.module_name in solution_urls:
422 # Already parsed. 457 # Already parsed.
423 continue 458 continue
424 if d in deps and type(deps[d]) != str: 459 if d in deps and type(deps[d]) != str:
425 if url.module_name == deps[d].module_name: 460 if url.module_name == deps[d].module_name:
426 continue 461 continue
427 elif isinstance(url, str): 462 elif isinstance(url, str):
428 parsed_url = urlparse.urlparse(url) 463 parsed_url = urlparse.urlparse(url)
429 scheme = parsed_url[0] 464 scheme = parsed_url[0]
430 if not scheme: 465 if not scheme:
431 # A relative url. Fetch the real base. 466 # A relative url. Fetch the real base.
432 path = parsed_url[2] 467 path = parsed_url[2]
433 if path[0] != "/": 468 if path[0] != "/":
434 raise gclient_utils.Error( 469 raise gclient_utils.Error(
435 "relative DEPS entry \"%s\" must begin with a slash" % d) 470 "relative DEPS entry \"%s\" must begin with a slash" % d)
436 # Create a scm just to query the full url. 471 # Create a scm just to query the full url.
437 scm = gclient_scm.CreateSCM(solution["url"], self.root_dir(), 472 scm = gclient_scm.CreateSCM(solution.url, self.root_dir(),
438 None) 473 None)
439 url = scm.FullUrlForRelativeUrl(url) 474 url = scm.FullUrlForRelativeUrl(url)
440 if d in deps and deps[d] != url: 475 if d in deps and deps[d] != url:
441 raise gclient_utils.Error( 476 raise gclient_utils.Error(
442 "Solutions have conflicting versions of dependency \"%s\"" % d) 477 "Solutions have conflicting versions of dependency \"%s\"" % d)
443 if d in solution_urls and solution_urls[d] != url: 478 if d in solution_urls and solution_urls[d] != url:
444 raise gclient_utils.Error( 479 raise gclient_utils.Error(
445 "Dependency \"%s\" conflicts with specified solution" % d) 480 "Dependency \"%s\" conflicts with specified solution" % d)
446 # Grab the dependency. 481 # Grab the dependency.
447 deps[d] = url 482 deps[d] = url
448 return deps 483 return deps
(...skipping 24 matching lines...) Expand all
473 """ 508 """
474 # Hooks only run for these command types. 509 # Hooks only run for these command types.
475 if not command in ('update', 'revert', 'runhooks'): 510 if not command in ('update', 'revert', 'runhooks'):
476 return 511 return
477 512
478 # Hooks only run when --nohooks is not specified 513 # Hooks only run when --nohooks is not specified
479 if self._options.nohooks: 514 if self._options.nohooks:
480 return 515 return
481 516
482 # Get any hooks from the .gclient file. 517 # Get any hooks from the .gclient file.
483 hooks = self.GetVar("hooks", []) 518 hooks = self._deps_hooks[:]
484 # Add any hooks found in DEPS files. 519 # Add any hooks found in DEPS files.
485 hooks.extend(self._deps_hooks) 520 for d in self.dependencies:
521 hooks.extend(d._deps_hooks)
486 522
487 # If "--force" was specified, run all hooks regardless of what files have 523 # If "--force" was specified, run all hooks regardless of what files have
488 # changed. If the user is using git, then we don't know what files have 524 # changed. If the user is using git, then we don't know what files have
489 # changed so we always run all hooks. 525 # changed so we always run all hooks.
490 if self._options.force or is_using_git: 526 if self._options.force or is_using_git:
491 for hook_dict in hooks: 527 for hook_dict in hooks:
492 self._RunHookAction(hook_dict, []) 528 self._RunHookAction(hook_dict, [])
493 return 529 return
494 530
495 # Run hooks on the basis of whether the files from the gclient operation 531 # Run hooks on the basis of whether the files from the gclient operation
496 # match each hook's pattern. 532 # match each hook's pattern.
497 for hook_dict in hooks: 533 for hook_dict in hooks:
498 pattern = re.compile(hook_dict['pattern']) 534 pattern = re.compile(hook_dict['pattern'])
499 matching_file_list = [f for f in file_list if pattern.search(f)] 535 matching_file_list = [f for f in file_list if pattern.search(f)]
500 if matching_file_list: 536 if matching_file_list:
501 self._RunHookAction(hook_dict, matching_file_list) 537 self._RunHookAction(hook_dict, matching_file_list)
502 538
503 def _EnforceRevisions(self, solutions): 539 def _EnforceRevisions(self):
504 """Checks for revision overrides.""" 540 """Checks for revision overrides."""
505 revision_overrides = {} 541 revision_overrides = {}
506 if self._options.head: 542 if self._options.head:
507 return revision_overrides 543 return revision_overrides
508 for s in solutions: 544 for s in self.dependencies:
509 if not s.get('safesync_url', None): 545 if not s.safesync_url:
510 continue 546 continue
511 handle = urllib.urlopen(s['safesync_url']) 547 handle = urllib.urlopen(s.safesync_url)
512 rev = handle.read().strip() 548 rev = handle.read().strip()
513 handle.close() 549 handle.close()
514 if len(rev): 550 if len(rev):
515 self._options.revisions.append('%s@%s' % (s['name'], rev)) 551 self._options.revisions.append('%s@%s' % (s.name, rev))
516 if not self._options.revisions: 552 if not self._options.revisions:
517 return revision_overrides 553 return revision_overrides
518 # --revision will take over safesync_url. 554 # --revision will take over safesync_url.
519 solutions_names = [s['name'] for s in solutions] 555 solutions_names = [s.name for s in self.dependencies]
520 index = 0 556 index = 0
521 for revision in self._options.revisions: 557 for revision in self._options.revisions:
522 if not '@' in revision: 558 if not '@' in revision:
523 # Support for --revision 123 559 # Support for --revision 123
524 revision = '%s@%s' % (solutions_names[index], revision) 560 revision = '%s@%s' % (solutions_names[index], revision)
525 sol, rev = revision.split("@", 1) 561 sol, rev = revision.split('@', 1)
526 if not sol in solutions_names: 562 if not sol in solutions_names:
527 #raise gclient_utils.Error('%s is not a valid solution.' % sol) 563 #raise gclient_utils.Error('%s is not a valid solution.' % sol)
528 print >> sys.stderr, ('Please fix your script, having invalid ' 564 print >> sys.stderr, ('Please fix your script, having invalid '
529 '--revision flags will soon considered an error.') 565 '--revision flags will soon considered an error.')
530 else: 566 else:
531 revision_overrides[sol] = rev 567 revision_overrides[sol] = rev
532 index += 1 568 index += 1
533 return revision_overrides 569 return revision_overrides
534 570
535 def RunOnDeps(self, command, args): 571 def RunOnDeps(self, command, args):
536 """Runs a command on each dependency in a client and its dependencies. 572 """Runs a command on each dependency in a client and its dependencies.
537 573
538 The module's dependencies are specified in its top-level DEPS files. 574 The module's dependencies are specified in its top-level DEPS files.
539 575
540 Args: 576 Args:
541 command: The command to use (e.g., 'status' or 'diff') 577 command: The command to use (e.g., 'status' or 'diff')
542 args: list of str - extra arguments to add to the command line. 578 args: list of str - extra arguments to add to the command line.
543 579
544 Raises: 580 Raises:
545 Error: If the client has conflicting entries. 581 Error: If the client has conflicting entries.
546 """ 582 """
547 if not command in self.SUPPORTED_COMMANDS: 583 if not command in self.SUPPORTED_COMMANDS:
548 raise gclient_utils.Error("'%s' is an unsupported command" % command) 584 raise gclient_utils.Error("'%s' is an unsupported command" % command)
549 585
550 solutions = self.GetVar("solutions") 586 if not self.dependencies:
551 if not solutions:
552 raise gclient_utils.Error("No solution specified") 587 raise gclient_utils.Error("No solution specified")
553 revision_overrides = self._EnforceRevisions(solutions) 588 revision_overrides = self._EnforceRevisions()
554 589
555 # When running runhooks --force, there's no need to consult the SCM. 590 # When running runhooks --force, there's no need to consult the SCM.
556 # All known hooks are expected to run unconditionally regardless of working 591 # All known hooks are expected to run unconditionally regardless of working
557 # copy state, so skip the SCM status check. 592 # copy state, so skip the SCM status check.
558 run_scm = not (command == 'runhooks' and self._options.force) 593 run_scm = not (command == 'runhooks' and self._options.force)
559 594
560 entries = {} 595 entries = {}
561 entries_deps_content = {} 596 entries_deps_content = {}
562 file_list = [] 597 file_list = []
563 # Run on the base solutions first. 598 # Run on the base solutions first.
564 for solution in solutions: 599 for solution in self.dependencies:
565 name = solution["name"] 600 name = solution.name
566 deps_file = solution.get("deps_file", self.DEPS_FILE)
567 if '/' in deps_file or '\\' in deps_file:
568 raise gclient_utils.Error('deps_file name must not be a path, just a '
569 'filename.')
570 if name in entries: 601 if name in entries:
571 raise gclient_utils.Error("solution %s specified more than once" % name) 602 raise gclient_utils.Error("solution %s specified more than once" % name)
572 url = solution["url"] 603 url = solution.url
573 entries[name] = url 604 entries[name] = url
574 if run_scm and url: 605 if run_scm and url:
575 self._options.revision = revision_overrides.get(name) 606 self._options.revision = revision_overrides.get(name)
576 scm = gclient_scm.CreateSCM(url, self.root_dir(), name) 607 scm = gclient_scm.CreateSCM(url, self.root_dir(), name)
577 scm.RunCommand(command, self._options, args, file_list) 608 scm.RunCommand(command, self._options, args, file_list)
578 file_list = [os.path.join(name, f.strip()) for f in file_list] 609 file_list = [os.path.join(name, f.strip()) for f in file_list]
579 self._options.revision = None 610 self._options.revision = None
580 try: 611 try:
581 deps_content = gclient_utils.FileRead( 612 deps_content = gclient_utils.FileRead(
582 os.path.join(self.root_dir(), name, deps_file)) 613 os.path.join(self.root_dir(), name, solution.deps_file))
583 except IOError, e: 614 except IOError, e:
584 if e.errno != errno.ENOENT: 615 if e.errno != errno.ENOENT:
585 raise 616 raise
586 deps_content = "" 617 deps_content = ""
587 entries_deps_content[name] = deps_content 618 entries_deps_content[name] = deps_content
588 619
589 # Process the dependencies next (sort alphanumerically to ensure that 620 # Process the dependencies next (sort alphanumerically to ensure that
590 # containing directories get populated first and for readability) 621 # containing directories get populated first and for readability)
591 deps = self._ParseAllDeps(entries, entries_deps_content) 622 deps = self._ParseAllDeps(entries, entries_deps_content)
592 deps_to_process = deps.keys() 623 deps_to_process = deps.keys()
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after
696 """Output revision info mapping for the client and its dependencies. 727 """Output revision info mapping for the client and its dependencies.
697 728
698 This allows the capture of an overall "revision" for the source tree that 729 This allows the capture of an overall "revision" for the source tree that
699 can be used to reproduce the same tree in the future. It is only useful for 730 can be used to reproduce the same tree in the future. It is only useful for
700 "unpinned dependencies", i.e. DEPS/deps references without a svn revision 731 "unpinned dependencies", i.e. DEPS/deps references without a svn revision
701 number or a git hash. A git branch name isn't "pinned" since the actual 732 number or a git hash. A git branch name isn't "pinned" since the actual
702 commit can change. 733 commit can change.
703 734
704 The --snapshot option allows creating a .gclient file to reproduce the tree. 735 The --snapshot option allows creating a .gclient file to reproduce the tree.
705 """ 736 """
706 solutions = self.GetVar("solutions") 737 if not self.dependencies:
707 if not solutions:
708 raise gclient_utils.Error("No solution specified") 738 raise gclient_utils.Error("No solution specified")
709 739
710 # Inner helper to generate base url and rev tuple 740 # Inner helper to generate base url and rev tuple
711 def GetURLAndRev(name, original_url): 741 def GetURLAndRev(name, original_url):
712 url, _ = gclient_utils.SplitUrlRevision(original_url) 742 url, _ = gclient_utils.SplitUrlRevision(original_url)
713 scm = gclient_scm.CreateSCM(original_url, self.root_dir(), name) 743 scm = gclient_scm.CreateSCM(original_url, self.root_dir(), name)
714 return (url, scm.revinfo(self._options, [], None)) 744 return (url, scm.revinfo(self._options, [], None))
715 745
716 # text of the snapshot gclient file 746 # text of the snapshot gclient file
717 new_gclient = "" 747 new_gclient = ""
718 # Dictionary of { path : SCM url } to ensure no duplicate solutions 748 # Dictionary of { path : SCM url } to ensure no duplicate solutions
719 solution_names = {} 749 solution_names = {}
720 entries = {} 750 entries = {}
721 entries_deps_content = {} 751 entries_deps_content = {}
722 # Run on the base solutions first. 752 # Run on the base solutions first.
723 for solution in solutions: 753 for solution in self.dependencies:
724 # Dictionary of { path : SCM url } to describe the gclient checkout 754 # Dictionary of { path : SCM url } to describe the gclient checkout
725 name = solution["name"] 755 name = solution.name
726 if name in solution_names: 756 if name in solution_names:
727 raise gclient_utils.Error("solution %s specified more than once" % name) 757 raise gclient_utils.Error("solution %s specified more than once" % name)
728 (url, rev) = GetURLAndRev(name, solution["url"]) 758 (url, rev) = GetURLAndRev(name, solution.url)
729 entries[name] = "%s@%s" % (url, rev) 759 entries[name] = "%s@%s" % (url, rev)
730 solution_names[name] = "%s@%s" % (url, rev) 760 solution_names[name] = "%s@%s" % (url, rev)
731 deps_file = solution.get("deps_file", self.DEPS_FILE) 761 deps_file = solution.deps_file
732 if '/' in deps_file or '\\' in deps_file: 762 if '/' in deps_file or '\\' in deps_file:
733 raise gclient_utils.Error('deps_file name must not be a path, just a ' 763 raise gclient_utils.Error('deps_file name must not be a path, just a '
734 'filename.') 764 'filename.')
735 try: 765 try:
736 deps_content = gclient_utils.FileRead( 766 deps_content = gclient_utils.FileRead(
737 os.path.join(self.root_dir(), name, deps_file)) 767 os.path.join(self.root_dir(), name, deps_file))
738 except IOError, e: 768 except IOError, e:
739 if e.errno != errno.ENOENT: 769 if e.errno != errno.ENOENT:
740 raise 770 raise
741 deps_content = "" 771 deps_content = ""
(...skipping 399 matching lines...) Expand 10 before | Expand all | Expand 10 after
1141 return CMDhelp(parser, argv) 1171 return CMDhelp(parser, argv)
1142 except gclient_utils.Error, e: 1172 except gclient_utils.Error, e:
1143 print >> sys.stderr, 'Error: %s' % str(e) 1173 print >> sys.stderr, 'Error: %s' % str(e)
1144 return 1 1174 return 1
1145 1175
1146 1176
1147 if '__main__' == __name__: 1177 if '__main__' == __name__:
1148 sys.exit(Main(sys.argv[1:])) 1178 sys.exit(Main(sys.argv[1:]))
1149 1179
1150 # vim: ts=2:sw=2:tw=80:et: 1180 # vim: ts=2:sw=2:tw=80:et:
OLDNEW
« no previous file with comments | « no previous file | gclient_scm.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698