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 library pub_update_test; | 5 library pub_update_test; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:io'; | 8 import 'dart:io'; |
| 9 | 9 |
| 10 import '../../../pkg/unittest/lib/unittest.dart'; | 10 import '../../../pkg/unittest/lib/unittest.dart'; |
| 11 | 11 |
| 12 import '../../pub/lock_file.dart'; | 12 import '../../pub/lock_file.dart'; |
| 13 import '../../pub/package.dart'; | 13 import '../../pub/package.dart'; |
| 14 import '../../pub/pubspec.dart'; | 14 import '../../pub/pubspec.dart'; |
| 15 import '../../pub/source.dart'; | 15 import '../../pub/source.dart'; |
| 16 import '../../pub/source_registry.dart'; | 16 import '../../pub/source_registry.dart'; |
| 17 import '../../pub/system_cache.dart'; | 17 import '../../pub/system_cache.dart'; |
| 18 import '../../pub/utils.dart'; | 18 import '../../pub/utils.dart'; |
| 19 import '../../pub/version.dart'; | 19 import '../../pub/version.dart'; |
| 20 import '../../pub/version_solver.dart'; | 20 import '../../pub/version_solver2.dart'; |
| 21 import 'test_pub.dart'; | 21 import 'test_pub.dart'; |
| 22 | 22 |
| 23 Matcher noVersion(List<String> packages) { | 23 Matcher noVersion(List<String> packages) { |
| 24 return predicate((x) { | 24 return predicate((x) { |
| 25 if (x is! NoVersionException) return false; | 25 if (x is! NoVersionException) return false; |
| 26 | 26 |
| 27 // Make sure the error string mentions the conflicting dependers. | 27 // Make sure the error string mentions the conflicting dependers. |
| 28 var message = x.toString(); | 28 var message = x.toString(); |
| 29 return packages.every((package) => message.contains(package)); | 29 return packages.every((package) => message.contains(package)); |
| 30 }, "is a NoVersionException"); | 30 }, "is a NoVersionException"); |
| (...skipping 14 matching lines...) Expand all Loading... | |
| 45 if (x is! DescriptionMismatchException) return false; | 45 if (x is! DescriptionMismatchException) return false; |
| 46 | 46 |
| 47 // Make sure the error string mentions the conflicting dependers. | 47 // Make sure the error string mentions the conflicting dependers. |
| 48 if (!x.toString().contains(package1)) return false; | 48 if (!x.toString().contains(package1)) return false; |
| 49 if (!x.toString().contains(package2)) return false; | 49 if (!x.toString().contains(package2)) return false; |
| 50 | 50 |
| 51 return true; | 51 return true; |
| 52 }, "is a DescriptionMismatchException"); | 52 }, "is a DescriptionMismatchException"); |
| 53 } | 53 } |
| 54 | 54 |
| 55 final couldNotSolve = predicate((x) => x is CouldNotSolveException, | 55 // If no solution can be found, the solver just reports the last failure that |
| 56 "is a CouldNotSolveException"); | 56 // happened during propagation. Since we don't specify the order that solutions |
| 57 // are tried, this just validates that *some* failure occurred, but not which. | |
| 58 final couldNotSolve = predicate((x) => x is SolverFailure, | |
| 59 "is a SolverFailure"); | |
| 57 | 60 |
| 58 Matcher sourceMismatch(String package1, String package2) { | 61 Matcher sourceMismatch(String package1, String package2) { |
| 59 return predicate((x) { | 62 return predicate((x) { |
| 60 if (x is! SourceMismatchException) return false; | 63 if (x is! SourceMismatchException) return false; |
| 61 | 64 |
| 62 // Make sure the error string mentions the conflicting dependers. | 65 // Make sure the error string mentions the conflicting dependers. |
| 63 if (!x.toString().contains(package1)) return false; | 66 if (!x.toString().contains(package1)) return false; |
| 64 if (!x.toString().contains(package2)) return false; | 67 if (!x.toString().contains(package2)) return false; |
| 65 | 68 |
| 66 return true; | 69 return true; |
| (...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 198 'bar 1.0.2': {}, | 201 'bar 1.0.2': {}, |
| 199 'baz 1.0.0': {} | 202 'baz 1.0.0': {} |
| 200 }, lockfile: { | 203 }, lockfile: { |
| 201 'baz': '1.0.0' | 204 'baz': '1.0.0' |
| 202 }, result: { | 205 }, result: { |
| 203 'myapp from root': '0.0.0', | 206 'myapp from root': '0.0.0', |
| 204 'foo': '1.0.2', | 207 'foo': '1.0.2', |
| 205 'bar': '1.0.2' | 208 'bar': '1.0.2' |
| 206 }); | 209 }); |
| 207 | 210 |
| 211 testResolve('unlocks dependencies if necessary to ensure that a new ' | |
| 212 'dependency is satisfied', { | |
|
Bob Nystrom
2013/03/26 22:07:56
This is copied from one of the integration tests,
| |
| 213 'myapp 0.0.0': { | |
| 214 'foo': 'any', | |
| 215 'newdep': 'any' | |
| 216 }, | |
| 217 'foo 1.0.0': { 'bar': '<2.0.0' }, | |
| 218 'bar 1.0.0': { 'baz': '<2.0.0' }, | |
| 219 'baz 1.0.0': { 'qux': '<2.0.0' }, | |
| 220 'qux 1.0.0': {}, | |
| 221 'foo 2.0.0': { 'bar': '<3.0.0' }, | |
| 222 'bar 2.0.0': { 'baz': '<3.0.0' }, | |
| 223 'baz 2.0.0': { 'qux': '<3.0.0' }, | |
| 224 'qux 2.0.0': {}, | |
| 225 'newdep 2.0.0': { 'baz': '>=1.5.0' } | |
| 226 }, lockfile: { | |
| 227 'foo': '1.0.0', | |
| 228 'bar': '1.0.0', | |
| 229 'baz': '1.0.0', | |
| 230 'qux': '1.0.0' | |
| 231 }, result: { | |
| 232 'myapp from root': '0.0.0', | |
| 233 'foo': '2.0.0', | |
| 234 'bar': '2.0.0', | |
| 235 'baz': '2.0.0', | |
| 236 'qux': '1.0.0', | |
| 237 'newdep': '2.0.0' | |
| 238 }); | |
| 239 | |
| 208 testResolve('circular dependency', { | 240 testResolve('circular dependency', { |
| 209 'myapp 1.0.0': { | 241 'myapp 1.0.0': { |
| 210 'foo': '1.0.0' | 242 'foo': '1.0.0' |
| 211 }, | 243 }, |
| 212 'foo 1.0.0': { | 244 'foo 1.0.0': { |
| 213 'bar': '1.0.0' | 245 'bar': '1.0.0' |
| 214 }, | 246 }, |
| 215 'bar 1.0.0': { | 247 'bar 1.0.0': { |
| 216 'foo': '1.0.0' | 248 'foo': '1.0.0' |
| 217 } | 249 } |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 258 } | 290 } |
| 259 }, error: sourceMismatch('foo', 'bar')); | 291 }, error: sourceMismatch('foo', 'bar')); |
| 260 | 292 |
| 261 testResolve('dependency back onto root package with wrong version', { | 293 testResolve('dependency back onto root package with wrong version', { |
| 262 'myapp 1.0.0': { | 294 'myapp 1.0.0': { |
| 263 'foo': '1.0.0' | 295 'foo': '1.0.0' |
| 264 }, | 296 }, |
| 265 'foo 1.0.0': { | 297 'foo 1.0.0': { |
| 266 'myapp': '<1.0.0' | 298 'myapp': '<1.0.0' |
| 267 } | 299 } |
| 268 }, error: disjointConstraint(['foo'])); | 300 }, error: noVersion(['foo'])); |
| 269 | 301 |
| 270 testResolve('no version that matches requirement', { | 302 testResolve('no version that matches requirement', { |
| 271 'myapp 0.0.0': { | 303 'myapp 0.0.0': { |
| 272 'foo': '>=1.0.0 <2.0.0' | 304 'foo': '>=1.0.0 <2.0.0' |
| 273 }, | 305 }, |
| 274 'foo 2.0.0': {}, | 306 'foo 2.0.0': {}, |
| 275 'foo 2.1.3': {} | 307 'foo 2.1.3': {} |
| 276 }, error: noVersion(['myapp'])); | 308 }, error: noVersion(['myapp'])); |
| 277 | 309 |
| 278 testResolve('no version that matches combined constraint', { | 310 testResolve('no version that matches combined constraint', { |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 328 'foo 1.0.0': { | 360 'foo 1.0.0': { |
| 329 'shared': '1.0.0' | 361 'shared': '1.0.0' |
| 330 }, | 362 }, |
| 331 'bar 1.0.0': { | 363 'bar 1.0.0': { |
| 332 'shared from mock2': '1.0.0' | 364 'shared from mock2': '1.0.0' |
| 333 }, | 365 }, |
| 334 'shared 1.0.0': {}, | 366 'shared 1.0.0': {}, |
| 335 'shared 1.0.0 from mock2': {} | 367 'shared 1.0.0 from mock2': {} |
| 336 }, error: sourceMismatch('foo', 'bar')); | 368 }, error: sourceMismatch('foo', 'bar')); |
| 337 | 369 |
| 338 testResolve('unstable dependency graph', { | 370 // This used to fail on the old solver because it requires downgrading an |
| 371 // earlier-selected dependency (a) in order to find a solution. | |
| 372 testResolve('circular dependency on older version', { | |
| 339 'myapp 0.0.0': { | 373 'myapp 0.0.0': { |
| 340 'a': '>=1.0.0' | 374 'a': '>=1.0.0' |
| 341 }, | 375 }, |
| 342 'a 1.0.0': {}, | 376 'a 1.0.0': {}, |
| 343 'a 2.0.0': { | 377 'a 2.0.0': { |
| 344 'b': '1.0.0' | 378 'b': '1.0.0' |
| 345 }, | 379 }, |
| 346 'b 1.0.0': { | 380 'b 1.0.0': { |
| 347 'a': '1.0.0' | 381 'a': '1.0.0' |
| 348 } | 382 } |
| 383 }, result: { | |
| 384 'myapp from root': '0.0.0', | |
| 385 'a': '1.0.0' | |
| 386 }); | |
| 387 | |
| 388 testResolve('unsolvable', { | |
| 389 'myapp 0.0.0': { | |
| 390 'a': 'any', | |
| 391 'b': 'any' | |
| 392 }, | |
| 393 'a 1.0.0': { | |
| 394 'b': '1.0.0' | |
| 395 }, | |
| 396 'a 2.0.0': { | |
| 397 'b': '2.0.0' | |
| 398 }, | |
| 399 'b 1.0.0': { | |
| 400 'a': '2.0.0' | |
| 401 }, | |
| 402 'b 2.0.0': { | |
| 403 'a': '1.0.0' | |
| 404 } | |
| 349 }, error: couldNotSolve); | 405 }, error: couldNotSolve); |
| 350 | 406 |
| 351 group('dev dependencies', () { | 407 group('dev dependencies', () { |
| 352 testResolve("includes root package's dev dependencies", { | 408 testResolve("includes root package's dev dependencies", { |
| 353 'myapp 1.0.0': { | 409 'myapp 1.0.0': { |
| 354 '(dev) foo': '1.0.0', | 410 '(dev) foo': '1.0.0', |
| 355 '(dev) bar': '1.0.0' | 411 '(dev) bar': '1.0.0' |
| 356 }, | 412 }, |
| 357 'foo 1.0.0': {}, | 413 'foo 1.0.0': {}, |
| 358 'bar 1.0.0': {} | 414 'bar 1.0.0': {} |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 382 }, | 438 }, |
| 383 'foo 1.0.0': { | 439 'foo 1.0.0': { |
| 384 '(dev) bar': '1.0.0' | 440 '(dev) bar': '1.0.0' |
| 385 }, | 441 }, |
| 386 'bar 1.0.0': {} | 442 'bar 1.0.0': {} |
| 387 }, result: { | 443 }, result: { |
| 388 'myapp from root': '1.0.0', | 444 'myapp from root': '1.0.0', |
| 389 'foo': '1.0.0' | 445 'foo': '1.0.0' |
| 390 }); | 446 }); |
| 391 }); | 447 }); |
| 448 | |
| 449 group('backtracking', () { | |
| 450 testResolve('simple backtracking', { | |
| 451 'myapp 0.0.0': { | |
| 452 'foo': 'any' | |
| 453 }, | |
| 454 'foo 1.0.0': { | |
| 455 'bar': '1.0.0' | |
| 456 }, | |
| 457 'foo 2.0.0': { | |
| 458 'bar': '2.0.0' | |
| 459 }, | |
| 460 'foo 3.0.0': { | |
| 461 'bar': '3.0.0' | |
| 462 }, | |
| 463 'bar 1.0.0': { | |
| 464 'baz': 'any' | |
| 465 }, | |
| 466 'bar 2.0.0': { | |
| 467 'baz': '2.0.0' | |
| 468 }, | |
| 469 'bar 3.0.0': { | |
| 470 'baz': '3.0.0' | |
| 471 }, | |
| 472 'baz 1.0.0': {} | |
| 473 }, result: { | |
| 474 'myapp from root': '0.0.0', | |
| 475 'foo': '1.0.0', | |
| 476 'bar': '1.0.0', | |
| 477 'baz': '1.0.0' | |
| 478 }); | |
| 479 | |
| 480 // Pathological example. | |
| 481 // TODO(bob): Document better. | |
| 482 var map = { | |
| 483 'myapp 0.0.0': { | |
| 484 'foo': 'any', | |
| 485 'bar': 'any' | |
| 486 }, | |
| 487 'baz 0.0.0': {} | |
| 488 }; | |
| 489 | |
| 490 for (var i = 0; i < 10; i++) { | |
| 491 for (var j = 0; j < 10; j++) { | |
| 492 map['foo $i.$j.0'] = {'baz': '$i.0.0'}; | |
| 493 map['bar $i.$j.0'] = {'baz': '0.$j.0'}; | |
| 494 } | |
| 495 } | |
| 496 | |
| 497 testResolve('nasty backtrack', map, result: { | |
| 498 'myapp from root': '0.0.0', | |
| 499 'foo': '0.9.0', | |
| 500 'bar': '9.0.0', | |
| 501 'baz': '0.0.0' | |
| 502 }); | |
| 503 // TODO(bob): More tests. | |
| 504 }); | |
| 392 } | 505 } |
| 393 | 506 |
| 394 // TODO(rnystrom): More stuff to test: | 507 // TODO(rnystrom): More stuff to test: |
| 395 // - Depending on a non-existent package. | 508 // - Depending on a non-existent package. |
| 396 // - Test that only a certain number requests are sent to the mock source so we | 509 // - Test that only a certain number requests are sent to the mock source so we |
| 397 // can keep track of server traffic. | 510 // can keep track of server traffic. |
| 398 | 511 |
| 512 /* | |
| 513 // TODO(bob): Remove! | |
| 514 no_testResolve(description, packages, {lockfile, result, Matcher error}) { | |
| 515 // Do nothing. | |
| 516 print('\u001b[33m-\u001b[0m $description'); | |
| 517 } | |
| 518 */ | |
| 519 | |
| 520 solo_testResolve(description, packages, {lockfile, result, Matcher error}) { | |
| 521 _testResolve(solo_test, description, packages, | |
| 522 lockfile: lockfile, result: result, error: error); | |
| 523 } | |
| 524 | |
| 399 testResolve(description, packages, {lockfile, result, Matcher error}) { | 525 testResolve(description, packages, {lockfile, result, Matcher error}) { |
| 400 test(description, () { | 526 _testResolve(test, description, packages, |
| 527 lockfile: lockfile, result: result, error: error); | |
| 528 } | |
| 529 | |
| 530 _testResolve(testFn, description, packages, {lockfile, result, Matcher error}) { | |
| 531 testFn(description, () { | |
| 401 var cache = new SystemCache('.'); | 532 var cache = new SystemCache('.'); |
| 402 source1 = new MockSource('mock1'); | 533 source1 = new MockSource('mock1'); |
| 403 source2 = new MockSource('mock2'); | 534 source2 = new MockSource('mock2'); |
| 404 cache.register(source1); | 535 cache.register(source1); |
| 405 cache.register(source2); | 536 cache.register(source2); |
| 406 cache.sources.setDefault(source1.name); | 537 cache.sources.setDefault(source1.name); |
| 407 | 538 |
| 408 // Build the test package graph. | 539 // Build the test package graph. |
| 409 var root; | 540 var root; |
| 410 packages.forEach((nameVersion, dependencies) { | 541 packages.forEach((nameVersion, dependencies) { |
| 411 var parsed = parseSource(nameVersion, (isDev, nameVersion, source) { | 542 var parsed = parseSource(nameVersion, (isDev, nameVersion, source) { |
| 412 var parts = nameVersion.split(' '); | 543 var parts = nameVersion.split(' '); |
| 413 var name = parts[0]; | 544 var name = parts[0]; |
| 414 var version = parts[1]; | 545 var version = parts[1]; |
| 415 | 546 |
| 416 var package = source1.mockPackage(name, version, dependencies); | 547 var package = mockPackage(name, version, dependencies); |
| 417 if (name == 'myapp') { | 548 if (name == 'myapp') { |
| 418 // Don't add the root package to the server, so we can verify that Pub | 549 // Don't add the root package to the server, so we can verify that Pub |
| 419 // doesn't try to look up information about the local package on the | 550 // doesn't try to look up information about the local package on the |
| 420 // remote server. | 551 // remote server. |
| 421 root = package; | 552 root = package; |
| 422 } else { | 553 } else { |
| 423 source.addPackage(package); | 554 source.addPackage(name, package); |
| 424 } | 555 } |
| 425 }); | 556 }); |
| 426 }); | 557 }); |
| 427 | 558 |
| 428 // Clean up the expectation. | 559 // Clean up the expectation. |
| 429 if (result != null) { | 560 if (result != null) { |
| 430 var newResult = {}; | 561 var newResult = {}; |
| 431 result.forEach((name, version) { | 562 result.forEach((name, version) { |
| 432 parseSource(name, (isDev, name, source) { | 563 parseSource(name, (isDev, name, source) { |
| 433 version = new Version.parse(version); | 564 version = new Version.parse(version); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 465 } | 596 } |
| 466 | 597 |
| 467 /// A source used for testing. This both creates mock package objects and acts | 598 /// A source used for testing. This both creates mock package objects and acts |
| 468 /// as a source for them. | 599 /// as a source for them. |
| 469 /// | 600 /// |
| 470 /// In order to support testing packages that have the same name but different | 601 /// In order to support testing packages that have the same name but different |
| 471 /// descriptions, a package's name is calculated by taking the description | 602 /// descriptions, a package's name is calculated by taking the description |
| 472 /// string and stripping off any trailing hyphen followed by non-hyphen | 603 /// string and stripping off any trailing hyphen followed by non-hyphen |
| 473 /// characters. | 604 /// characters. |
| 474 class MockSource extends Source { | 605 class MockSource extends Source { |
| 475 final Map<String, Map<Version, Package>> _packages; | 606 final _packages = <String, Map<Version, Package>>{}; |
| 607 | |
| 608 /// Keeps track of which package version lists have been requested. Ensures | |
| 609 /// that a source is only hit once for a given package and that pub | |
| 610 /// internally caches the results. | |
| 611 final _requestedVersions = new Set<String>(); | |
| 612 | |
| 613 /// Keeps track of which package pubspecs have been requested. Ensures that a | |
| 614 /// source is only hit once for a given package and that pub internally | |
| 615 /// caches the results. | |
| 616 final _requestedPubspecs = new Map<String, Set<Version>>(); | |
| 476 | 617 |
| 477 final String name; | 618 final String name; |
| 478 bool get shouldCache => true; | 619 bool get shouldCache => true; |
| 479 | 620 |
| 480 MockSource(this.name) | 621 MockSource(this.name); |
| 481 : _packages = <String, Map<Version, Package>>{}; | |
| 482 | 622 |
| 483 Future<List<Version>> getVersions(String name, String description) { | 623 Future<List<Version>> getVersions(String name, String description) { |
| 484 return defer(() => _packages[description].keys.toList()); | 624 return defer(() { |
| 625 // Make sure the solver doesn't request the same thing twice. | |
| 626 if (_requestedVersions.contains(description)) { | |
| 627 throw 'Version list for $description was already requested.'; | |
| 628 } | |
| 629 | |
| 630 _requestedVersions.add(description); | |
| 631 | |
| 632 if (!_packages.containsKey(description)){ | |
| 633 throw 'MockSource does not have a package matching "$description".'; | |
| 634 } | |
| 635 return _packages[description].keys.toList(); | |
| 636 }); | |
| 485 } | 637 } |
| 486 | 638 |
| 487 Future<Pubspec> describe(PackageId id) { | 639 Future<Pubspec> describe(PackageId id) { |
| 488 return defer(() { | 640 return defer(() { |
| 489 return _packages[id.name][id.version].pubspec; | 641 // Make sure the solver doesn't request the same thing twice. |
| 642 if (_requestedPubspecs.containsKey(id.description) && | |
| 643 _requestedPubspecs[id.description].contains(id.version)) { | |
| 644 throw 'Pubspec for $id was already requested.'; | |
| 645 } | |
| 646 | |
| 647 _requestedPubspecs.putIfAbsent(id.description, () => new Set<Version>()); | |
| 648 _requestedPubspecs[id.description].add(id.version); | |
| 649 | |
| 650 return _packages[id.description][id.version].pubspec; | |
| 490 }); | 651 }); |
| 491 } | 652 } |
| 492 | 653 |
| 493 Future<bool> install(PackageId id, String path) { | 654 Future<bool> install(PackageId id, String path) { |
| 494 throw 'no'; | 655 throw 'no'; |
| 495 } | 656 } |
| 496 | 657 |
| 497 Package mockPackage(String description, String version, | 658 void addPackage(String description, Package package) { |
| 498 Map dependencyStrings) { | 659 _packages.putIfAbsent(description, () => new Map<Version, Package>()); |
| 499 // Build the pubspec dependencies. | 660 _packages[description][package.version] = package; |
| 500 var dependencies = <PackageRef>[]; | |
| 501 var devDependencies = <PackageRef>[]; | |
| 502 | |
| 503 dependencyStrings.forEach((name, constraint) { | |
| 504 parseSource(name, (isDev, name, source) { | |
| 505 var packageName = name.replaceFirst(new RegExp(r"-[^-]+$"), ""); | |
| 506 var ref = new PackageRef(packageName, source, | |
| 507 new VersionConstraint.parse(constraint), name); | |
| 508 | |
| 509 if (isDev) { | |
| 510 devDependencies.add(ref); | |
| 511 } else { | |
| 512 dependencies.add(ref); | |
| 513 } | |
| 514 }); | |
| 515 }); | |
| 516 | |
| 517 var pubspec = new Pubspec( | |
| 518 description, new Version.parse(version), dependencies, devDependencies, | |
| 519 new PubspecEnvironment()); | |
| 520 return new Package.inMemory(pubspec); | |
| 521 } | |
| 522 | |
| 523 void addPackage(Package package) { | |
| 524 _packages.putIfAbsent(package.name, () => new Map<Version, Package>()); | |
| 525 _packages[package.name][package.version] = package; | |
| 526 } | 661 } |
| 527 } | 662 } |
| 528 | 663 |
| 664 Package mockPackage(String description, String version, | |
| 665 Map dependencyStrings) { | |
| 666 // Build the pubspec dependencies. | |
| 667 var dependencies = <PackageRef>[]; | |
| 668 var devDependencies = <PackageRef>[]; | |
| 669 | |
| 670 dependencyStrings.forEach((name, constraint) { | |
| 671 parseSource(name, (isDev, name, source) { | |
| 672 var packageName = name.replaceFirst(new RegExp(r"-[^-]+$"), ""); | |
| 673 var ref = new PackageRef(packageName, source, | |
| 674 new VersionConstraint.parse(constraint), name); | |
| 675 | |
| 676 if (isDev) { | |
| 677 devDependencies.add(ref); | |
| 678 } else { | |
| 679 dependencies.add(ref); | |
| 680 } | |
| 681 }); | |
| 682 }); | |
| 683 | |
| 684 var name = description.replaceFirst(new RegExp(r"-[^-]+$"), ""); | |
| 685 var pubspec = new Pubspec( | |
| 686 name, new Version.parse(version), dependencies, devDependencies, | |
| 687 new PubspecEnvironment()); | |
| 688 return new Package.inMemory(pubspec); | |
| 689 } | |
| 690 | |
| 529 void parseSource(String description, | 691 void parseSource(String description, |
| 530 callback(bool isDev, String name, Source source)) { | 692 callback(bool isDev, String name, Source source)) { |
| 531 var isDev = false; | 693 var isDev = false; |
| 532 | 694 |
| 533 if (description.startsWith("(dev) ")) { | 695 if (description.startsWith("(dev) ")) { |
| 534 description = description.substring("(dev) ".length); | 696 description = description.substring("(dev) ".length); |
| 535 isDev = true; | 697 isDev = true; |
| 536 } | 698 } |
| 537 | 699 |
| 538 var name = description; | 700 var name = description; |
| 539 var source = source1; | 701 var source = source1; |
| 540 | 702 |
| 541 var sourceNames = { | 703 var sourceNames = { |
| 542 'mock1': source1, | 704 'mock1': source1, |
| 543 'mock2': source2, | 705 'mock2': source2, |
| 544 'root': null | 706 'root': null |
| 545 }; | 707 }; |
| 546 | 708 |
| 547 var match = new RegExp(r"(.*) from (.*)").firstMatch(description); | 709 var match = new RegExp(r"(.*) from (.*)").firstMatch(description); |
| 548 if (match != null) { | 710 if (match != null) { |
| 549 name = match[1]; | 711 name = match[1]; |
| 550 source = sourceNames[match[2]]; | 712 source = sourceNames[match[2]]; |
| 551 } | 713 } |
| 552 | 714 |
| 553 callback(isDev, name, source); | 715 callback(isDev, name, source); |
| 554 } | 716 } |
| OLD | NEW |