Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 import 'dart:async'; | 5 import 'dart:async'; |
| 6 | 6 |
| 7 import 'package:pub/src/lock_file.dart'; | 7 import 'package:pub/src/lock_file.dart'; |
| 8 import 'package:pub/src/log.dart' as log; | 8 import 'package:pub/src/log.dart' as log; |
| 9 import 'package:pub/src/package.dart'; | 9 import 'package:pub/src/package.dart'; |
| 10 import 'package:pub/src/pubspec.dart'; | 10 import 'package:pub/src/pubspec.dart'; |
| 11 import 'package:pub/src/sdk.dart' as sdk; | 11 import 'package:pub/src/sdk.dart' as sdk; |
| 12 import 'package:pub/src/solver/version_solver.dart'; | 12 import 'package:pub/src/solver/version_solver.dart'; |
| 13 import 'package:pub/src/source.dart'; | 13 import 'package:pub/src/source.dart'; |
| 14 import 'package:pub/src/source/cached.dart'; | 14 import 'package:pub/src/source/cached.dart'; |
| 15 import 'package:pub/src/source_registry.dart'; | |
| 15 import 'package:pub/src/system_cache.dart'; | 16 import 'package:pub/src/system_cache.dart'; |
| 16 import 'package:pub/src/utils.dart'; | 17 import 'package:pub/src/utils.dart'; |
| 17 import 'package:pub_semver/pub_semver.dart'; | 18 import 'package:pub_semver/pub_semver.dart'; |
| 18 import 'package:test/test.dart'; | 19 import 'package:test/test.dart'; |
| 19 | 20 |
| 20 MockSource source1; | 21 MockSource source1; |
| 21 MockSource source2; | 22 MockSource source2; |
| 22 | 23 |
| 23 main() { | 24 main() { |
| 24 // Uncomment this to debug failing tests. | 25 // Uncomment this to debug failing tests. |
| (...skipping 620 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 645 'b 2.0.0': { | 646 'b 2.0.0': { |
| 646 'a-y': 'any' | 647 'a-y': 'any' |
| 647 }, | 648 }, |
| 648 'c 1.0.0': {}, | 649 'c 1.0.0': {}, |
| 649 'c 2.0.0': {}, | 650 'c 2.0.0': {}, |
| 650 'c 3.0.0': {}, | 651 'c 3.0.0': {}, |
| 651 'c 4.0.0': {}, | 652 'c 4.0.0': {}, |
| 652 'c 5.0.0': {}, | 653 'c 5.0.0': {}, |
| 653 }, result: { | 654 }, result: { |
| 654 'myapp from root': '0.0.0', | 655 'myapp from root': '0.0.0', |
| 655 'a': '1.0.0', | 656 'a-x': '1.0.0', |
|
Bob Nystrom
2016/06/23 20:29:49
Why the change here?
nweiz
2016/06/23 21:01:21
Previously, the result wasn't validating which "a
Bob Nystrom
2016/06/23 22:02:20
Ah, cool. I thought it was actually producing a di
| |
| 656 'b': '1.0.0', | 657 'b': '1.0.0', |
| 657 'c': '5.0.0' | 658 'c': '5.0.0' |
| 658 }, maxTries: 2); | 659 }, maxTries: 2); |
| 659 | 660 |
| 660 // Similar to the above two tests but where there is no solution. It should | 661 // Similar to the above two tests but where there is no solution. It should |
| 661 // fail in this case with no backtracking. | 662 // fail in this case with no backtracking. |
| 662 testResolve('backjump to conflicting source', { | 663 testResolve('backjump to conflicting source', { |
| 663 'myapp 0.0.0': { | 664 'myapp 0.0.0': { |
| 664 'a': 'any', | 665 'a': 'any', |
| 665 'b': 'any', | 666 'b': 'any', |
| (...skipping 448 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1114 source2 = new MockSource('mock2'); | 1115 source2 = new MockSource('mock2'); |
| 1115 | 1116 |
| 1116 var cache = new SystemCache(rootDir: '.'); | 1117 var cache = new SystemCache(rootDir: '.'); |
| 1117 cache.sources.register(source1); | 1118 cache.sources.register(source1); |
| 1118 cache.sources.register(source2); | 1119 cache.sources.register(source2); |
| 1119 cache.sources.setDefault(source1.name); | 1120 cache.sources.setDefault(source1.name); |
| 1120 | 1121 |
| 1121 // Build the test package graph. | 1122 // Build the test package graph. |
| 1122 var root; | 1123 var root; |
| 1123 packages.forEach((description, dependencies) { | 1124 packages.forEach((description, dependencies) { |
| 1124 var id = parseSpec(description); | 1125 var id = parseSpec(cache.sources, description); |
| 1125 var package = mockPackage(id, dependencies, | 1126 var package = mockPackage(cache.sources, id, dependencies, |
| 1126 id.name == 'myapp' ? overrides : null); | 1127 id.name == 'myapp' ? overrides : null); |
| 1127 if (id.name == 'myapp') { | 1128 if (id.name == 'myapp') { |
| 1128 // Don't add the root package to the server, so we can verify that Pub | 1129 // Don't add the root package to the server, so we can verify that Pub |
| 1129 // doesn't try to look up information about the local package on the | 1130 // doesn't try to look up information about the local package on the |
| 1130 // remote server. | 1131 // remote server. |
| 1131 root = package; | 1132 root = package; |
| 1132 } else { | 1133 } else { |
| 1133 (cache.source(id.source) as BoundMockSource) | 1134 (cache.source(id.source) as BoundMockSource) |
| 1134 .addPackage(id.description, package); | 1135 .addPackage(id.description, package); |
| 1135 } | 1136 } |
| 1136 }); | 1137 }); |
| 1137 | 1138 |
| 1138 // Clean up the expectation. | 1139 // Clean up the expectation. |
| 1139 if (result != null) { | 1140 if (result != null) { |
| 1140 var newResult = {}; | 1141 var newResult = {}; |
| 1141 result.forEach((description, version) { | 1142 result.forEach((description, version) { |
| 1142 var id = parseSpec(description, version); | 1143 var id = parseSpec(cache.sources, description, version); |
| 1143 newResult[id.name] = id; | 1144 newResult[id.name] = id; |
| 1144 }); | 1145 }); |
| 1145 result = newResult; | 1146 result = newResult; |
| 1146 } | 1147 } |
| 1147 | 1148 |
| 1148 // Parse the lockfile. | 1149 // Parse the lockfile. |
| 1149 var realLockFile; | 1150 var realLockFile; |
| 1150 if (lockfile == null) { | 1151 if (lockfile == null) { |
| 1151 realLockFile = new LockFile.empty(cache.sources); | 1152 realLockFile = new LockFile.empty(); |
| 1152 } else { | 1153 } else { |
| 1153 realLockFile = new LockFile(lockfile.keys.map((name) { | 1154 realLockFile = new LockFile(lockfile.keys.map((name) { |
| 1154 var version = new Version.parse(lockfile[name]); | 1155 var version = new Version.parse(lockfile[name]); |
| 1155 return new PackageId(name, source1.name, version, name); | 1156 return new PackageId(name, source1, version, name); |
| 1156 }), cache.sources); | 1157 })); |
| 1157 } | 1158 } |
| 1158 | 1159 |
| 1159 // Resolve the versions. | 1160 // Resolve the versions. |
| 1160 log.verbosity = log.Verbosity.NONE; | 1161 log.verbosity = log.Verbosity.NONE; |
| 1161 var future = resolveVersions( | 1162 var future = resolveVersions( |
| 1162 downgrade ? SolveType.DOWNGRADE : SolveType.GET, | 1163 downgrade ? SolveType.DOWNGRADE : SolveType.GET, |
| 1163 cache, root, lockFile: realLockFile); | 1164 cache, root, lockFile: realLockFile); |
| 1164 | 1165 |
| 1165 var matcher; | 1166 var matcher; |
| 1166 if (result != null) { | 1167 if (result != null) { |
| (...skipping 184 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1351 /// characters. | 1352 /// characters. |
| 1352 class MockSource extends Source { | 1353 class MockSource extends Source { |
| 1353 final String name; | 1354 final String name; |
| 1354 final hasMultipleVersions = true; | 1355 final hasMultipleVersions = true; |
| 1355 | 1356 |
| 1356 MockSource(this.name); | 1357 MockSource(this.name); |
| 1357 | 1358 |
| 1358 BoundSource bind(SystemCache cache) => new BoundMockSource(this, cache); | 1359 BoundSource bind(SystemCache cache) => new BoundMockSource(this, cache); |
| 1359 | 1360 |
| 1360 PackageRef parseRef(String name, description, {String containingPath}) => | 1361 PackageRef parseRef(String name, description, {String containingPath}) => |
| 1361 new PackageRef(name, this.name, description); | 1362 new PackageRef(name, this, description); |
| 1362 | 1363 |
| 1363 PackageId parseId(String name, Version version, description) => | 1364 PackageId parseId(String name, Version version, description) => |
| 1364 new PackageId(name, this.name, version, description); | 1365 new PackageId(name, this, version, description); |
| 1365 | 1366 |
| 1366 bool descriptionsEqual(description1, description2) => | 1367 bool descriptionsEqual(description1, description2) => |
| 1367 description1 == description2; | 1368 description1 == description2; |
| 1369 | |
| 1370 int hashDescription(description) => description.hashCode; | |
| 1368 } | 1371 } |
| 1369 | 1372 |
| 1370 class BoundMockSource extends CachedSource { | 1373 class BoundMockSource extends CachedSource { |
| 1371 final SystemCache systemCache; | 1374 final SystemCache systemCache; |
| 1372 | 1375 |
| 1373 final MockSource source; | 1376 final MockSource source; |
| 1374 | 1377 |
| 1375 final _packages = <String, Map<Version, Package>>{}; | 1378 final _packages = <String, Map<Version, Package>>{}; |
| 1376 | 1379 |
| 1377 /// Keeps track of which package version lists have been requested. Ensures | 1380 /// Keeps track of which package version lists have been requested. Ensures |
| (...skipping 18 matching lines...) Expand all Loading... | |
| 1396 } | 1399 } |
| 1397 | 1400 |
| 1398 _requestedVersions.add(ref.description); | 1401 _requestedVersions.add(ref.description); |
| 1399 | 1402 |
| 1400 if (!_packages.containsKey(ref.description)){ | 1403 if (!_packages.containsKey(ref.description)){ |
| 1401 throw new Exception('MockSource does not have a package matching ' | 1404 throw new Exception('MockSource does not have a package matching ' |
| 1402 '"${ref.description}".'); | 1405 '"${ref.description}".'); |
| 1403 } | 1406 } |
| 1404 | 1407 |
| 1405 return _packages[ref.description].values.map((package) { | 1408 return _packages[ref.description].values.map((package) { |
| 1406 return new PackageId( | 1409 return new PackageId(ref.name, source, package.version, ref.description); |
| 1407 ref.name, source.name, package.version, ref.description); | |
| 1408 }).toList(); | 1410 }).toList(); |
| 1409 } | 1411 } |
| 1410 | 1412 |
| 1411 Future<Pubspec> describeUncached(PackageId id) { | 1413 Future<Pubspec> describeUncached(PackageId id) { |
| 1412 return new Future.sync(() { | 1414 return new Future.sync(() { |
| 1413 // Make sure the solver doesn't request the same thing twice. | 1415 // Make sure the solver doesn't request the same thing twice. |
| 1414 if (_requestedPubspecs.containsKey(id.description) && | 1416 if (_requestedPubspecs.containsKey(id.description) && |
| 1415 _requestedPubspecs[id.description].contains(id.version)) { | 1417 _requestedPubspecs[id.description].contains(id.version)) { |
| 1416 throw new Exception('Pubspec for $id was already requested.'); | 1418 throw new Exception('Pubspec for $id was already requested.'); |
| 1417 } | 1419 } |
| (...skipping 13 matching lines...) Expand all Loading... | |
| 1431 | 1433 |
| 1432 Future<Pair<List<PackageId>, List<PackageId>>> repairCachedPackages() => | 1434 Future<Pair<List<PackageId>, List<PackageId>>> repairCachedPackages() => |
| 1433 throw new UnsupportedError('Cannot repair mock packages'); | 1435 throw new UnsupportedError('Cannot repair mock packages'); |
| 1434 | 1436 |
| 1435 void addPackage(String description, Package package) { | 1437 void addPackage(String description, Package package) { |
| 1436 _packages.putIfAbsent(description, () => new Map<Version, Package>()); | 1438 _packages.putIfAbsent(description, () => new Map<Version, Package>()); |
| 1437 _packages[description][package.version] = package; | 1439 _packages[description][package.version] = package; |
| 1438 } | 1440 } |
| 1439 } | 1441 } |
| 1440 | 1442 |
| 1441 Package mockPackage(PackageId id, Map dependencyStrings, Map overrides) { | 1443 Package mockPackage(SourceRegistry sources, PackageId id, Map dependencyStrings, |
| 1444 Map overrides) { | |
| 1442 var sdkConstraint = null; | 1445 var sdkConstraint = null; |
| 1443 | 1446 |
| 1444 // Build the pubspec dependencies. | 1447 // Build the pubspec dependencies. |
| 1445 var dependencies = <PackageDep>[]; | 1448 var dependencies = <PackageDep>[]; |
| 1446 var devDependencies = <PackageDep>[]; | 1449 var devDependencies = <PackageDep>[]; |
| 1447 | 1450 |
| 1448 dependencyStrings.forEach((spec, constraint) { | 1451 dependencyStrings.forEach((spec, constraint) { |
| 1449 var isDev = spec.startsWith("(dev) "); | 1452 var isDev = spec.startsWith("(dev) "); |
| 1450 if (isDev) { | 1453 if (isDev) { |
| 1451 spec = spec.substring("(dev) ".length); | 1454 spec = spec.substring("(dev) ".length); |
| 1452 } | 1455 } |
| 1453 | 1456 |
| 1454 var dep = parseSpec(spec).withConstraint( | 1457 var dep = parseSpec(sources, spec).withConstraint( |
| 1455 new VersionConstraint.parse(constraint)); | 1458 new VersionConstraint.parse(constraint)); |
| 1456 | 1459 |
| 1457 if (dep.name == 'sdk') { | 1460 if (dep.name == 'sdk') { |
| 1458 sdkConstraint = dep.constraint; | 1461 sdkConstraint = dep.constraint; |
| 1459 return; | 1462 return; |
| 1460 } | 1463 } |
| 1461 | 1464 |
| 1462 if (isDev) { | 1465 if (isDev) { |
| 1463 devDependencies.add(dep); | 1466 devDependencies.add(dep); |
| 1464 } else { | 1467 } else { |
| 1465 dependencies.add(dep); | 1468 dependencies.add(dep); |
| 1466 } | 1469 } |
| 1467 }); | 1470 }); |
| 1468 | 1471 |
| 1469 var dependencyOverrides = <PackageDep>[]; | 1472 var dependencyOverrides = <PackageDep>[]; |
| 1470 if (overrides != null) { | 1473 if (overrides != null) { |
| 1471 overrides.forEach((spec, constraint) { | 1474 overrides.forEach((spec, constraint) { |
| 1472 dependencyOverrides.add(parseSpec(spec).withConstraint( | 1475 dependencyOverrides.add(parseSpec(sources, spec) |
| 1473 new VersionConstraint.parse(constraint))); | 1476 .withConstraint(new VersionConstraint.parse(constraint))); |
| 1474 }); | 1477 }); |
| 1475 } | 1478 } |
| 1476 | 1479 |
| 1477 return new Package.inMemory(new Pubspec(id.name, | 1480 return new Package.inMemory(new Pubspec(id.name, |
| 1478 version: id.version, | 1481 version: id.version, |
| 1479 dependencies: dependencies, | 1482 dependencies: dependencies, |
| 1480 devDependencies: devDependencies, | 1483 devDependencies: devDependencies, |
| 1481 dependencyOverrides: dependencyOverrides, | 1484 dependencyOverrides: dependencyOverrides, |
| 1482 sdkConstraint: sdkConstraint)); | 1485 sdkConstraint: sdkConstraint)); |
| 1483 } | 1486 } |
| 1484 | 1487 |
| 1485 /// Creates a new [PackageId] parsed from [text], which looks something like | 1488 /// Creates a new [PackageId] parsed from [text], which looks something like |
| 1486 /// this: | 1489 /// this: |
| 1487 /// | 1490 /// |
| 1488 /// foo-xyz 1.0.0 from mock | 1491 /// foo-xyz 1.0.0 from mock |
| 1489 /// | 1492 /// |
| 1490 /// The package name is "foo". A hyphenated suffix like "-xyz" here is part | 1493 /// The package name is "foo". A hyphenated suffix like "-xyz" here is part |
| 1491 /// of the package description, but not its name, so the description here is | 1494 /// of the package description, but not its name, so the description here is |
| 1492 /// "foo-xyz". | 1495 /// "foo-xyz". |
| 1493 /// | 1496 /// |
| 1494 /// This is followed by an optional [Version]. If [version] is provided, then | 1497 /// This is followed by an optional [Version]. If [version] is provided, then |
| 1495 /// it is parsed to a [Version], and [text] should *not* also contain a | 1498 /// it is parsed to a [Version], and [text] should *not* also contain a |
| 1496 /// version string. | 1499 /// version string. |
| 1497 /// | 1500 /// |
| 1498 /// The "from mock" optional suffix is the name of a source for the package. | 1501 /// The "from mock" optional suffix is the name of a source for the package. |
| 1499 /// If omitted, it defaults to "mock1". | 1502 /// If omitted, it defaults to "mock1". |
| 1500 PackageId parseSpec(String text, [String version]) { | 1503 PackageId parseSpec(SourceRegistry sources, String text, [String version]) { |
| 1501 var pattern = new RegExp(r"(([a-z_]*)(-[a-z_]+)?)( ([^ ]+))?( from (.*))?$"); | 1504 var pattern = new RegExp(r"(([a-z_]*)(-[a-z_]+)?)( ([^ ]+))?( from (.*))?$"); |
| 1502 var match = pattern.firstMatch(text); | 1505 var match = pattern.firstMatch(text); |
| 1503 if (match == null) { | 1506 if (match == null) { |
| 1504 throw new FormatException("Could not parse spec '$text'."); | 1507 throw new FormatException("Could not parse spec '$text'."); |
| 1505 } | 1508 } |
| 1506 | 1509 |
| 1507 var description = match[1]; | 1510 var description = match[1]; |
| 1508 var name = match[2]; | 1511 var name = match[2]; |
| 1509 | 1512 |
| 1510 var parsedVersion; | 1513 var parsedVersion; |
| 1511 if (version != null) { | 1514 if (version != null) { |
| 1512 // Spec string shouldn't also contain a version. | 1515 // Spec string shouldn't also contain a version. |
| 1513 if (match[5] != null) { | 1516 if (match[5] != null) { |
| 1514 throw new ArgumentError("Spec '$text' should not contain a version " | 1517 throw new ArgumentError("Spec '$text' should not contain a version " |
| 1515 "since '$version' was passed in explicitly."); | 1518 "since '$version' was passed in explicitly."); |
| 1516 } | 1519 } |
| 1517 parsedVersion = new Version.parse(version); | 1520 parsedVersion = new Version.parse(version); |
| 1518 } else { | 1521 } else { |
| 1519 if (match[5] != null) { | 1522 if (match[5] != null) { |
| 1520 parsedVersion = new Version.parse(match[5]); | 1523 parsedVersion = new Version.parse(match[5]); |
| 1521 } else { | 1524 } else { |
| 1522 parsedVersion = Version.none; | 1525 parsedVersion = Version.none; |
| 1523 } | 1526 } |
| 1524 } | 1527 } |
| 1525 | 1528 |
| 1526 var source = "mock1"; | 1529 var source = sources["mock1"]; |
| 1527 if (match[7] != null) { | 1530 if (match[7] != null) source = match[7] == "root" ? null : sources[match[7]]; |
| 1528 source = match[7]; | |
| 1529 if (source == "root") source = null; | |
| 1530 } | |
| 1531 | 1531 |
| 1532 return new PackageId(name, source, parsedVersion, description); | 1532 return new PackageId(name, source, parsedVersion, description); |
| 1533 } | 1533 } |
| OLD | NEW |