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

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

Issue 14297021: Move pub into sdk/lib/_internal. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Disallow package: imports of pub. Created 7 years, 8 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 | Annotate | Revision Log
« no previous file with comments | « utils/pub/solver/version_solver.dart ('k') | utils/pub/source_registry.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) 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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library source;
6
7 import 'dart:async';
8
9 import 'package:pathos/path.dart' as path;
10
11 import 'io.dart';
12 import 'package.dart';
13 import 'pubspec.dart';
14 import 'system_cache.dart';
15 import 'utils.dart';
16 import 'version.dart';
17
18 /// A source from which to install packages.
19 ///
20 /// Each source has many packages that it looks up using [PackageId]s. The
21 /// source is responsible for installing these packages to the package cache.
22 abstract class Source {
23 /// The name of the source. Should be lower-case, suitable for use in a
24 /// filename, and unique accross all sources.
25 String get name;
26
27 /// Whether or not this source is the default source.
28 bool get isDefault => systemCache.sources.defaultSource == this;
29
30 /// Whether this source's packages should be cached in Pub's global cache
31 /// directory.
32 ///
33 /// A source should be cached if it requires network access to retrieve
34 /// packages. It doesn't need to be cached if all packages are available
35 /// locally.
36 bool get shouldCache;
37
38 /// The system cache with which this source is registered.
39 SystemCache get systemCache {
40 assert(_systemCache != null);
41 return _systemCache;
42 }
43
44 /// The system cache variable. Set by [_bind].
45 SystemCache _systemCache;
46
47 /// The root directory of this source's cache within the system cache.
48 ///
49 /// This shouldn't be overridden by subclasses.
50 String get systemCacheRoot => path.join(systemCache.rootDir, name);
51
52 /// Records the system cache to which this source belongs.
53 ///
54 /// This should only be called once for each source, by
55 /// [SystemCache.register]. It should not be overridden by base classes.
56 void bind(SystemCache systemCache) {
57 assert(_systemCache == null);
58 this._systemCache = systemCache;
59 }
60
61 /// Get the list of all versions that exist for the package described by
62 /// [description]. [name] is the expected name of the package.
63 ///
64 /// Note that this does *not* require the packages to be installed, which is
65 /// the point. This is used during version resolution to determine which
66 /// package versions are available to be installed (or already installed).
67 ///
68 /// By default, this assumes that each description has a single version and
69 /// uses [describe] to get that version.
70 Future<List<Version>> getVersions(String name, description) {
71 return describe(new PackageId(name, this, Version.none, description))
72 .then((pubspec) => [pubspec.version]);
73 }
74
75 /// Loads the (possibly remote) pubspec for the package version identified by
76 /// [id]. This may be called for packages that have not yet been installed
77 /// during the version resolution process.
78 ///
79 /// For cached sources, by default this uses [installToSystemCache] to get the
80 /// pubspec. There is no default implementation for non-cached sources; they
81 /// must implement it manually.
82 Future<Pubspec> describe(PackageId id) {
83 if (!shouldCache) {
84 throw new UnimplementedError("Source $name must implement describe(id).");
85 }
86 return installToSystemCache(id).then((package) => package.pubspec);
87 }
88
89 /// Installs the package identified by [id] to [path]. Returns a [Future] that
90 /// completes when the installation was finished. The [Future] should resolve
91 /// to true if the package was found in the source and false if it wasn't. For
92 /// all other error conditions, it should complete with an exception.
93 ///
94 /// [path] is guaranteed not to exist, and its parent directory is guaranteed
95 /// to exist.
96 ///
97 /// Note that [path] may be deleted. If re-installing a package that has
98 /// already been installed would be costly or impossible,
99 /// [installToSystemCache] should be implemented instead of [install].
100 ///
101 /// This doesn't need to be implemented if [installToSystemCache] is
102 /// implemented.
103 Future<bool> install(PackageId id, String path) {
104 throw new UnimplementedError("Either install or installToSystemCache must "
105 "be implemented for source $name.");
106 }
107
108 /// Installs the package identified by [id] to the system cache. This is only
109 /// called for sources with [shouldCache] set to true.
110 ///
111 /// By default, this uses [systemCacheDirectory] and [install].
112 Future<Package> installToSystemCache(PackageId id) {
113 var packageDir;
114 return systemCacheDirectory(id).then((p) {
115 packageDir = p;
116
117 // See if it's already cached.
118 if (dirExists(packageDir)) {
119 if (!_isCachedPackageCorrupted(packageDir)) return true;
120 // Busted, so wipe out the package and reinstall.
121 deleteEntry(packageDir);
122 }
123
124 ensureDir(path.dirname(packageDir));
125 return install(id, packageDir);
126 }).then((found) {
127 if (!found) fail('Package $id not found.');
128 return new Package.load(id.name, packageDir, systemCache.sources);
129 });
130 }
131
132 /// Since pub generates symlinks that point into the system cache (in
133 /// particular, targeting the "lib" directories of cached packages), it's
134 /// possible to accidentally break cached packages if something traverses
135 /// that symlink.
136 ///
137 /// This tries to determine if the cached package at [packageDir] has been
138 /// corrupted. The heuristics are it is corrupted if any of the following are
139 /// true:
140 ///
141 /// * It has an empty "lib" directory.
142 /// * It has no pubspec.
143 bool _isCachedPackageCorrupted(String packageDir) {
144 if (!fileExists(path.join(packageDir, "pubspec.yaml"))) return true;
145
146 var libDir = path.join(packageDir, "lib");
147 if (dirExists(libDir)) return listDir(libDir).length == 0;
148
149 // If we got here, it's OK.
150 return false;
151 }
152
153 /// Returns the directory in the system cache that the package identified by
154 /// [id] should be installed to. This should return a path to a subdirectory
155 /// of [systemCacheRoot].
156 ///
157 /// This doesn't need to be implemented if [shouldCache] is false.
158 Future<String> systemCacheDirectory(PackageId id) {
159 return new Future.error(
160 "systemCacheDirectory() must be implemented if shouldCache is true.");
161 }
162
163 /// When a [Pubspec] or [LockFile] is parsed, it reads in the description for
164 /// each dependency. It is up to the dependency's [Source] to determine how
165 /// that should be interpreted. This will be called during parsing to validate
166 /// that the given [description] is well-formed according to this source, and
167 /// to give the source a chance to canonicalize the description.
168 ///
169 /// [containingPath] is the path to the local file (pubspec or lockfile)
170 /// where this description appears. It may be `null` if the description is
171 /// coming from some in-memory source (such as pulling down a pubspec from
172 /// pub.dartlang.org).
173 ///
174 /// It should return if a (possibly modified) valid description, or throw a
175 /// [FormatException] if not valid.
176 ///
177 /// [fromLockFile] is true when the description comes from a [LockFile], to
178 /// allow the source to use lockfile-specific descriptions via [resolveId].
179 dynamic parseDescription(String containingPath, description,
180 {bool fromLockFile: false}) {
181 return description;
182 }
183
184 /// Returns whether or not [description1] describes the same package as
185 /// [description2] for this source. This method should be light-weight. It
186 /// doesn't need to validate that either package exists.
187 ///
188 /// By default, just uses regular equality.
189 bool descriptionsEqual(description1, description2) =>
190 description1 == description2;
191
192 /// For some sources, [PackageId]s can point to different chunks of code at
193 /// different times. This takes such an [id] and returns a future that
194 /// completes to a [PackageId] that will uniquely specify a single chunk of
195 /// code forever.
196 ///
197 /// For example, [GitSource] might take an [id] with description
198 /// `http://github.com/dart-lang/some-lib.git` and return an id with a
199 /// description that includes the current commit of the Git repository.
200 ///
201 /// This will be called after the package identified by [id] is installed, so
202 /// the source can use the installed package to determine information about
203 /// the resolved id.
204 ///
205 /// The returned [PackageId] may have a description field that's invalid
206 /// according to [parseDescription], although it must still be serializable
207 /// to JSON and YAML. It must also be equal to [id] according to
208 /// [descriptionsEqual].
209 ///
210 /// By default, this just returns [id].
211 Future<PackageId> resolveId(PackageId id) => new Future.value(id);
212
213 /// Returns the [Package]s that have been installed in the system cache.
214 List<Package> getCachedPackages() {
215 if (shouldCache) {
216 throw new UnimplementedError("Source $name must implement this.");
217 }
218 }
219
220 /// Returns the source's name.
221 String toString() => name;
222 }
OLDNEW
« no previous file with comments | « utils/pub/solver/version_solver.dart ('k') | utils/pub/source_registry.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698