Skip to content

Support implicit pub dependencies #1844

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Mar 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 33 additions & 10 deletions lib/src/solver/incompatibility.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down Expand Up @@ -222,16 +242,19 @@ class Incompatibility {
/// that should be associated with [this] and [other], respectively.
String andToString(Incompatibility other,
[Map<String, PackageDetail> 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");
Expand Down
5 changes: 5 additions & 0 deletions lib/src/solver/incompatibility_cause.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand Down
25 changes: 24 additions & 1 deletion lib/src/solver/version_solver.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -79,7 +80,29 @@ class VersionSolver {
VersionSolver(this._type, this._systemCache, this._root, this._lockFile,
Iterable<String> 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.
Expand Down
19 changes: 9 additions & 10 deletions test/implicit_barback_dependency_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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(
Expand All @@ -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.
"""));
});
}
2 changes: 0 additions & 2 deletions test/implicit_dependency_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down