Skip to content

Commit

Permalink
Separate out VM dependencies.
Browse files Browse the repository at this point in the history
The Packages interface class should not depend on a platform specific
library (dart:io).
This removed the dependency, and also splits the implementation
classes into those that are generally applicable and those that
requite dart:io to operate (the "local packages directory" which
allows iterating the package names by scanning the directory).

Bump version to 0.0.2+4
  • Loading branch information
harryterkelsen authored and lrhn committed Jun 2, 2015
1 parent f77f208 commit 99afb4d
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 77 deletions.
1 change: 1 addition & 0 deletions lib/discovery.dart
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import "package:http/http.dart" as http;
import "packages.dart";
import "packages_file.dart" as pkgfile show parse;
import "src/packages_impl.dart";
import "src/packages_io_impl.dart";

/// Discover the package configuration for a Dart script.
///
Expand Down
38 changes: 0 additions & 38 deletions lib/packages.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

library package_config.packages;

import "dart:async" show Future;
import "discovery.dart" show findPackages;
import "src/packages_impl.dart";

/// A package resolution strategy.
Expand All @@ -26,42 +24,6 @@ abstract class Packages {
/// package resolution strategy is found.
static const Packages noPackages = const NoPackages();

/// Create a `Packages` object based on a map from package name to base URI.
///
/// The resulting `Packages` object will resolve package URIs by using this
/// map.
/// There is no validation of the map containing only valid package names,
factory Packages(Map<String, Uri> packageMapping) =>
new MapPackages(packageMapping);

/// Attempts to find a package resolution strategy for a Dart script.
///
/// The [baseLocation] should point to a Dart script or to its directory.
/// The function goes through the following steps in order to search for
/// a packages resolution strategy:
///
/// * First check if a `.packages` file in the script's directory.
/// If a file is found, its content is loaded and interpreted as a map
/// from package names to package location URIs.
/// If loading or parsing of the file fails, so does this function.
/// * Then if `baseLocation` is not a `file:` URI,
/// assume that a `packages/` directory exists in the script's directory,
/// and return a `Packages` object that resolves package URIs as
/// paths into that directory.
/// * If `baseLocation` is a `file:` URI, instead *check* whether
/// a `packages/` directory exists in the script directory.
/// If it does, return a `Packages` object that resolves package URIs
/// as paths into that directory. This `Packages` object is able to
/// read the directory and see which packages are available.
/// * Otherwise, check each directory in the parent path of `baseLocation`
/// for the existence of a `.packages` file. If one is found, it is loaded
/// just as in the first step.
/// * If no file is found before reaching the file system root,
/// the constant [noPackages] is returned. It's a `Packages` object
/// with no available packages.
///
static Future<Packages> find(Uri baseLocation) => findPackages(baseLocation);

/// Resolve a package URI into a non-package URI.
///
/// Translates a `package:` URI, according to the package resolution
Expand Down
47 changes: 10 additions & 37 deletions lib/src/packages_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
// 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.

/// Implementations of [Packages] that may be used in either server or browser
/// based applications. For implementations that can only run in the browser,
/// see [package_config.packages_io_impl].
library package_config.packages_impl;

import "dart:collection" show UnmodifiableMapView;
import "dart:io" show Directory;
import "package:path/path.dart" as path;
import "../packages.dart";
import "util.dart" show checkValidPackageUri;

Expand All @@ -26,16 +27,15 @@ class NoPackages implements Packages {
Map<String, Uri> asMap() => const<String,Uri>{};
}


/// Base class for [Packages] implementations.
///
/// This class implements the [resolve] method in terms of a private
/// member
abstract class _PackagesBase implements Packages {
abstract class PackagesBase implements Packages {
Uri resolve(Uri packageUri, {Uri notFound(Uri packageUri)}) {
packageUri = _normalizePath(packageUri);
String packageName = checkValidPackageUri(packageUri);
Uri packageBase = _getBase(packageName);
Uri packageBase = getBase(packageName);
if (packageBase == null) {
if (notFound != null) return notFound(packageUri);
throw new ArgumentError.value(packageUri, "packageUri",
Expand All @@ -49,61 +49,34 @@ abstract class _PackagesBase implements Packages {
///
/// Returns `null` if no package exists with that name, and that can be
/// determined.
Uri _getBase(String packageName);
Uri getBase(String packageName);

// TODO: inline to uri.normalizePath() when we move to 1.11
static Uri _normalizePath(Uri uri) => new Uri().resolveUri(uri);
}

/// A [Packages] implementation based on an existing map.
class MapPackages extends _PackagesBase {
class MapPackages extends PackagesBase {
final Map<String, Uri> _mapping;
MapPackages(this._mapping);

Uri _getBase(String packageName) => _mapping[packageName];
Uri getBase(String packageName) => _mapping[packageName];

Iterable<String> get packages => _mapping.keys;

Map<String, Uri> asMap() => new UnmodifiableMapView<String, Uri>(_mapping);
}

/// A [Packages] implementation based on a local directory.
class FilePackagesDirectoryPackages extends _PackagesBase {
final Directory _packageDir;
FilePackagesDirectoryPackages(this._packageDir);

Uri _getBase(String packageName) =>
new Uri.file(path.join(_packageDir.path, packageName, '.'));

Iterable<String> _listPackageNames() {
return _packageDir.listSync()
.where((e) => e is Directory)
.map((e) => path.basename(e.path));
}

Iterable<String> get packages {
return _listPackageNames();
}

Map<String, Uri> asMap() {
var result = <String, Uri>{};
for (var packageName in _listPackageNames()) {
result[packageName] = _getBase(packageName);
}
return new UnmodifiableMapView<String, Uri>(result);
}
}

/// A [Packages] implementation based on a remote (e.g., HTTP) directory.
///
/// There is no way to detect which packages exist short of trying to use
/// them. You can't necessarily check whether a directory exists,
/// except by checking for a know file in the directory.
class NonFilePackagesDirectoryPackages extends _PackagesBase {
class NonFilePackagesDirectoryPackages extends PackagesBase {
final Uri _packageBase;
NonFilePackagesDirectoryPackages(this._packageBase);

Uri _getBase(String packageName) => _packageBase.resolve("$packageName/");
Uri getBase(String packageName) => _packageBase.resolve("$packageName/");

Error _failListingPackages() {
return new UnsupportedError(
Expand Down
37 changes: 37 additions & 0 deletions lib/src/packages_io_impl.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
// 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.

/// Implementations of [Packages] that can only be used in server based
/// applications.
library package_config.packages_io_impl;

import "dart:collection" show UnmodifiableMapView;
import "dart:io" show Directory;
import "package:path/path.dart" as path;
import "packages_impl.dart";

/// A [Packages] implementation based on a local directory.
class FilePackagesDirectoryPackages extends PackagesBase {
final Directory _packageDir;
FilePackagesDirectoryPackages(this._packageDir);

Uri getBase(String packageName) =>
new Uri.file(path.join(_packageDir.path, packageName, '.'));

Iterable<String> _listPackageNames() {
return _packageDir.listSync()
.where((e) => e is Directory)
.map((e) => path.basename(e.path));
}

Iterable<String> get packages => _listPackageNames();

Map<String, Uri> asMap() {
var result = <String, Uri>{};
for (var packageName in _listPackageNames()) {
result[packageName] = getBase(packageName);
}
return new UnmodifiableMapView<String, Uri>(result);
}
}
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: package_config
version: 0.0.2+4
version: 0.0.3
description: Support for working with Package Resolution config files.
author: Dart Team <misc@dartlang.org>
homepage: https://github.com/dart-lang/package_config
Expand Down
3 changes: 2 additions & 1 deletion test/parse_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ library test_all;

import "package:package_config/packages.dart";
import "package:package_config/packages_file.dart" show parse;
import "package:package_config/src/packages_impl.dart";
import "package:test/test.dart";

main() {
Expand Down Expand Up @@ -123,7 +124,7 @@ main() {

Packages doParse(String sample, Uri baseUri) {
Map<String, Uri> map = parse(sample.codeUnits, baseUri);
return new Packages(map);
return new MapPackages(map);
}

// Valid samples.
Expand Down

0 comments on commit 99afb4d

Please sign in to comment.