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

Side by Side Diff: package_config/lib/discovery.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 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 unified diff | Download patch
« no previous file with comments | « observe/pubspec.yaml ('k') | package_config/lib/discovery_analysis.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
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.
4
5 library package_config.discovery;
6
7 import "dart:async";
8 import "dart:io";
9 import "dart:typed_data" show Uint8List;
10
11 import "package:path/path.dart" as path;
12
13 import "packages.dart";
14 import "packages_file.dart" as pkgfile show parse;
15 import "src/packages_impl.dart";
16 import "src/packages_io_impl.dart";
17
18 /// Reads a package resolution file and creates a [Packages] object from it.
19 ///
20 /// The [packagesFile] must exist and be loadable.
21 /// Currently that means the URI must have a `file`, `http` or `https` scheme,
22 /// and that the file can be loaded and its contents parsed correctly.
23 ///
24 /// If the [loader] is provided, it is used to fetch non-`file` URIs, and
25 /// it can support other schemes or set up more complex HTTP requests.
26 ///
27 /// This function can be used to load an explicitly configured package
28 /// resolution file, for example one specified using a `--packages`
29 /// command-line parameter.
30 Future<Packages> loadPackagesFile(Uri packagesFile,
31 {Future<List<int>> loader(Uri uri)}) {
32 Packages parseBytes(List<int> bytes) {
33 Map<String, Uri> packageMap = pkgfile.parse(bytes, packagesFile);
34 return new MapPackages(packageMap);
35 }
36 if (packagesFile.scheme == "file") {
37 File file = new File.fromUri(packagesFile);
38 return file.readAsBytes().then(parseBytes);
39 }
40 if (loader == null) {
41 return _httpGet(packagesFile).then(parseBytes);
42 }
43 return loader(packagesFile).then(parseBytes);
44 }
45
46
47 /// Create a [Packages] object for a package directory.
48 ///
49 /// The [packagesDir] URI should refer to a directory.
50 /// Package names are resolved as relative to sub-directories of the
51 /// package directory.
52 ///
53 /// This function can be used for explicitly configured package directories,
54 /// for example one specified using a `--package-root` comand-line parameter.
55 Packages getPackagesDirectory(Uri packagesDir) {
56 if (packagesDir.scheme == "file") {
57 Directory directory = new Directory.fromUri(packagesDir);
58 return new FilePackagesDirectoryPackages(directory);
59 }
60 if (!packagesDir.path.endsWith('/')) {
61 packagesDir = packagesDir.replace(path: packagesDir.path + '/');
62 }
63 return new NonFilePackagesDirectoryPackages(packagesDir);
64 }
65
66
67 /// Discover the package configuration for a Dart script.
68 ///
69 /// The [baseUri] points to either the Dart script or its directory.
70 /// A package resolution strategy is found by going through the following steps,
71 /// and stopping when something is found.
72 ///
73 /// * Check if a `.packages` file exists in the same directory.
74 /// * If `baseUri`'s scheme is not `file`, then assume a `packages` directory
75 /// in the same directory, and resolve packages relative to that.
76 /// * If `baseUri`'s scheme *is* `file`:
77 /// * Check if a `packages` directory exists.
78 /// * Otherwise check each successive parent directory of `baseUri` for a
79 /// `.packages` file.
80 ///
81 /// If any of these tests succeed, a `Packages` class is returned.
82 /// Returns the constant [noPackages] if no resolution strategy is found.
83 ///
84 /// This function currently only supports `file`, `http` and `https` URIs.
85 /// It needs to be able to load a `.packages` file from the URI, so only
86 /// recognized schemes are accepted.
87 ///
88 /// To support other schemes, or more complex HTTP requests,
89 /// an optional [loader] function can be supplied.
90 /// It's called to load the `.packages` file for a non-`file` scheme.
91 /// The loader function returns the *contents* of the file
92 /// identified by the URI it's given.
93 /// The content should be a UTF-8 encoded `.packages` file, and must return an
94 /// error future if loading fails for any reason.
95 Future<Packages> findPackages(Uri baseUri,
96 {Future<List<int>> loader(Uri unsupportedUri)}) {
97 if (baseUri.scheme == "file") {
98 return new Future<Packages>.sync(() => findPackagesFromFile(baseUri));
99 } else if (loader != null) {
100 return findPackagesFromNonFile(baseUri, loader: loader);
101 } else if (baseUri.scheme == "http" || baseUri.scheme == "https") {
102 return findPackagesFromNonFile(baseUri, loader: _httpGet);
103 } else {
104 return new Future<Packages>.value(Packages.noPackages);
105 }
106 }
107
108 /// Find the location of the package resolution file/directory for a Dart file.
109 ///
110 /// Checks for a `.packages` file in the [workingDirectory].
111 /// If not found, checks for a `packages` directory in the same directory.
112 /// If still not found, starts checking parent directories for
113 /// `.packages` until reaching the root directory.
114 ///
115 /// Returns a [File] object of a `.packages` file if one is found, or a
116 /// [Directory] object for the `packages/` directory if that is found.
117 FileSystemEntity _findPackagesFile(String workingDirectory) {
118 var dir = new Directory(workingDirectory);
119 if (!dir.isAbsolute) dir = dir.absolute;
120 if (!dir.existsSync()) {
121 throw new ArgumentError.value(
122 workingDirectory, "workingDirectory", "Directory does not exist.");
123 }
124 File checkForConfigFile(Directory directory) {
125 assert(directory.isAbsolute);
126 var file = new File(path.join(directory.path, ".packages"));
127 if (file.existsSync()) return file;
128 return null;
129 }
130 // Check for $cwd/.packages
131 var packagesCfgFile = checkForConfigFile(dir);
132 if (packagesCfgFile != null) return packagesCfgFile;
133 // Check for $cwd/packages/
134 var packagesDir = new Directory(path.join(dir.path, "packages"));
135 if (packagesDir.existsSync()) return packagesDir;
136 // Check for cwd(/..)+/.packages
137 var parentDir = dir.parent;
138 while (parentDir.path != dir.path) {
139 packagesCfgFile = checkForConfigFile(parentDir);
140 if (packagesCfgFile != null) break;
141 dir = parentDir;
142 parentDir = dir.parent;
143 }
144 return packagesCfgFile;
145 }
146
147 /// Finds a package resolution strategy for a local Dart script.
148 ///
149 /// The [fileBaseUri] points to either a Dart script or the directory of the
150 /// script. The `fileBaseUri` must be a `file:` URI.
151 ///
152 /// This function first tries to locate a `.packages` file in the `fileBaseUri`
153 /// directory. If that is not found, it instead checks for the presence of
154 /// a `packages/` directory in the same place.
155 /// If that also fails, it starts checking parent directories for a `.packages`
156 /// file, and stops if it finds it.
157 /// Otherwise it gives up and returns [Packages.noPackages].
158 Packages findPackagesFromFile(Uri fileBaseUri) {
159 Uri baseDirectoryUri = fileBaseUri;
160 if (!fileBaseUri.path.endsWith('/')) {
161 baseDirectoryUri = baseDirectoryUri.resolve(".");
162 }
163 String baseDirectoryPath = baseDirectoryUri.toFilePath();
164 FileSystemEntity location = _findPackagesFile(baseDirectoryPath);
165 if (location == null) return Packages.noPackages;
166 if (location is File) {
167 List<int> fileBytes = location.readAsBytesSync();
168 Map<String, Uri> map =
169 pkgfile.parse(fileBytes, new Uri.file(location.path));
170 return new MapPackages(map);
171 }
172 assert(location is Directory);
173 return new FilePackagesDirectoryPackages(location);
174 }
175
176 /// Finds a package resolution strategy for a Dart script.
177 ///
178 /// The [nonFileUri] points to either a Dart script or the directory of the
179 /// script.
180 /// The [nonFileUri] should not be a `file:` URI since the algorithm for
181 /// finding a package resolution strategy is more elaborate for `file:` URIs.
182 /// In that case, use [findPackagesFromFile].
183 ///
184 /// This function first tries to locate a `.packages` file in the [nonFileUri]
185 /// directory. If that is not found, it instead assumes a `packages/` directory
186 /// in the same place.
187 ///
188 /// By default, this function only works for `http:` and `https:` URIs.
189 /// To support other schemes, a loader must be provided, which is used to
190 /// try to load the `.packages` file. The loader should return the contents
191 /// of the requested `.packages` file as bytes, which will be assumed to be
192 /// UTF-8 encoded.
193 Future<Packages> findPackagesFromNonFile(Uri nonFileUri,
194 {Future<List<int>> loader(Uri name)}) {
195 if (loader == null) loader = _httpGet;
196 Uri packagesFileUri = nonFileUri.resolve(".packages");
197 return loader(packagesFileUri).then((List<int> fileBytes) {
198 Map<String, Uri> map = pkgfile.parse(fileBytes, packagesFileUri);
199 return new MapPackages(map);
200 }, onError: (_) {
201 // Didn't manage to load ".packages". Assume a "packages/" directory.
202 Uri packagesDirectoryUri = nonFileUri.resolve("packages/");
203 return new NonFilePackagesDirectoryPackages(packagesDirectoryUri);
204 });
205 }
206
207 /// Fetches a file over http.
208 Future<List<int>> _httpGet(Uri uri) async {
209 HttpClient client = new HttpClient();
210 HttpClientRequest request = await client.getUrl(uri);
211 HttpClientResponse response = await request.close();
212 if (response.statusCode != HttpStatus.OK) {
213 throw 'Failure getting $uri: '
214 '${response.statusCode} ${response.reasonPhrase}';
215 }
216 List<List<int>> splitContent = await response.toList();
217 int totalLength = 0;
218 for (var list in splitContent) {
219 totalLength += list.length;
220 }
221 Uint8List result = new Uint8List(totalLength);
222 int offset = 0;
223 for (List<int> contentPart in splitContent) {
224 result.setRange(offset, offset + contentPart.length, contentPart);
225 offset += contentPart.length;
226 }
227 return result;
228 }
OLDNEW
« no previous file with comments | « observe/pubspec.yaml ('k') | package_config/lib/discovery_analysis.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698