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 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
129 | 129 |
130 def Lookup(self, var_name): | 130 def Lookup(self, var_name): |
131 """Implements the Var syntax.""" | 131 """Implements the Var syntax.""" |
132 if var_name in self._custom_vars: | 132 if var_name in self._custom_vars: |
133 return self._custom_vars[var_name] | 133 return self._custom_vars[var_name] |
134 elif var_name in self._local_scope.get("vars", {}): | 134 elif var_name in self._local_scope.get("vars", {}): |
135 return self._local_scope["vars"][var_name] | 135 return self._local_scope["vars"][var_name] |
136 raise gclient_utils.Error("Var is not defined: %s" % var_name) | 136 raise gclient_utils.Error("Var is not defined: %s" % var_name) |
137 | 137 |
138 | 138 |
139 class DependencySettings(object): | 139 class DependencySettings(GClientKeywords): |
140 """Immutable configuration settings.""" | 140 """Immutable configuration settings.""" |
141 def __init__( | 141 def __init__( |
142 self, parent, safesync_url, managed, custom_deps, custom_vars, | 142 self, parent, url, safesync_url, managed, custom_deps, custom_vars, |
143 deps_file, should_process): | 143 deps_file, should_process): |
| 144 GClientKeywords.__init__(self) |
| 145 |
144 # These are not mutable: | 146 # These are not mutable: |
145 self._parent = parent | 147 self._parent = parent |
146 self._safesync_url = safesync_url | 148 self._safesync_url = safesync_url |
147 self._deps_file = deps_file | 149 self._deps_file = deps_file |
| 150 self._url = url |
148 # 'managed' determines whether or not this dependency is synced/updated by | 151 # 'managed' determines whether or not this dependency is synced/updated by |
149 # gclient after gclient checks it out initially. The difference between | 152 # gclient after gclient checks it out initially. The difference between |
150 # 'managed' and 'should_process' is that the user specifies 'managed' via | 153 # 'managed' and 'should_process' is that the user specifies 'managed' via |
151 # the --unmanaged command-line flag or a .gclient config, where | 154 # the --unmanaged command-line flag or a .gclient config, where |
152 # 'should_process' is dynamically set by gclient if it goes over its | 155 # 'should_process' is dynamically set by gclient if it goes over its |
153 # recursion limit and controls gclient's behavior so it does not misbehave. | 156 # recursion limit and controls gclient's behavior so it does not misbehave. |
154 self._managed = managed | 157 self._managed = managed |
155 self._should_process = should_process | 158 self._should_process = should_process |
156 | 159 |
157 # These are only set in .gclient and not in DEPS files. | 160 # These are only set in .gclient and not in DEPS files. |
158 self._custom_vars = custom_vars or {} | 161 self._custom_vars = custom_vars or {} |
159 self._custom_deps = custom_deps or {} | 162 self._custom_deps = custom_deps or {} |
160 | 163 |
| 164 # Post process the url to remove trailing slashes. |
| 165 if isinstance(self._url, basestring): |
| 166 # urls are sometime incorrectly written as proto://host/path/@rev. Replace |
| 167 # it to proto://host/path@rev. |
| 168 if self._url.count('@') > 1: |
| 169 raise gclient_utils.Error('Invalid url "%s"' % self._url) |
| 170 self._url = self._url.replace('/@', '@') |
| 171 elif not isinstance(self._url, |
| 172 (self.FromImpl, self.FileImpl, None.__class__)): |
| 173 raise gclient_utils.Error( |
| 174 ('dependency url must be either a string, None, ' |
| 175 'File() or From() instead of %s') % self._url.__class__.__name__) |
161 if '/' in self._deps_file or '\\' in self._deps_file: | 176 if '/' in self._deps_file or '\\' in self._deps_file: |
162 raise gclient_utils.Error('deps_file name must not be a path, just a ' | 177 raise gclient_utils.Error('deps_file name must not be a path, just a ' |
163 'filename. %s' % self._deps_file) | 178 'filename. %s' % self._deps_file) |
164 | 179 |
165 @property | 180 @property |
166 def deps_file(self): | 181 def deps_file(self): |
167 """Immutable so no need to lock.""" | 182 """Immutable so no need to lock.""" |
168 return self._deps_file | 183 return self._deps_file |
169 | 184 |
170 @property | 185 @property |
(...skipping 19 matching lines...) Expand all Loading... |
190 @property | 205 @property |
191 def custom_vars(self): | 206 def custom_vars(self): |
192 """Immutable so no need to lock.""" | 207 """Immutable so no need to lock.""" |
193 return self._custom_vars.copy() | 208 return self._custom_vars.copy() |
194 | 209 |
195 @property | 210 @property |
196 def custom_deps(self): | 211 def custom_deps(self): |
197 """Immutable so no need to lock.""" | 212 """Immutable so no need to lock.""" |
198 return self._custom_deps.copy() | 213 return self._custom_deps.copy() |
199 | 214 |
| 215 @property |
| 216 def url(self): |
| 217 return self._url |
200 | 218 |
201 class Dependency(GClientKeywords, gclient_utils.WorkItem, DependencySettings): | 219 |
| 220 class Dependency(gclient_utils.WorkItem, DependencySettings): |
202 """Object that represents a dependency checkout.""" | 221 """Object that represents a dependency checkout.""" |
203 | 222 |
204 def __init__(self, parent, name, url, safesync_url, managed, custom_deps, | 223 def __init__(self, parent, name, url, safesync_url, managed, custom_deps, |
205 custom_vars, deps_file, should_process): | 224 custom_vars, deps_file, should_process): |
206 GClientKeywords.__init__(self) | |
207 gclient_utils.WorkItem.__init__(self, name) | 225 gclient_utils.WorkItem.__init__(self, name) |
208 DependencySettings.__init__( | 226 DependencySettings.__init__( |
209 self, parent, safesync_url, managed, custom_deps, custom_vars, | 227 self, parent, url, safesync_url, managed, custom_deps, custom_vars, |
210 deps_file, should_process) | 228 deps_file, should_process) |
211 | 229 |
212 # This is in both .gclient and DEPS files: | 230 # This is in both .gclient and DEPS files: |
213 self.url = url | 231 self._deps_hooks = [] |
214 | |
215 self.deps_hooks = [] | |
216 | 232 |
217 # Calculates properties: | 233 # Calculates properties: |
218 self.parsed_url = None | 234 self._parsed_url = None |
219 self._dependencies = [] | 235 self._dependencies = [] |
220 # A cache of the files affected by the current operation, necessary for | 236 # A cache of the files affected by the current operation, necessary for |
221 # hooks. | 237 # hooks. |
222 self._file_list = [] | 238 self._file_list = [] |
223 # If it is not set to True, the dependency wasn't processed for its child | 239 # If it is not set to True, the dependency wasn't processed for its child |
224 # dependency, i.e. its DEPS wasn't read. | 240 # dependency, i.e. its DEPS wasn't read. |
225 self.deps_parsed = False | 241 self._deps_parsed = False |
226 # This dependency has been processed, i.e. checked out | 242 # This dependency has been processed, i.e. checked out |
227 self.processed = False | 243 self._processed = False |
228 # This dependency had its hook run | 244 # This dependency had its hook run |
229 self.hooks_ran = False | 245 self._hooks_ran = False |
230 | 246 |
231 # Post process the url to remove trailing slashes. | 247 # Setup self.requirements and find any other dependency who would have self |
232 if isinstance(self.url, basestring): | 248 # as a requirement. |
233 # urls are sometime incorrectly written as proto://host/path/@rev. Replace | |
234 # it to proto://host/path@rev. | |
235 if self.url.count('@') > 1: | |
236 raise gclient_utils.Error('Invalid url "%s"' % self.url) | |
237 self.url = self.url.replace('/@', '@') | |
238 | 249 |
239 self._FindDependencies() | |
240 | |
241 # Sanity checks | |
242 if not self.name and self.parent: | |
243 raise gclient_utils.Error('Dependency without name') | |
244 if not isinstance(self.url, | |
245 (basestring, self.FromImpl, self.FileImpl, None.__class__)): | |
246 raise gclient_utils.Error('dependency url must be either a string, None, ' | |
247 'File() or From() instead of %s' % | |
248 self.url.__class__.__name__) | |
249 | |
250 def _FindDependencies(self): | |
251 """Setup self.requirements and find any other dependency who would have self | |
252 as a requirement. | |
253 """ | |
254 # self.parent is implicitly a requirement. This will be recursive by | 250 # self.parent is implicitly a requirement. This will be recursive by |
255 # definition. | 251 # definition. |
256 if self.parent and self.parent.name: | 252 if self.parent and self.parent.name: |
257 self._requirements.add(self.parent.name) | 253 self._requirements.add(self.parent.name) |
258 | 254 |
259 # For a tree with at least 2 levels*, the leaf node needs to depend | 255 # For a tree with at least 2 levels*, the leaf node needs to depend |
260 # on the level higher up in an orderly way. | 256 # on the level higher up in an orderly way. |
261 # This becomes messy for >2 depth as the DEPS file format is a dictionary, | 257 # This becomes messy for >2 depth as the DEPS file format is a dictionary, |
262 # thus unsorted, while the .gclient format is a list thus sorted. | 258 # thus unsorted, while the .gclient format is a list thus sorted. |
263 # | 259 # |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
296 # Step 2: Find any requirements self may impose. | 292 # Step 2: Find any requirements self may impose. |
297 if obj.name.startswith(posixpath.join(self.name, '')): | 293 if obj.name.startswith(posixpath.join(self.name, '')): |
298 try: | 294 try: |
299 # Access to a protected member _requirements of a client class | 295 # Access to a protected member _requirements of a client class |
300 # pylint: disable=W0212 | 296 # pylint: disable=W0212 |
301 obj.lock.acquire() | 297 obj.lock.acquire() |
302 obj._requirements.add(self.name) | 298 obj._requirements.add(self.name) |
303 finally: | 299 finally: |
304 obj.lock.release() | 300 obj.lock.release() |
305 | 301 |
| 302 if not self.name and self.parent: |
| 303 raise gclient_utils.Error('Dependency without name') |
| 304 |
306 def LateOverride(self, url): | 305 def LateOverride(self, url): |
307 """Resolves the parsed url from url. | 306 """Resolves the parsed url from url. |
308 | 307 |
309 Manages From() keyword accordingly. Do not touch self.parsed_url nor | 308 Manages From() keyword accordingly. Do not touch self.parsed_url nor |
310 self.url because it may called with other urls due to From().""" | 309 self.url because it may called with other urls due to From().""" |
311 assert self.parsed_url == None or not self.should_process, self.parsed_url | 310 assert self.parsed_url == None or not self.should_process, self.parsed_url |
312 overriden_url = self.get_custom_deps(self.name, url) | 311 overriden_url = self.get_custom_deps(self.name, url) |
313 if overriden_url != url: | 312 if overriden_url != url: |
314 logging.info('%s, %s was overriden to %s' % (self.name, url, | 313 logging.info('%s, %s was overriden to %s' % (self.name, url, |
315 overriden_url)) | 314 overriden_url)) |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
368 return None | 367 return None |
369 else: | 368 else: |
370 raise gclient_utils.Error('Unkown url type') | 369 raise gclient_utils.Error('Unkown url type') |
371 | 370 |
372 def ParseDepsFile(self): | 371 def ParseDepsFile(self): |
373 """Parses the DEPS file for this dependency.""" | 372 """Parses the DEPS file for this dependency.""" |
374 assert self.processed == True | 373 assert self.processed == True |
375 if self.deps_parsed: | 374 if self.deps_parsed: |
376 logging.debug('%s was already parsed' % self.name) | 375 logging.debug('%s was already parsed' % self.name) |
377 return | 376 return |
378 self.deps_parsed = True | |
379 # One thing is unintuitive, vars= {} must happen before Var() use. | 377 # One thing is unintuitive, vars= {} must happen before Var() use. |
380 local_scope = {} | 378 local_scope = {} |
381 var = self.VarImpl(self.custom_vars, local_scope) | 379 var = self.VarImpl(self.custom_vars, local_scope) |
382 global_scope = { | 380 global_scope = { |
383 'File': self.FileImpl, | 381 'File': self.FileImpl, |
384 'From': self.FromImpl, | 382 'From': self.FromImpl, |
385 'Var': var.Lookup, | 383 'Var': var.Lookup, |
386 'deps_os': {}, | 384 'deps_os': {}, |
387 } | 385 } |
388 filepath = os.path.join(self.root.root_dir, self.name, self.deps_file) | 386 filepath = os.path.join(self.root.root_dir, self.name, self.deps_file) |
(...skipping 17 matching lines...) Expand all Loading... |
406 os_deps = local_scope['deps_os'].get(deps_os_key, {}) | 404 os_deps = local_scope['deps_os'].get(deps_os_key, {}) |
407 if len(enforced_os) > 1: | 405 if len(enforced_os) > 1: |
408 # Ignore any conflict when including deps for more than one | 406 # Ignore any conflict when including deps for more than one |
409 # platform, so we collect the broadest set of dependencies | 407 # platform, so we collect the broadest set of dependencies |
410 # available. We may end up with the wrong revision of something for | 408 # available. We may end up with the wrong revision of something for |
411 # our platform, but this is the best we can do. | 409 # our platform, but this is the best we can do. |
412 deps.update([x for x in os_deps.items() if not x[0] in deps]) | 410 deps.update([x for x in os_deps.items() if not x[0] in deps]) |
413 else: | 411 else: |
414 deps.update(os_deps) | 412 deps.update(os_deps) |
415 | 413 |
416 self.deps_hooks.extend(local_scope.get('hooks', [])) | 414 self._deps_hooks.extend(local_scope.get('hooks', [])) |
417 | 415 |
418 # If a line is in custom_deps, but not in the solution, we want to append | 416 # If a line is in custom_deps, but not in the solution, we want to append |
419 # this line to the solution. | 417 # this line to the solution. |
420 for d in self.custom_deps: | 418 for d in self.custom_deps: |
421 if d not in deps: | 419 if d not in deps: |
422 deps[d] = self.custom_deps[d] | 420 deps[d] = self.custom_deps[d] |
423 | 421 |
424 # If use_relative_paths is set in the DEPS file, regenerate | 422 # If use_relative_paths is set in the DEPS file, regenerate |
425 # the dictionary using paths relative to the directory containing | 423 # the dictionary using paths relative to the directory containing |
426 # the DEPS file. | 424 # the DEPS file. |
(...skipping 23 matching lines...) Expand all Loading... |
450 #should_process = False | 448 #should_process = False |
451 continue | 449 continue |
452 else: | 450 else: |
453 raise gclient_utils.Error( | 451 raise gclient_utils.Error( |
454 'Dependency %s specified more than once:\n %s\nvs\n %s' % | 452 'Dependency %s specified more than once:\n %s\nvs\n %s' % |
455 (name, tree[name].hierarchy(), self.hierarchy())) | 453 (name, tree[name].hierarchy(), self.hierarchy())) |
456 self._dependencies.append( | 454 self._dependencies.append( |
457 Dependency( | 455 Dependency( |
458 self, name, url, None, None, None, None, | 456 self, name, url, None, None, None, None, |
459 self.deps_file, should_process)) | 457 self.deps_file, should_process)) |
| 458 self._deps_parsed = True |
460 logging.debug('Loaded: %s' % str(self)) | 459 logging.debug('Loaded: %s' % str(self)) |
461 | 460 |
462 # Arguments number differs from overridden method | 461 # Arguments number differs from overridden method |
463 # pylint: disable=W0221 | 462 # pylint: disable=W0221 |
464 def run(self, revision_overrides, command, args, work_queue, options): | 463 def run(self, revision_overrides, command, args, work_queue, options): |
465 """Runs 'command' before parsing the DEPS in case it's a initial checkout | 464 """Runs 'command' before parsing the DEPS in case it's a initial checkout |
466 or a revert.""" | 465 or a revert.""" |
467 | 466 |
468 def maybeGetParentRevision(options): | 467 def maybeGetParentRevision(options): |
469 """If we are performing an update and --transitive is set, set the | 468 """If we are performing an update and --transitive is set, set the |
(...skipping 28 matching lines...) Expand all Loading... |
498 (options.revision, revision)) | 497 (options.revision, revision)) |
499 revision_overrides[self.name] = revision | 498 revision_overrides[self.name] = revision |
500 | 499 |
501 assert self._file_list == [] | 500 assert self._file_list == [] |
502 if not self.should_process: | 501 if not self.should_process: |
503 return | 502 return |
504 # When running runhooks, there's no need to consult the SCM. | 503 # When running runhooks, there's no need to consult the SCM. |
505 # All known hooks are expected to run unconditionally regardless of working | 504 # All known hooks are expected to run unconditionally regardless of working |
506 # copy state, so skip the SCM status check. | 505 # copy state, so skip the SCM status check. |
507 run_scm = command not in ('runhooks', None) | 506 run_scm = command not in ('runhooks', None) |
508 self.parsed_url = self.LateOverride(self.url) | 507 self._parsed_url = self.LateOverride(self.url) |
509 if run_scm and self.parsed_url: | 508 if run_scm and self.parsed_url: |
510 if isinstance(self.parsed_url, self.FileImpl): | 509 if isinstance(self.parsed_url, self.FileImpl): |
511 # Special support for single-file checkout. | 510 # Special support for single-file checkout. |
512 if not command in (None, 'cleanup', 'diff', 'pack', 'status'): | 511 if not command in (None, 'cleanup', 'diff', 'pack', 'status'): |
513 options.revision = self.parsed_url.GetRevision() | 512 options.revision = self.parsed_url.GetRevision() |
514 scm = gclient_scm.SVNWrapper(self.parsed_url.GetPath(), | 513 scm = gclient_scm.SVNWrapper(self.parsed_url.GetPath(), |
515 self.root.root_dir, | 514 self.root.root_dir, |
516 self.name) | 515 self.name) |
517 scm.RunCommand('updatesingle', options, | 516 scm.RunCommand('updatesingle', options, |
518 args + [self.parsed_url.GetFilename()], | 517 args + [self.parsed_url.GetFilename()], |
(...skipping 16 matching lines...) Expand all Loading... |
535 # It depends on the command being executed (like runhooks vs sync). | 534 # It depends on the command being executed (like runhooks vs sync). |
536 if not os.path.isabs(self._file_list[i]): | 535 if not os.path.isabs(self._file_list[i]): |
537 continue | 536 continue |
538 prefix = os.path.commonprefix( | 537 prefix = os.path.commonprefix( |
539 [self.root.root_dir.lower(), self._file_list[i].lower()]) | 538 [self.root.root_dir.lower(), self._file_list[i].lower()]) |
540 self._file_list[i] = self._file_list[i][len(prefix):] | 539 self._file_list[i] = self._file_list[i][len(prefix):] |
541 # Strip any leading path separators. | 540 # Strip any leading path separators. |
542 while (self._file_list[i].startswith('\\') or | 541 while (self._file_list[i].startswith('\\') or |
543 self._file_list[i].startswith('/')): | 542 self._file_list[i].startswith('/')): |
544 self._file_list[i] = self._file_list[i][1:] | 543 self._file_list[i] = self._file_list[i][1:] |
545 self.processed = True | 544 self._processed = True |
546 if self.recursion_limit: | 545 if self.recursion_limit: |
547 # Then we can parse the DEPS file. | 546 # Then we can parse the DEPS file. |
548 self.ParseDepsFile() | 547 self.ParseDepsFile() |
549 | 548 |
550 # Parse the dependencies of this dependency. | 549 # Parse the dependencies of this dependency. |
551 for s in self.dependencies: | 550 for s in self.dependencies: |
552 work_queue.enqueue(s) | 551 work_queue.enqueue(s) |
553 | 552 |
554 def RunHooksRecursively(self, options): | 553 def RunHooksRecursively(self, options): |
555 """Evaluates all hooks, running actions as needed. run() | 554 """Evaluates all hooks, running actions as needed. run() |
(...skipping 23 matching lines...) Expand all Loading... |
579 if matching_file_list: | 578 if matching_file_list: |
580 self._RunHookAction(hook_dict, matching_file_list) | 579 self._RunHookAction(hook_dict, matching_file_list) |
581 for s in self.dependencies: | 580 for s in self.dependencies: |
582 s.RunHooksRecursively(options) | 581 s.RunHooksRecursively(options) |
583 | 582 |
584 def _RunHookAction(self, hook_dict, matching_file_list): | 583 def _RunHookAction(self, hook_dict, matching_file_list): |
585 """Runs the action from a single hook.""" | 584 """Runs the action from a single hook.""" |
586 # A single DEPS file can specify multiple hooks so this function can be | 585 # A single DEPS file can specify multiple hooks so this function can be |
587 # called multiple times on a single Dependency. | 586 # called multiple times on a single Dependency. |
588 #assert self.hooks_ran == False | 587 #assert self.hooks_ran == False |
589 self.hooks_ran = True | 588 self._hooks_ran = True |
590 logging.debug(hook_dict) | 589 logging.debug(hook_dict) |
591 logging.debug(matching_file_list) | 590 logging.debug(matching_file_list) |
592 command = hook_dict['action'][:] | 591 command = hook_dict['action'][:] |
593 if command[0] == 'python': | 592 if command[0] == 'python': |
594 # If the hook specified "python" as the first item, the action is a | 593 # If the hook specified "python" as the first item, the action is a |
595 # Python script. Run it by starting a new copy of the same | 594 # Python script. Run it by starting a new copy of the same |
596 # interpreter. | 595 # interpreter. |
597 command[0] = sys.executable | 596 command[0] = sys.executable |
598 | 597 |
599 if '$matching_files' in command: | 598 if '$matching_files' in command: |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
634 | 633 |
635 Immutable so no need to lock. | 634 Immutable so no need to lock. |
636 """ | 635 """ |
637 return max(self.parent.recursion_limit - 1, 0) | 636 return max(self.parent.recursion_limit - 1, 0) |
638 | 637 |
639 @property | 638 @property |
640 def dependencies(self): | 639 def dependencies(self): |
641 return tuple(self._dependencies) | 640 return tuple(self._dependencies) |
642 | 641 |
643 @property | 642 @property |
| 643 def deps_hooks(self): |
| 644 return tuple(self._deps_hooks) |
| 645 |
| 646 @property |
| 647 def parsed_url(self): |
| 648 return self._parsed_url |
| 649 |
| 650 @property |
| 651 def deps_parsed(self): |
| 652 return self._deps_parsed |
| 653 |
| 654 @property |
| 655 def processed(self): |
| 656 return self._processed |
| 657 |
| 658 @property |
| 659 def hooks_ran(self): |
| 660 return self._hooks_ran |
| 661 |
| 662 @property |
644 def file_list(self): | 663 def file_list(self): |
645 result = self._file_list[:] | 664 result = self._file_list[:] |
646 for d in self.dependencies: | 665 for d in self.dependencies: |
647 result.extend(d.file_list) | 666 result.extend(d.file_list) |
648 return tuple(result) | 667 return tuple(result) |
649 | 668 |
650 def __str__(self): | 669 def __str__(self): |
651 out = [] | 670 out = [] |
652 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps', | 671 for i in ('name', 'url', 'parsed_url', 'safesync_url', 'custom_deps', |
653 'custom_vars', 'deps_hooks', 'file_list', 'should_process', | 672 'custom_vars', 'deps_hooks', 'file_list', 'should_process', |
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
768 s.get('safesync_url', None), | 787 s.get('safesync_url', None), |
769 s.get('managed', True), | 788 s.get('managed', True), |
770 s.get('custom_deps', {}), | 789 s.get('custom_deps', {}), |
771 s.get('custom_vars', {}), | 790 s.get('custom_vars', {}), |
772 s.get('deps_file', 'DEPS'), | 791 s.get('deps_file', 'DEPS'), |
773 True)) | 792 True)) |
774 except KeyError: | 793 except KeyError: |
775 raise gclient_utils.Error('Invalid .gclient file. Solution is ' | 794 raise gclient_utils.Error('Invalid .gclient file. Solution is ' |
776 'incomplete: %s' % s) | 795 'incomplete: %s' % s) |
777 # .gclient can have hooks. | 796 # .gclient can have hooks. |
778 self.deps_hooks = config_dict.get('hooks', []) | 797 self._deps_hooks = config_dict.get('hooks', []) |
779 self.deps_parsed = True | 798 self._deps_parsed = True |
780 | 799 |
781 def SaveConfig(self): | 800 def SaveConfig(self): |
782 gclient_utils.FileWrite(os.path.join(self.root_dir, | 801 gclient_utils.FileWrite(os.path.join(self.root_dir, |
783 self._options.config_filename), | 802 self._options.config_filename), |
784 self.config_content) | 803 self.config_content) |
785 | 804 |
786 @staticmethod | 805 @staticmethod |
787 def LoadCurrentConfig(options): | 806 def LoadCurrentConfig(options): |
788 """Searches for and loads a .gclient file relative to the current working | 807 """Searches for and loads a .gclient file relative to the current working |
789 dir. Returns a GClient object.""" | 808 dir. Returns a GClient object.""" |
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1439 except (gclient_utils.Error, subprocess2.CalledProcessError), e: | 1458 except (gclient_utils.Error, subprocess2.CalledProcessError), e: |
1440 print >> sys.stderr, 'Error: %s' % str(e) | 1459 print >> sys.stderr, 'Error: %s' % str(e) |
1441 return 1 | 1460 return 1 |
1442 | 1461 |
1443 | 1462 |
1444 if '__main__' == __name__: | 1463 if '__main__' == __name__: |
1445 fix_encoding.fix_encoding() | 1464 fix_encoding.fix_encoding() |
1446 sys.exit(Main(sys.argv[1:])) | 1465 sys.exit(Main(sys.argv[1:])) |
1447 | 1466 |
1448 # vim: ts=2:sw=2:tw=80:et: | 1467 # vim: ts=2:sw=2:tw=80:et: |
OLD | NEW |