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:io'; | 5 import 'dart:io'; |
6 | 6 |
7 import 'package:barback/barback.dart'; | 7 import 'package:barback/barback.dart'; |
8 import 'package:path/path.dart' as p; | 8 import 'package:path/path.dart' as p; |
9 import 'package:pub_semver/pub_semver.dart'; | 9 import 'package:pub_semver/pub_semver.dart'; |
10 | 10 |
11 import 'barback/transformer_id.dart'; | 11 import 'barback/transformer_id.dart'; |
12 import 'io.dart'; | 12 import 'io.dart'; |
13 import 'git.dart' as git; | 13 import 'git.dart' as git; |
14 import 'pubspec.dart'; | 14 import 'pubspec.dart'; |
15 import 'source_registry.dart'; | 15 import 'source_registry.dart'; |
| 16 import 'source.dart'; |
16 import 'utils.dart'; | 17 import 'utils.dart'; |
17 | 18 |
18 final _README_REGEXP = new RegExp(r"^README($|\.)", caseSensitive: false); | 19 final _README_REGEXP = new RegExp(r"^README($|\.)", caseSensitive: false); |
19 | 20 |
20 /// A named, versioned, unit of code and resource reuse. | 21 /// A named, versioned, unit of code and resource reuse. |
21 class Package { | 22 class Package { |
22 /// Compares [a] and [b] orders them by name then version number. | 23 /// Compares [a] and [b] orders them by name then version number. |
23 /// | 24 /// |
24 /// This is normally used as a [Comparator] to pass to sort. This does not | 25 /// This is normally used as a [Comparator] to pass to sort. This does not |
25 /// take a package's description or root directory into account, so multiple | 26 /// take a package's description or root directory into account, so multiple |
(...skipping 287 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
313 | 314 |
314 // Re-write the paths so they're underneath the symlink. | 315 // Re-write the paths so they're underneath the symlink. |
315 return targetFiles.map((targetFile) => | 316 return targetFiles.map((targetFile) => |
316 p.join(link, p.relative(targetFile, from: target))); | 317 p.join(link, p.relative(targetFile, from: target))); |
317 } | 318 } |
318 | 319 |
319 /// Returns a debug string for the package. | 320 /// Returns a debug string for the package. |
320 String toString() => '$name $version ($dir)'; | 321 String toString() => '$name $version ($dir)'; |
321 } | 322 } |
322 | 323 |
323 /// This is the private base class of [PackageRef], [PackageID], and | 324 /// The base class of [PackageRef], [PackageId], and [PackageDep]. |
324 /// [PackageDep]. | 325 abstract class PackageName { |
325 /// | |
326 /// It contains functionality and state that those classes share but is private | |
327 /// so that from outside of this library, there is no type relationship between | |
328 /// those three types. | |
329 class _PackageName { | |
330 _PackageName(this.name, this.source, this.description) | |
331 : isMagic = false; | |
332 | |
333 _PackageName.magic(this.name) | |
334 : source = null, | |
335 description = null, | |
336 isMagic = true; | |
337 | |
338 /// The name of the package being identified. | 326 /// The name of the package being identified. |
339 final String name; | 327 final String name; |
340 | 328 |
341 /// The name of the [Source] used to look up this package given its | 329 /// The [Source] used to look up this package. |
342 /// [description]. | |
343 /// | 330 /// |
344 /// If this is a root package, this will be `null`. | 331 /// If this is a root package, this will be `null`. |
345 final String source; | 332 final Source source; |
346 | 333 |
347 /// The metadata used by the package's [source] to identify and locate it. | 334 /// The metadata used by the package's [source] to identify and locate it. |
348 /// | 335 /// |
349 /// It contains whatever [Source]-specific data it needs to be able to get | 336 /// It contains whatever [Source]-specific data it needs to be able to get |
350 /// the package. For example, the description of a git sourced package might | 337 /// the package. For example, the description of a git sourced package might |
351 /// by the URL "git://github.com/dart/uilib.git". | 338 /// by the URL "git://github.com/dart/uilib.git". |
352 final description; | 339 final description; |
353 | 340 |
354 /// Whether this is a name for a magic package. | 341 /// Whether this is a name for a magic package. |
355 /// | 342 /// |
356 /// Magic packages are unversioned pub constructs that have special semantics. | 343 /// Magic packages are unversioned pub constructs that have special semantics. |
357 /// For example, a magic package named "pub itself" is inserted into the | 344 /// For example, a magic package named "pub itself" is inserted into the |
358 /// dependency graph when any package depends on barback. This packages has | 345 /// dependency graph when any package depends on barback. This packages has |
359 /// dependencies that represent the versions of barback and related packages | 346 /// dependencies that represent the versions of barback and related packages |
360 /// that pub is compatible with. | 347 /// that pub is compatible with. |
361 final bool isMagic; | 348 final bool isMagic; |
362 | 349 |
363 /// Whether this package is the root package. | 350 /// Whether this package is the root package. |
364 bool get isRoot => source == null && !isMagic; | 351 bool get isRoot => source == null && !isMagic; |
365 | 352 |
| 353 PackageName._(this.name, this.source, this.description) |
| 354 : isMagic = false; |
| 355 |
| 356 PackageName._magic(this.name) |
| 357 : source = null, |
| 358 description = null, |
| 359 isMagic = true; |
| 360 |
366 String toString() { | 361 String toString() { |
367 if (isRoot) return "$name (root)"; | 362 if (isRoot) return "$name (root)"; |
368 if (isMagic) return name; | 363 if (isMagic) return name; |
369 return "$name from $source"; | 364 return "$name from $source"; |
370 } | 365 } |
371 | 366 |
372 /// Returns a [PackageRef] with this one's [name], [source], and | 367 /// Returns a [PackageRef] with this one's [name], [source], and |
373 /// [description]. | 368 /// [description]. |
374 PackageRef toRef() => isMagic | 369 PackageRef toRef() => isMagic |
375 ? new PackageRef.magic(name) | 370 ? new PackageRef.magic(name) |
376 : new PackageRef(name, source, description); | 371 : new PackageRef(name, source, description); |
377 | 372 |
378 /// Returns a [PackageDep] for this package with the given version constraint. | 373 /// Returns a [PackageDep] for this package with the given version constraint. |
379 PackageDep withConstraint(VersionConstraint constraint) => | 374 PackageDep withConstraint(VersionConstraint constraint) => |
380 new PackageDep(name, source, constraint, description); | 375 new PackageDep(name, source, constraint, description); |
| 376 |
| 377 /// Returns whether this refers to the same package as [other]. |
| 378 /// |
| 379 /// This doesn't compare any constraint information; it's equivalent to |
| 380 /// `this.toRef() == other.toRef()`. |
| 381 bool samePackage(PackageName other) { |
| 382 if (other.name != name) return false; |
| 383 if (source == null) return other.source == null; |
| 384 |
| 385 return other.source == source && |
| 386 source.descriptionsEqual(description, other.description); |
| 387 } |
| 388 |
| 389 int get hashCode { |
| 390 if (source == null) return name.hashCode; |
| 391 return name.hashCode ^ |
| 392 source.hashCode ^ |
| 393 source.hashDescription(description); |
| 394 } |
381 } | 395 } |
382 | 396 |
383 /// A reference to a [Package], but not any particular version(s) of it. | 397 /// A reference to a [Package], but not any particular version(s) of it. |
384 class PackageRef extends _PackageName { | 398 class PackageRef extends PackageName { |
385 /// Creates a reference to a package with the given [name], [source], and | 399 /// Creates a reference to a package with the given [name], [source], and |
386 /// [description]. | 400 /// [description]. |
387 /// | 401 /// |
388 /// Since an ID's description is an implementation detail of its source, this | 402 /// Since an ID's description is an implementation detail of its source, this |
389 /// should generally not be called outside of [Source] subclasses. A reference | 403 /// should generally not be called outside of [Source] subclasses. A reference |
390 /// can be obtained from a user-supplied description using [Source.parseRef]. | 404 /// can be obtained from a user-supplied description using [Source.parseRef]. |
391 PackageRef(String name, String source, description) | 405 PackageRef(String name, Source source, description) |
392 : super(name, source, description); | 406 : super._(name, source, description); |
393 | 407 |
394 /// Creates a reference to a magic package (see [isMagic]). | 408 /// Creates a reference to a magic package (see [isMagic]). |
395 PackageRef.magic(String name) | 409 PackageRef.magic(String name) |
396 : super.magic(name); | 410 : super._magic(name); |
397 | 411 |
398 int get hashCode => name.hashCode ^ source.hashCode; | 412 bool operator ==(other) => other is PackageRef && samePackage(other); |
399 | |
400 bool operator ==(other) { | |
401 // TODO(rnystrom): We're assuming here that we don't need to delve into the | |
402 // description. | |
403 return other is PackageRef && | |
404 other.name == name && | |
405 other.source == source; | |
406 } | |
407 } | 413 } |
408 | 414 |
409 /// A reference to a specific version of a package. | 415 /// A reference to a specific version of a package. |
410 /// | 416 /// |
411 /// A package ID contains enough information to correctly get the package. | 417 /// A package ID contains enough information to correctly get the package. |
412 /// | 418 /// |
413 /// It's possible for multiple distinct package IDs to point to different | 419 /// It's possible for multiple distinct package IDs to point to different |
414 /// packages that have identical contents. For example, the same package may be | 420 /// packages that have identical contents. For example, the same package may be |
415 /// available from multiple sources. As far as Pub is concerned, those packages | 421 /// available from multiple sources. As far as Pub is concerned, those packages |
416 /// are different. | 422 /// are different. |
417 /// | 423 /// |
418 /// Note that a package ID's [description] field has a different structure than | 424 /// Note that a package ID's [description] field has a different structure than |
419 /// the [PackageRef.description] or [PackageDep.description] fields for some | 425 /// the [PackageRef.description] or [PackageDep.description] fields for some |
420 /// sources. For example, the `git` source adds revision information to the | 426 /// sources. For example, the `git` source adds revision information to the |
421 /// description to ensure that the same ID always points to the same source. | 427 /// description to ensure that the same ID always points to the same source. |
422 class PackageId extends _PackageName { | 428 class PackageId extends PackageName { |
423 /// The package's version. | 429 /// The package's version. |
424 final Version version; | 430 final Version version; |
425 | 431 |
426 /// Creates an ID for a package with the given [name], [source], [version], | 432 /// Creates an ID for a package with the given [name], [source], [version], |
427 /// and [description]. | 433 /// and [description]. |
428 /// | 434 /// |
429 /// Since an ID's description is an implementation detail of its source, this | 435 /// Since an ID's description is an implementation detail of its source, this |
430 /// should generally not be called outside of [Source] subclasses. | 436 /// should generally not be called outside of [Source] subclasses. |
431 PackageId(String name, String source, this.version, description) | 437 PackageId(String name, Source source, this.version, description) |
432 : super(name, source, description); | 438 : super._(name, source, description); |
433 | 439 |
434 /// Creates an ID for a magic package (see [isMagic]). | 440 /// Creates an ID for a magic package (see [isMagic]). |
435 PackageId.magic(String name) | 441 PackageId.magic(String name) |
436 : super.magic(name), | 442 : super._magic(name), |
437 version = Version.none; | 443 version = Version.none; |
438 | 444 |
439 /// Creates an ID for the given root package. | 445 /// Creates an ID for the given root package. |
440 PackageId.root(Package package) | 446 PackageId.root(Package package) |
441 : version = package.version, | 447 : version = package.version, |
442 super(package.name, null, package.name); | 448 super._(package.name, null, package.name); |
443 | 449 |
444 int get hashCode => name.hashCode ^ source.hashCode ^ version.hashCode; | 450 int get hashCode => super.hashCode ^ version.hashCode; |
445 | 451 |
446 bool operator ==(other) { | 452 bool operator ==(other) => |
447 // TODO(rnystrom): We're assuming here that we don't need to delve into the | 453 other is PackageId && samePackage(other) && other.version == version; |
448 // description. | |
449 return other is PackageId && | |
450 other.name == name && | |
451 other.source == source && | |
452 other.version == version; | |
453 } | |
454 | 454 |
455 String toString() { | 455 String toString() { |
456 if (isRoot) return "$name $version (root)"; | 456 if (isRoot) return "$name $version (root)"; |
457 if (isMagic) return name; | 457 if (isMagic) return name; |
458 return "$name $version from $source"; | 458 return "$name $version from $source"; |
459 } | 459 } |
460 } | 460 } |
461 | 461 |
462 /// A reference to a constrained range of versions of one package. | 462 /// A reference to a constrained range of versions of one package. |
463 class PackageDep extends _PackageName { | 463 class PackageDep extends PackageName { |
464 /// The allowed package versions. | 464 /// The allowed package versions. |
465 final VersionConstraint constraint; | 465 final VersionConstraint constraint; |
466 | 466 |
467 /// Creates a reference to package with the given [name], [source], | 467 /// Creates a reference to package with the given [name], [source], |
468 /// [constraint], and [description]. | 468 /// [constraint], and [description]. |
469 /// | 469 /// |
470 /// Since an ID's description is an implementation detail of its source, this | 470 /// Since an ID's description is an implementation detail of its source, this |
471 /// should generally not be called outside of [Source] subclasses. | 471 /// should generally not be called outside of [Source] subclasses. |
472 PackageDep(String name, String source, this.constraint, description) | 472 PackageDep(String name, Source source, this.constraint, description) |
473 : super(name, source, description); | 473 : super._(name, source, description); |
474 | 474 |
475 PackageDep.magic(String name) | 475 PackageDep.magic(String name) |
476 : super.magic(name), | 476 : super._magic(name), |
477 constraint = Version.none; | 477 constraint = Version.none; |
478 | 478 |
479 String toString() { | 479 String toString() { |
480 if (isRoot) return "$name $constraint (root)"; | 480 if (isRoot) return "$name $constraint (root)"; |
481 if (isMagic) return name; | 481 if (isMagic) return name; |
482 return "$name $constraint from $source ($description)"; | 482 return "$name $constraint from $source ($description)"; |
483 } | 483 } |
484 | 484 |
485 int get hashCode => name.hashCode ^ source.hashCode ^ constraint.hashCode; | 485 /// Whether [id] satisfies this dependency. |
| 486 /// |
| 487 /// Specifically, whether [id] refers to the same package as [this] *and* |
| 488 /// [constraint] allows `id.version`. |
| 489 bool allows(PackageId id) => |
| 490 samePackage(id) && constraint.allows(id.version); |
486 | 491 |
487 bool operator ==(other) { | 492 int get hashCode => super.hashCode ^ constraint.hashCode; |
488 // TODO(rnystrom): We're assuming here that we don't need to delve into the | 493 |
489 // description. | 494 bool operator ==(other) => |
490 return other is PackageDep && | 495 other is PackageDep && |
491 other.name == name && | 496 samePackage(other) && |
492 other.source == source && | 497 other.constraint == constraint; |
493 other.constraint == constraint; | |
494 } | |
495 } | 498 } |
OLD | NEW |