diff --git a/lib/src/solver/incompatibility.dart b/lib/src/solver/incompatibility.dart index c9d42de69..11c971109 100644 --- a/lib/src/solver/incompatibility.dart +++ b/lib/src/solver/incompatibility.dart @@ -109,6 +109,26 @@ class Incompatibility { return "${_terse(depender, details, allowEvery: true)} depends on " "${_terse(dependee, details)}"; + } else if (cause == IncompatibilityCause.pubDependency) { + if (terms.length == 1) { + var forbidden = terms.first; + assert(forbidden.isPositive); + + // The only one-term pub dependency is on barback, which forbids + // versions outside the range pub supports. + return "pub itself depends on ${_terseRef(forbidden, details)} " + "${VersionConstraint.any.difference(forbidden.constraint)}"; + } + + assert(terms.length == 2); + assert(terms.first.isPositive); + assert(terms.first.package.name == "barback"); + + var dependee = terms.last; + assert(!dependee.isPositive); + + return "when barback is in use pub itself depends on " + + _terse(dependee, details); } else if (cause == IncompatibilityCause.useLatest) { assert(terms.length == 1); @@ -222,16 +242,19 @@ class Incompatibility { /// that should be associated with [this] and [other], respectively. String andToString(Incompatibility other, [Map details, int thisLine, int otherLine]) { - var requiresBoth = _tryRequiresBoth(other, details, thisLine, otherLine); - if (requiresBoth != null) return requiresBoth; - - var requiresThrough = - _tryRequiresThrough(other, details, thisLine, otherLine); - if (requiresThrough != null) return requiresThrough; - - var requiresForbidden = - _tryRequiresForbidden(other, details, thisLine, otherLine); - if (requiresForbidden != null) return requiresForbidden; + if (this.cause != IncompatibilityCause.pubDependency && + other.cause != IncompatibilityCause.pubDependency) { + var requiresBoth = _tryRequiresBoth(other, details, thisLine, otherLine); + if (requiresBoth != null) return requiresBoth; + + var requiresThrough = + _tryRequiresThrough(other, details, thisLine, otherLine); + if (requiresThrough != null) return requiresThrough; + + var requiresForbidden = + _tryRequiresForbidden(other, details, thisLine, otherLine); + if (requiresForbidden != null) return requiresForbidden; + } var buffer = new StringBuffer(this.toString(details)); if (thisLine != null) buffer.write(" $thisLine"); diff --git a/lib/src/solver/incompatibility_cause.dart b/lib/src/solver/incompatibility_cause.dart index f889f146d..1ce98aea3 100644 --- a/lib/src/solver/incompatibility_cause.dart +++ b/lib/src/solver/incompatibility_cause.dart @@ -19,6 +19,11 @@ abstract class IncompatibilityCause { /// The incompatibility represents a package's dependency. static const IncompatibilityCause dependency = const _Cause("dependency"); + /// The incompatibility represents pub's own dependency, which is activated + /// when barback is selected. + static const IncompatibilityCause pubDependency = + const _Cause("pub dependency"); + /// The incompatibility represents the user's request that we use the latest /// version of a given package. static const IncompatibilityCause useLatest = const _Cause("use latest"); diff --git a/lib/src/solver/version_solver.dart b/lib/src/solver/version_solver.dart index b989f5f98..1d5bfef85 100644 --- a/lib/src/solver/version_solver.dart +++ b/lib/src/solver/version_solver.dart @@ -8,6 +8,7 @@ import 'dart:math' as math; import 'package:collection/collection.dart'; import 'package:pub_semver/pub_semver.dart'; +import '../barback.dart'; import '../exceptions.dart'; import '../lock_file.dart'; import '../log.dart' as log; @@ -79,7 +80,29 @@ class VersionSolver { VersionSolver(this._type, this._systemCache, this._root, this._lockFile, Iterable useLatest) : _overriddenPackages = new MapKeySet(_root.pubspec.dependencyOverrides), - _useLatest = new Set.from(useLatest); + _useLatest = new Set.from(useLatest) { + _addImplicitIncompatibilities(); + } + + /// Adds incompatibilities representing the dependencies pub itself has on + /// various packages to support barback at runtime. + void _addImplicitIncompatibilities() { + var barbackOverride = _root.pubspec.dependencyOverrides["barback"]; + var barbackRef = barbackOverride == null + ? _systemCache.sources.hosted.refFor("barback") + : barbackOverride.toRef(); + + pubConstraints.forEach((name, constraint) { + if (_root.pubspec.dependencyOverrides.containsKey(name)) return; + + _addIncompatibility(new Incompatibility([ + new Term(barbackRef.withConstraint(VersionConstraint.any), true), + new Term( + _systemCache.sources.hosted.refFor(name).withConstraint(constraint), + false) + ], IncompatibilityCause.pubDependency)); + }); + } /// Finds a set of dependencies that match the root package's constraints, or /// throws an error if no such set is available. diff --git a/test/implicit_barback_dependency_test.dart b/test/implicit_barback_dependency_test.dart index 5e36ca363..8dc01fd9b 100644 --- a/test/implicit_barback_dependency_test.dart +++ b/test/implicit_barback_dependency_test.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -@Skip() - import 'package:test/test.dart'; import 'package:pub/src/barback.dart' as barback; @@ -150,10 +148,11 @@ main() { await d.appDir({"barback": "any"}).create(); - await pubGet(error: """ -Package barback has no versions that match >=$current <$max derived from: -- myapp depends on version any -- pub itself depends on version >=$current <$max"""); + await pubGet(error: equalsIgnoringWhitespace(""" + Because no versions of barback match >=0.15.0 <0.15.3 and pub itself + depends on barback >=0.15.0 <0.15.3, barback is forbidden. + So, because myapp depends on barback any, version solving failed. + """)); }); test( @@ -169,9 +168,9 @@ Package barback has no versions that match >=$current <$max derived from: await d.appDir({"barback": previous}).create(); - await pubGet(error: """ -Incompatible version constraints on barback: -- myapp depends on version $previous -- pub itself depends on version >=$current <$max"""); + await pubGet(error: equalsIgnoringWhitespace(""" + Because pub itself depends on barback >=0.15.0 <0.15.3 and myapp depends + on barback 0.14.0, version solving failed. + """)); }); } diff --git a/test/implicit_dependency_test.dart b/test/implicit_dependency_test.dart index 59fcaa915..16df364de 100644 --- a/test/implicit_dependency_test.dart +++ b/test/implicit_dependency_test.dart @@ -2,8 +2,6 @@ // for details. All rights reserved. Use of this source code is governed by a // BSD-style license that can be found in the LICENSE file. -@Skip() - import 'package:test/test.dart'; import 'package:pub/src/barback.dart' as barback;