Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(900)

Unified Diff: lib/discovery.dart

Issue 1142363005: Added .packages, packages/ discovery. (Closed) Base URL: https://github.com/dart-lang/package_config.git@master
Patch Set: Addressed comments. Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | lib/packagemap.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/discovery.dart
diff --git a/lib/discovery.dart b/lib/discovery.dart
new file mode 100644
index 0000000000000000000000000000000000000000..78254eeba4151975f01aa3c6a8c9f58a50f16a47
--- /dev/null
+++ b/lib/discovery.dart
@@ -0,0 +1,160 @@
+// 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.
+
+library package_config.discovery;
+
+import "dart:async";
+import "dart:io" show Directory, File, FileSystemEntity;
+import "package:path/path.dart" as path;
+import "package:http/http.dart" as http;
+import "packages.dart";
+import "packages_file.dart" as pkgfile show parse;
+import "src/packages_impl.dart";
+
+/// Discover the package configuration for a Dart script.
+///
+/// The [baseUri] points to either the Dart script or its directory.
+/// A package resolution strategy is found by going through the following steps,
+/// and stopping when something is found.
+///
+/// * Check if a `.packages` file exists in the same directory.
+/// * If `baseUri`'s scheme is not `file`, then assume a `packages` directory
+/// in the same directory, and resolve packages relative to that.
+/// * If `baseUri`'s scheme *is* `file`:
+/// * Check if a `packages` directory exists.
+/// * Otherwise check each successive parent directory of `baseUri` for a
+/// `.packages` file.
+///
+/// If any of these tests succeed, a `Packages` class is returned.
+/// Returns the constant [noPackages] if no resolution strategy is found.
+///
+/// This function currently only supports `file`, `http` and `https` URIs.
+/// It needs to be able to load a `.packages` file from the URI, so only
+/// recognized schemes are accepted.
+///
+/// To support other schemes, an optional [loader] function can be supplied.
+/// It's called to load the `.packages` file for any unsupported scheme.
+/// It must return the *contents* of the file identified by the URI it's given,
+/// which should be a UTF-8 encoded `.packages` file, and must return an
+/// error future if loading fails for any reason.
+Future<Packages> findPackages(
+ Uri baseUri,
+ {Future<List<int>> loader(Uri unsupportedUri)}) {
+ if (baseUri.scheme == "file") {
+ return new Future<Packages>.sync(() => findPackagesFromFile(baseUri));
+ } else if (baseUri.scheme == "http" || baseUri.scheme == "https") {
+ return findPackagesFromNonFile(baseUri, _httpGet);
+ } else if (loader != null) {
+ return findPackagesFromNonFile(baseUri, loader);
+ } else {
+ return new Future<Packages>.value(Packages.noPackages);
+ }
+}
+
+/// Find the location of the package resolution file/directory for a Dart file.
+///
+/// Checks for a `.packages` file in the [workingDirectory].
+/// If not found, checks for a `packages` directory in the same directory.
+/// If still not found, starts checking parent directories for
+/// `.packages` until reaching the root directory.
+///
+/// Returns a [File] object of a `.packages` file if one is found, or a
+/// [Directory] object for the `packages/` directory if that is found.
+FileSystemEntity _findPackagesFile(String workingDirectory) {
+ var dir = new Directory(workingDirectory);
+ if (!dir.isAbsolute) dir = dir.absolute;
+ if (!dir.existsSync()) {
+ throw new ArgumentError.value(
+ workingDirectory, "workingDirectory", "Directory does not exist.");
+ }
+ File checkForConfigFile(Directory directory) {
+ assert(directory.isAbsolute);
+ var file = new File(path.join(directory.path, ".packages"));
+ if (file.existsSync()) return file;
+ return null;
+ }
+ // Check for $cwd/.packages
+ var packagesCfgFile = checkForConfigFile(dir);
+ if (packagesCfgFile != null) return packagesCfgFile;
+ // Check for $cwd/packages/
+ var packagesDir = new Directory(path.join(dir.path, "packages"));
+ if (packagesDir.existsSync()) return packagesDir;
+ // Check for cwd(/..)+/.packages
+ var parentDir = dir.parent;
+ while (parentDir.path != dir.path) {
+ packagesCfgFile = checkForConfigFile(parentDir);
+ if (packagesCfgFile != null) break;
+ dir = parentDir;
+ parentDir = dir.parent;
+ }
+ return packagesCfgFile;
+}
+
+/// Finds a package resolution strategy for a local Dart script.
+///
+/// The [fileBaseUri] points to either a Dart script or the directory of the
+/// script. The `fileBaseUri` must be a `file:` URI.
+///
+/// This function first tries to locate a `.packages` file in the `fileBaseUri`
+/// directory. If that is not found, it instead checks for the presence of
+/// a `packages/` directory in the same place.
+/// If that also fails, it starts checking parent directories for a `.packages`
+/// file, and stops if it finds it.
+/// Otherwise it gives up and returns [Pacakges.noPackages].
+Packages findPackagesFromFile(Uri fileBaseUri) {
+ Uri baseDirectoryUri = fileBaseUri;
+ if (!fileBaseUri.path.endsWith('/')) {
+ baseDirectoryUri = baseDirectoryUri.resolve(".");
+ }
+ String baseDirectoryPath = baseDirectoryUri.toFilePath();
+ FileSystemEntity location = _findPackagesFile(baseDirectoryPath);
+ if (location == null) return Packages.noPackages;
+ if (location is File) {
+ List<int> fileBytes = location.readAsBytesSync();
+ Map<String, Uri> map = pkgfile.parse(fileBytes,
+ new Uri.file(location.path));
+ return new MapPackages(map);
+ }
+ assert(location is Directory);
+ return new FilePackagesDirectoryPackages(location);
+}
+
+/// Finds a package resolution strategy for a Dart script.
+///
+/// The [nonFileUri] points to either a Dart script or the directory of the
+/// script.
+/// The [nonFileUri] should not be a `file:` URI since the algorithm for
+/// finding a package resolution strategy is more elaborate for `file:` URIs.
+/// In that case, use [findPackagesFile].
+///
+/// This function first tries to locate a `.packages` file in the [nonFileUri]
+/// directory. If that is not found, it instead assumes a `packages/` directory
+/// in the same place.
+///
+/// By default, this function only works for `http:` and `https:` URIs.
+/// To support other schemes, a loader must be provided, which is used to
+/// try to load the `.packages` file. The loader should return the contents
+/// of the requestsed `.packages` file as bytes, which will be assumed to be
+/// UTF-8 encoded.
+Future<Packages> findPackagesFromNonFile(Uri nonFileUri,
+ [Future<List<int>> loader(Uri name)]) {
+ if (loader == null) loader = _httpGet;
+ Uri packagesFileUri = nonFileUri.resolve(".packages");
+ return loader(packagesFileUri).then((List<int> fileBytes) {
+ Map<String, Uri> map = pkgfile.parse(fileBytes, packagesFileUri);
+ return new MapPackages(map);
+ }, onError: (_) {
+ // Didn't manage to load ".packages". Assume a "packages/" directory.
+ Uri packagesDirectoryUri = nonFileUri.resolve("packages/");
+ return new NonFilePackagesDirectoryPackages(packagesDirectoryUri);
+ });
+}
+
+/// Fetches a file using the http library.
+Future<List<int>> _httpGet(Uri uri) {
+ return http.get(uri).then((http.Response response) {
+ if (response.statusCode == 200) return response.bodyBytes;
+ throw 0; // The error message isn't being used for anything.
+ });
+}
« no previous file with comments | « no previous file | lib/packagemap.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698