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

Side by Side Diff: sdk/lib/_internal/pub/lib/src/solver/backtracking_solver.dart

Issue 356523003: Add implicit constraints from pub onto stack_trace and source_maps. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 /// A back-tracking depth-first solver. 5 /// A back-tracking depth-first solver.
6 /// 6 ///
7 /// Attempts to find the best solution for a root package's transitive 7 /// Attempts to find the best solution for a root package's transitive
8 /// dependency graph, where a "solution" is a set of concrete package versions. 8 /// dependency graph, where a "solution" is a set of concrete package versions.
9 /// A valid solution will select concrete versions for every package reached 9 /// A valid solution will select concrete versions for every package reached
10 /// from the root package's dependency graph, and each of those packages will 10 /// from the root package's dependency graph, and each of those packages will
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 /// Desctructively modifies [deps]. Completes to a list of packages if the 527 /// Desctructively modifies [deps]. Completes to a list of packages if the
528 /// traversal is complete. Completes it to an error if a failure occurred. 528 /// traversal is complete. Completes it to an error if a failure occurred.
529 /// Otherwise, recurses. 529 /// Otherwise, recurses.
530 Future<List<PackageId>> _traverseDeps(PackageId depender, 530 Future<List<PackageId>> _traverseDeps(PackageId depender,
531 DependencyQueue deps) { 531 DependencyQueue deps) {
532 // Move onto the next package if we've traversed all of these references. 532 // Move onto the next package if we've traversed all of these references.
533 if (deps.isEmpty) return _traversePackage(); 533 if (deps.isEmpty) return _traversePackage();
534 534
535 return resetStack(() { 535 return resetStack(() {
536 return deps.advance().then((dep) { 536 return deps.advance().then((dep) {
537 _validateDependency(dep, depender); 537 var dependency = new Dependency(depender.name, depender.version, dep);
538 538 return _registerDependency(dependency).then((_) {
539 // Add the dependency. 539 if (dep.name == "barback") return _addImplicitDependencies();
540 var dependencies = _getDependencies(dep.name);
541 dependencies.add(new Dependency(depender.name, depender.version, dep));
542
543 // If the package is barback, pub has an implicit version constraint on
544 // it since pub itself uses barback too. Note that we don't check for
545 // the hosted source here because we still want to do this even when
546 // people on the Dart team are on the bleeding edge and have a path
547 // dependency on the tip version of barback in the Dart repo.
548 //
549 // The length check here is to ensure we only add the barback
550 // dependency once.
551 if (dep.name == "barback" && dependencies.length == 1) {
552 _solver.logSolve('add implicit ${barback.supportedVersions} pub '
553 'dependency on barback');
554
555 // Use the same source and description as the explicit dependency.
556 // That way, this doesn't fail with a source/desc conflict if users
557 // (like Dart team members) use things like a path dependency to
558 // find barback.
559 var barbackDep = new PackageDep(dep.name, dep.source,
560 barback.supportedVersions, dep.description);
561 dependencies.add(new Dependency("pub itself", null, barbackDep));
562 }
563
564 var constraint = _getConstraint(dep.name);
565
566 // See if it's possible for a package to match that constraint.
567 if (constraint.isEmpty) {
568 var constraints = _getDependencies(dep.name)
569 .map((dep) => " ${dep.dep.constraint} from ${dep.depender}")
570 .join('\n');
571 _solver.logSolve(
572 'disjoint constraints on ${dep.name}:\n$constraints');
573 throw new DisjointConstraintException(dep.name, dependencies);
574 }
575
576 var selected = _validateSelected(dep, constraint);
577 if (selected != null) {
578 // The selected package version is good, so enqueue it to traverse
579 // into it.
580 _packages.add(selected);
581 return _traverseDeps(depender, deps);
582 }
583
584 // We haven't selected a version. Try all of the versions that match
585 // the constraints we currently have for this package.
586 var locked = _getValidLocked(dep.name);
587
588 return VersionQueue.create(locked,
589 () => _getAllowedVersions(dep)).then((versions) {
590 _packages.add(_solver.select(versions));
591 }); 540 });
592 }).then((_) => _traverseDeps(depender, deps)); 541 }).then((_) => _traverseDeps(depender, deps));
593 }); 542 });
594 } 543 }
595 544
545 /// Register [dependency]'s constraints on the package it depends on and
546 /// enqueues the package for processing if necessary.
547 Future _registerDependency(Dependency dependency) {
548 return syncFuture(() {
549 _validateDependency(dependency);
550
551 var dep = dependency.dep;
552 var dependencies = _getDependencies(dep.name);
553 dependencies.add(dependency);
554
555 var constraint = _getConstraint(dep.name);
556
557 // See if it's possible for a package to match that constraint.
558 if (constraint.isEmpty) {
559 var constraints = dependencies
560 .map((dep) => " ${dep.dep.constraint} from ${dep.depender}")
561 .join('\n');
562 _solver.logSolve(
563 'disjoint constraints on ${dep.name}:\n$constraints');
564 throw new DisjointConstraintException(dep.name, dependencies);
565 }
566
567 var selected = _validateSelected(dep, constraint);
568 if (selected != null) {
569 // The selected package version is good, so enqueue it to traverse
570 // into it.
571 _packages.add(selected);
572 return null;
573 }
574
575 // We haven't selected a version. Try all of the versions that match
576 // the constraints we currently have for this package.
577 var locked = _getValidLocked(dep.name);
578
579 return VersionQueue.create(locked, () {
580 return _getAllowedVersions(dep);
581 }).then((versions) => _packages.add(_solver.select(versions)));
582 });
583 }
584
596 /// Gets all versions of [dep] that match the current constraints placed on 585 /// Gets all versions of [dep] that match the current constraints placed on
597 /// it. 586 /// it.
598 Future<Iterable<PackageId>> _getAllowedVersions(PackageDep dep) { 587 Future<Iterable<PackageId>> _getAllowedVersions(PackageDep dep) {
599 var constraint = _getConstraint(dep.name); 588 var constraint = _getConstraint(dep.name);
600 return _solver.cache.getVersions(dep.toRef()).then((versions) { 589 return _solver.cache.getVersions(dep.toRef()).then((versions) {
601 var allowed = versions.where((id) => constraint.allows(id.version)); 590 var allowed = versions.where((id) => constraint.allows(id.version));
602 591
603 if (allowed.isEmpty) { 592 if (allowed.isEmpty) {
604 _solver.logSolve('no versions for ${dep.name} match $constraint'); 593 _solver.logSolve('no versions for ${dep.name} match $constraint');
605 throw new NoVersionException(dep.name, null, constraint, 594 throw new NoVersionException(dep.name, null, constraint,
(...skipping 20 matching lines...) Expand all
626 615
627 throw error; 616 throw error;
628 }); 617 });
629 } 618 }
630 619
631 /// Ensures that dependency [dep] from [depender] is consistent with the 620 /// Ensures that dependency [dep] from [depender] is consistent with the
632 /// other dependencies on the same package. 621 /// other dependencies on the same package.
633 /// 622 ///
634 /// Throws a [SolveFailure] exception if not. Only validates sources and 623 /// Throws a [SolveFailure] exception if not. Only validates sources and
635 /// descriptions, not the version. 624 /// descriptions, not the version.
636 void _validateDependency(PackageDep dep, PackageId depender) { 625 void _validateDependency(Dependency dependency) {
626 var dep = dependency.dep;
627
637 // Make sure the dependencies agree on source and description. 628 // Make sure the dependencies agree on source and description.
638 var required = _getRequired(dep.name); 629 var required = _getRequired(dep.name);
639 if (required == null) return; 630 if (required == null) return;
640 631
641 // Make sure all of the existing sources match the new reference. 632 // Make sure all of the existing sources match the new reference.
642 if (required.dep.source != dep.source) { 633 if (required.dep.source != dep.source) {
643 _solver.logSolve('source mismatch on ${dep.name}: ${required.dep.source} ' 634 _solver.logSolve('source mismatch on ${dep.name}: ${required.dep.source} '
644 '!= ${dep.source}'); 635 '!= ${dep.source}');
645 throw new SourceMismatchException(dep.name, 636 throw new SourceMismatchException(dep.name, [required, dependency]);
646 [required, new Dependency(depender.name, depender.version, dep)]);
647 } 637 }
648 638
649 // Make sure all of the existing descriptions match the new reference. 639 // Make sure all of the existing descriptions match the new reference.
650 var source = _solver.sources[dep.source]; 640 var source = _solver.sources[dep.source];
651 if (!source.descriptionsEqual(dep.description, required.dep.description)) { 641 if (!source.descriptionsEqual(dep.description, required.dep.description)) {
652 _solver.logSolve('description mismatch on ${dep.name}: ' 642 _solver.logSolve('description mismatch on ${dep.name}: '
653 '${required.dep.description} != ${dep.description}'); 643 '${required.dep.description} != ${dep.description}');
654 throw new DescriptionMismatchException(dep.name, 644 throw new DescriptionMismatchException(dep.name, [required, dependency]);
655 [required, new Dependency(depender.name, depender.version, dep)]);
656 } 645 }
657 } 646 }
658 647
659 /// Validates the currently selected package against the new dependency that 648 /// Validates the currently selected package against the new dependency that
660 /// [dep] and [constraint] place on it. 649 /// [dep] and [constraint] place on it.
661 /// 650 ///
662 /// Returns `null` if there is no currently selected package, throws a 651 /// Returns `null` if there is no currently selected package, throws a
663 /// [SolveFailure] if the new reference it not does not allow the previously 652 /// [SolveFailure] if the new reference it not does not allow the previously
664 /// selected version, or returns the selected package if successful. 653 /// selected version, or returns the selected package if successful.
665 PackageId _validateSelected(PackageDep dep, VersionConstraint constraint) { 654 PackageId _validateSelected(PackageDep dep, VersionConstraint constraint) {
666 var selected = _solver.getSelected(dep.name); 655 var selected = _solver.getSelected(dep.name);
667 if (selected == null) return null; 656 if (selected == null) return null;
668 657
669 // Make sure it meets the constraint. 658 // Make sure it meets the constraint.
670 if (!dep.constraint.allows(selected.version)) { 659 if (!dep.constraint.allows(selected.version)) {
671 _solver.logSolve('selection $selected does not match $constraint'); 660 _solver.logSolve('selection $selected does not match $constraint');
672 throw new NoVersionException(dep.name, selected.version, constraint, 661 throw new NoVersionException(dep.name, selected.version, constraint,
673 _getDependencies(dep.name)); 662 _getDependencies(dep.name));
674 } 663 }
675 664
676 return selected; 665 return selected;
677 } 666 }
678 667
668 /// Register pub's implicit dependencies.
669 ///
670 /// Pub has an implicit version constraint on barback and various other
671 /// packages used in barback's plugin isolate.
672 Future _addImplicitDependencies() {
673 /// Ensure we only add the barback dependency once.
674 if (_getDependencies("barback").length != 1) return new Future.value();
675
676 return Future.wait(barback.pubConstraints.keys.map((depName) {
677 var constraint = barback.pubConstraints[depName];
678 _solver.logSolve('add implicit $constraint pub dependency on '
679 '$depName');
680
681 var override = _solver._overrides[depName];
Bob Nystrom 2014/06/26 16:37:33 Nice. I didn't remember that the solver already ha
682
683 // Use the same source and description as the dependency override if
684 // one exists.
Bob Nystrom 2014/06/26 16:37:33 Document that this is mainly for the bots.
nweiz 2014/06/26 20:03:48 Done.
685 var pubDep = override == null ?
686 new PackageDep(depName, "hosted", constraint, depName) :
687 override.withConstraint(constraint);
688 return _registerDependency(new Dependency("pub itself", null, pubDep));
689 }));
690 }
691
679 /// Gets the list of dependencies for package [name]. 692 /// Gets the list of dependencies for package [name].
680 /// 693 ///
681 /// Creates an empty list if needed. 694 /// Creates an empty list if needed.
682 List<Dependency> _getDependencies(String name) { 695 List<Dependency> _getDependencies(String name) {
683 return _dependencies.putIfAbsent(name, () => <Dependency>[]); 696 return _dependencies.putIfAbsent(name, () => <Dependency>[]);
684 } 697 }
685 698
686 /// Gets a "required" reference to the package [name]. 699 /// Gets a "required" reference to the package [name].
687 /// 700 ///
688 /// This is the first non-root dependency on that package. All dependencies 701 /// This is the first non-root dependency on that package. All dependencies
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
745 /// 758 ///
746 /// Throws a [SolveFailure] if not. 759 /// Throws a [SolveFailure] if not.
747 void _validateSdkConstraint(Pubspec pubspec) { 760 void _validateSdkConstraint(Pubspec pubspec) {
748 if (pubspec.environment.sdkVersion.allows(sdk.version)) return; 761 if (pubspec.environment.sdkVersion.allows(sdk.version)) return;
749 762
750 throw new BadSdkVersionException(pubspec.name, 763 throw new BadSdkVersionException(pubspec.name,
751 'Package ${pubspec.name} requires SDK version ' 764 'Package ${pubspec.name} requires SDK version '
752 '${pubspec.environment.sdkVersion} but the current SDK is ' 765 '${pubspec.environment.sdkVersion} but the current SDK is '
753 '${sdk.version}.'); 766 '${sdk.version}.');
754 } 767 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698