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

Side by Side Diff: utils/pub/entrypoint.dart

Issue 11638010: Convert /** comments to /// in pub. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Respond to review. Created 8 years 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 | Annotate | Revision Log
« no previous file with comments | « utils/pub/command_version.dart ('k') | utils/pub/git.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 entrypoint; 5 library entrypoint;
6 6
7 import 'io.dart'; 7 import 'io.dart';
8 import 'lock_file.dart'; 8 import 'lock_file.dart';
9 import 'log.dart' as log; 9 import 'log.dart' as log;
10 import 'package.dart'; 10 import 'package.dart';
11 import 'root_source.dart'; 11 import 'root_source.dart';
12 import 'system_cache.dart'; 12 import 'system_cache.dart';
13 import 'utils.dart'; 13 import 'utils.dart';
14 import 'version.dart'; 14 import 'version.dart';
15 import 'version_solver.dart'; 15 import 'version_solver.dart';
16 16
17 /** 17 /// Pub operates over a directed graph of dependencies that starts at a root
18 * Pub operates over a directed graph of dependencies that starts at a root 18 /// "entrypoint" package. This is typically the package where the current
19 * "entrypoint" package. This is typically the package where the current 19 /// working directory is located. An entrypoint knows the [root] package it is
20 * working directory is located. An entrypoint knows the [root] package it is 20 /// associated with and is responsible for managing the "packages" directory
21 * associated with and is responsible for managing the "packages" directory 21 /// for it.
22 * for it. 22 ///
23 * 23 /// That directory contains symlinks to all packages used by an app. These links
24 * That directory contains symlinks to all packages used by an app. These links 24 /// point either to the [SystemCache] or to some other location on the local
25 * point either to the [SystemCache] or to some other location on the local 25 /// filesystem.
26 * filesystem. 26 ///
27 * 27 /// While entrypoints are typically applications, a pure library package may end
28 * While entrypoints are typically applications, a pure library package may end 28 /// up being used as an entrypoint. Also, a single package may be used as an
29 * up being used as an entrypoint. Also, a single package may be used as an 29 /// entrypoint in one context but not in another. For example, a package that
30 * entrypoint in one context but not in another. For example, a package that 30 /// contains a reusable library may not be the entrypoint when used by an app,
31 * contains a reusable library may not be the entrypoint when used by an app, 31 /// but may be the entrypoint when you're running its tests.
32 * but may be the entrypoint when you're running its tests.
33 */
34 class Entrypoint { 32 class Entrypoint {
35 /** 33 /// The root package this entrypoint is associated with.
36 * The root package this entrypoint is associated with.
37 */
38 final Package root; 34 final Package root;
39 35
40 /** 36 /// The system-wide cache which caches packages that need to be fetched over
41 * The system-wide cache which caches packages that need to be fetched over 37 /// the network.
42 * the network.
43 */
44 final SystemCache cache; 38 final SystemCache cache;
45 39
46 /** 40 /// Packages which are either currently being asynchronously installed to the
47 * Packages which are either currently being asynchronously installed to the 41 /// directory, or have already been installed.
48 * directory, or have already been installed.
49 */
50 final Map<PackageId, Future<PackageId>> _installs; 42 final Map<PackageId, Future<PackageId>> _installs;
51 43
52 Entrypoint(this.root, this.cache) 44 Entrypoint(this.root, this.cache)
53 : _installs = new Map<PackageId, Future<PackageId>>(); 45 : _installs = new Map<PackageId, Future<PackageId>>();
54 46
55 /// Loads the entrypoint from a package at [rootDir]. 47 /// Loads the entrypoint from a package at [rootDir].
56 static Future<Entrypoint> load(String rootDir, SystemCache cache) { 48 static Future<Entrypoint> load(String rootDir, SystemCache cache) {
57 return Package.load(null, rootDir, cache.sources).transform((package) => 49 return Package.load(null, rootDir, cache.sources).transform((package) =>
58 new Entrypoint(package, cache)); 50 new Entrypoint(package, cache));
59 } 51 }
60 52
61 /**
62 * The path to this "packages" directory.
63 */
64 // TODO(rnystrom): Make this path configurable. 53 // TODO(rnystrom): Make this path configurable.
54 /// The path to this "packages" directory.
65 String get path => join(root.dir, 'packages'); 55 String get path => join(root.dir, 'packages');
66 56
67 /** 57 /// Ensures that the package identified by [id] is installed to the directory.
68 * Ensures that the package identified by [id] is installed to the directory. 58 /// Returns the resolved [PackageId].
69 * Returns the resolved [PackageId]. 59 ///
70 * 60 /// If this completes successfully, the package is guaranteed to be importable
71 * If this completes successfully, the package is guaranteed to be importable 61 /// using the `package:` scheme.
72 * using the `package:` scheme. 62 ///
73 * 63 /// This will automatically install the package to the system-wide cache as
74 * This will automatically install the package to the system-wide cache as 64 /// well if it requires network access to retrieve (specifically, if
75 * well if it requires network access to retrieve (specifically, if 65 /// `id.source.shouldCache` is true).
76 * `id.source.shouldCache` is true). 66 ///
77 * 67 /// See also [installDependencies].
78 * See also [installDependencies].
79 */
80 Future<PackageId> install(PackageId id) { 68 Future<PackageId> install(PackageId id) {
81 var pendingOrCompleted = _installs[id]; 69 var pendingOrCompleted = _installs[id];
82 if (pendingOrCompleted != null) return pendingOrCompleted; 70 if (pendingOrCompleted != null) return pendingOrCompleted;
83 71
84 var packageDir = join(path, id.name); 72 var packageDir = join(path, id.name);
85 var future = ensureDir(dirname(packageDir)).chain((_) { 73 var future = ensureDir(dirname(packageDir)).chain((_) {
86 return exists(packageDir); 74 return exists(packageDir);
87 }).chain((exists) { 75 }).chain((exists) {
88 if (!exists) return new Future.immediate(null); 76 if (!exists) return new Future.immediate(null);
89 // TODO(nweiz): figure out when to actually delete the directory, and when 77 // TODO(nweiz): figure out when to actually delete the directory, and when
(...skipping 11 matching lines...) Expand all
101 throw 'Package ${id.name} not found in source "${id.source.name}".'; 89 throw 'Package ${id.name} not found in source "${id.source.name}".';
102 }); 90 });
103 } 91 }
104 }).chain((_) => id.resolved); 92 }).chain((_) => id.resolved);
105 93
106 _installs[id] = future; 94 _installs[id] = future;
107 95
108 return future; 96 return future;
109 } 97 }
110 98
111 /** 99 /// Installs all dependencies of the [root] package to its "packages"
112 * Installs all dependencies of the [root] package to its "packages" 100 /// directory, respecting the [LockFile] if present. Returns a [Future] that
113 * directory, respecting the [LockFile] if present. Returns a [Future] that 101 /// completes when all dependencies are installed.
114 * completes when all dependencies are installed.
115 */
116 Future installDependencies() { 102 Future installDependencies() {
117 return _loadLockFile() 103 return _loadLockFile()
118 .chain((lockFile) => resolveVersions(cache.sources, root, lockFile)) 104 .chain((lockFile) => resolveVersions(cache.sources, root, lockFile))
119 .chain(_installDependencies); 105 .chain(_installDependencies);
120 } 106 }
121 107
122 /** 108 /// Installs the latest available versions of all dependencies of the [root]
123 * Installs the latest available versions of all dependencies of the [root] 109 /// package to its "package" directory, writing a new [LockFile]. Returns a
124 * package to its "package" directory, writing a new [LockFile]. Returns a 110 /// [Future] that completes when all dependencies are installed.
125 * [Future] that completes when all dependencies are installed.
126 */
127 Future updateAllDependencies() { 111 Future updateAllDependencies() {
128 return resolveVersions(cache.sources, root, new LockFile.empty()) 112 return resolveVersions(cache.sources, root, new LockFile.empty())
129 .chain(_installDependencies); 113 .chain(_installDependencies);
130 } 114 }
131 115
132 /** 116 /// Installs the latest available versions of [dependencies], while leaving
133 * Installs the latest available versions of [dependencies], while leaving 117 /// other dependencies as specified by the [LockFile] if possible. Returns a
134 * other dependencies as specified by the [LockFile] if possible. Returns a 118 /// [Future] that completes when all dependencies are installed.
135 * [Future] that completes when all dependencies are installed.
136 */
137 Future updateDependencies(List<String> dependencies) { 119 Future updateDependencies(List<String> dependencies) {
138 return _loadLockFile().chain((lockFile) { 120 return _loadLockFile().chain((lockFile) {
139 var versionSolver = new VersionSolver(cache.sources, root, lockFile); 121 var versionSolver = new VersionSolver(cache.sources, root, lockFile);
140 for (var dependency in dependencies) { 122 for (var dependency in dependencies) {
141 versionSolver.useLatestVersion(dependency); 123 versionSolver.useLatestVersion(dependency);
142 } 124 }
143 return versionSolver.solve(); 125 return versionSolver.solve();
144 }).chain(_installDependencies); 126 }).chain(_installDependencies);
145 } 127 }
146 128
147 /** 129 /// Removes the old packages directory, installs all dependencies listed in
148 * Removes the old packages directory, installs all dependencies listed in 130 /// [packageVersions], and writes a [LockFile].
149 * [packageVersions], and writes a [LockFile].
150 */
151 Future _installDependencies(List<PackageId> packageVersions) { 131 Future _installDependencies(List<PackageId> packageVersions) {
152 return cleanDir(path).chain((_) { 132 return cleanDir(path).chain((_) {
153 return Futures.wait(packageVersions.map((id) { 133 return Futures.wait(packageVersions.map((id) {
154 if (id.source is RootSource) return new Future.immediate(id); 134 if (id.source is RootSource) return new Future.immediate(id);
155 return install(id); 135 return install(id);
156 })); 136 }));
157 }).chain(_saveLockFile) 137 }).chain(_saveLockFile)
158 .chain(_installSelfReference) 138 .chain(_installSelfReference)
159 .chain(_linkSecondaryPackageDirs); 139 .chain(_linkSecondaryPackageDirs);
160 } 140 }
161 141
162 /** 142 /// Loads the list of concrete package versions from the `pubspec.lock`, if it
163 * Loads the list of concrete package versions from the `pubspec.lock`, if it 143 /// exists. If it doesn't, this completes to an empty [LockFile].
164 * exists. If it doesn't, this completes to an empty [LockFile]. 144 ///
165 * 145 /// If there's an error reading the `pubspec.lock` file, this will print a
166 * If there's an error reading the `pubspec.lock` file, this will print a 146 /// warning message and act as though the file doesn't exist.
167 * warning message and act as though the file doesn't exist.
168 */
169 Future<LockFile> _loadLockFile() { 147 Future<LockFile> _loadLockFile() {
170 var lockFilePath = join(root.dir, 'pubspec.lock'); 148 var lockFilePath = join(root.dir, 'pubspec.lock');
171 149
172 log.fine("Loading lockfile."); 150 log.fine("Loading lockfile.");
173 return fileExists(lockFilePath).chain((exists) { 151 return fileExists(lockFilePath).chain((exists) {
174 if (!exists) { 152 if (!exists) {
175 log.fine("No lock file at $lockFilePath, creating empty one."); 153 log.fine("No lock file at $lockFilePath, creating empty one.");
176 return new Future<LockFile>.immediate(new LockFile.empty()); 154 return new Future<LockFile>.immediate(new LockFile.empty());
177 } 155 }
178 156
179 return readTextFile(lockFilePath).transform((text) => 157 return readTextFile(lockFilePath).transform((text) =>
180 new LockFile.parse(text, cache.sources)); 158 new LockFile.parse(text, cache.sources));
181 }); 159 });
182 } 160 }
183 161
184 /** 162 /// Saves a list of concrete package versions to the `pubspec.lock` file.
185 * Saves a list of concrete package versions to the `pubspec.lock` file.
186 */
187 Future _saveLockFile(List<PackageId> packageIds) { 163 Future _saveLockFile(List<PackageId> packageIds) {
188 var lockFile = new LockFile.empty(); 164 var lockFile = new LockFile.empty();
189 for (var id in packageIds) { 165 for (var id in packageIds) {
190 if (id.source is! RootSource) lockFile.packages[id.name] = id; 166 if (id.source is! RootSource) lockFile.packages[id.name] = id;
191 } 167 }
192 168
193 var lockFilePath = join(root.dir, 'pubspec.lock'); 169 var lockFilePath = join(root.dir, 'pubspec.lock');
194 log.fine("Saving lockfile."); 170 log.fine("Saving lockfile.");
195 return writeTextFile(lockFilePath, lockFile.serialize()); 171 return writeTextFile(lockFilePath, lockFile.serialize());
196 } 172 }
197 173
198 /** 174 /// Installs a self-referential symlink in the `packages` directory that will
199 * Installs a self-referential symlink in the `packages` directory that will 175 /// allow a package to import its own files using `package:`.
200 * allow a package to import its own files using `package:`.
201 */
202 Future _installSelfReference(_) { 176 Future _installSelfReference(_) {
203 var linkPath = join(path, root.name); 177 var linkPath = join(path, root.name);
204 return exists(linkPath).chain((exists) { 178 return exists(linkPath).chain((exists) {
205 // Create the symlink if it doesn't exist. 179 // Create the symlink if it doesn't exist.
206 if (exists) return new Future.immediate(null); 180 if (exists) return new Future.immediate(null);
207 return ensureDir(path).chain( 181 return ensureDir(path).chain(
208 (_) => createPackageSymlink(root.name, root.dir, linkPath, 182 (_) => createPackageSymlink(root.name, root.dir, linkPath,
209 isSelfLink: true)); 183 isSelfLink: true));
210 }); 184 });
211 } 185 }
212 186
213 /** 187 /// If `bin/`, `test/`, or `example/` directories exist, symlink `packages/`
214 * If `bin/`, `test/`, or `example/` directories exist, symlink `packages/` 188 /// into them so that their entrypoints can be run. Do the same for any
215 * into them so that their entrypoints can be run. Do the same for any 189 /// subdirectories of `test/` and `example/`.
216 * subdirectories of `test/` and `example/`.
217 */
218 Future _linkSecondaryPackageDirs(_) { 190 Future _linkSecondaryPackageDirs(_) {
219 var binDir = join(root.dir, 'bin'); 191 var binDir = join(root.dir, 'bin');
220 var exampleDir = join(root.dir, 'example'); 192 var exampleDir = join(root.dir, 'example');
221 var testDir = join(root.dir, 'test'); 193 var testDir = join(root.dir, 'test');
222 var toolDir = join(root.dir, 'tool'); 194 var toolDir = join(root.dir, 'tool');
223 var webDir = join(root.dir, 'web'); 195 var webDir = join(root.dir, 'web');
224 return dirExists(binDir).chain((exists) { 196 return dirExists(binDir).chain((exists) {
225 if (!exists) return new Future.immediate(null); 197 if (!exists) return new Future.immediate(null);
226 return _linkSecondaryPackageDir(binDir); 198 return _linkSecondaryPackageDir(binDir);
227 }).chain((_) => _linkSecondaryPackageDirsRecursively(exampleDir)) 199 }).chain((_) => _linkSecondaryPackageDirsRecursively(exampleDir))
228 .chain((_) => _linkSecondaryPackageDirsRecursively(testDir)) 200 .chain((_) => _linkSecondaryPackageDirsRecursively(testDir))
229 .chain((_) => _linkSecondaryPackageDirsRecursively(toolDir)) 201 .chain((_) => _linkSecondaryPackageDirsRecursively(toolDir))
230 .chain((_) => _linkSecondaryPackageDirsRecursively(webDir)); 202 .chain((_) => _linkSecondaryPackageDirsRecursively(webDir));
231 } 203 }
232 204
233 /** 205 /// Creates a symlink to the `packages` directory in [dir] and all its
234 * Creates a symlink to the `packages` directory in [dir] and all its 206 /// subdirectories.
235 * subdirectories.
236 */
237 Future _linkSecondaryPackageDirsRecursively(String dir) { 207 Future _linkSecondaryPackageDirsRecursively(String dir) {
238 return dirExists(dir).chain((exists) { 208 return dirExists(dir).chain((exists) {
239 if (!exists) return new Future.immediate(null); 209 if (!exists) return new Future.immediate(null);
240 return _linkSecondaryPackageDir(dir) 210 return _linkSecondaryPackageDir(dir)
241 .chain((_) => _listDirWithoutPackages(dir)) 211 .chain((_) => _listDirWithoutPackages(dir))
242 .chain((files) { 212 .chain((files) {
243 return Futures.wait(files.map((file) { 213 return Futures.wait(files.map((file) {
244 return dirExists(file).chain((isDir) { 214 return dirExists(file).chain((isDir) {
245 if (!isDir) return new Future.immediate(null); 215 if (!isDir) return new Future.immediate(null);
246 return _linkSecondaryPackageDir(file); 216 return _linkSecondaryPackageDir(file);
247 }); 217 });
248 })); 218 }));
249 }); 219 });
250 }); 220 });
251 } 221 }
252 222
253 // TODO(nweiz): roll this into [listDir] in io.dart once issue 4775 is fixed. 223 // TODO(nweiz): roll this into [listDir] in io.dart once issue 4775 is fixed.
254 /** 224 /// Recursively lists the contents of [dir], excluding hidden `.DS_Store`
255 * Recursively lists the contents of [dir], excluding hidden `.DS_Store` files 225 /// files and `package` files.
256 * and `package` files.
257 */
258 Future<List<String>> _listDirWithoutPackages(dir) { 226 Future<List<String>> _listDirWithoutPackages(dir) {
259 return listDir(dir).chain((files) { 227 return listDir(dir).chain((files) {
260 return Futures.wait(files.map((file) { 228 return Futures.wait(files.map((file) {
261 if (basename(file) == 'packages') return new Future.immediate([]); 229 if (basename(file) == 'packages') return new Future.immediate([]);
262 return dirExists(file).chain((isDir) { 230 return dirExists(file).chain((isDir) {
263 if (!isDir) return new Future.immediate([]); 231 if (!isDir) return new Future.immediate([]);
264 return _listDirWithoutPackages(file); 232 return _listDirWithoutPackages(file);
265 }).transform((subfiles) { 233 }).transform((subfiles) {
266 var fileAndSubfiles = [file]; 234 var fileAndSubfiles = [file];
267 fileAndSubfiles.addAll(subfiles); 235 fileAndSubfiles.addAll(subfiles);
268 return fileAndSubfiles; 236 return fileAndSubfiles;
269 }); 237 });
270 })); 238 }));
271 }).transform(flatten); 239 }).transform(flatten);
272 } 240 }
273 241
274 /** 242 /// Creates a symlink to the `packages` directory in [dir] if none exists.
275 * Creates a symlink to the `packages` directory in [dir] if none exists.
276 */
277 Future _linkSecondaryPackageDir(String dir) { 243 Future _linkSecondaryPackageDir(String dir) {
278 var to = join(dir, 'packages'); 244 var to = join(dir, 'packages');
279 return exists(to).chain((exists) { 245 return exists(to).chain((exists) {
280 if (exists) return new Future.immediate(null); 246 if (exists) return new Future.immediate(null);
281 return createSymlink(path, to); 247 return createSymlink(path, to);
282 }); 248 });
283 } 249 }
284 } 250 }
OLDNEW
« no previous file with comments | « utils/pub/command_version.dart ('k') | utils/pub/git.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698