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

Side by Side Diff: lib/src/source.dart

Issue 2044253003: Refactor Source and SourceRegistry. (Closed) Base URL: git@github.com:dart-lang/pub.git@master
Patch Set: Rename LiveSource to BoundSource. Created 4 years, 6 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 | « lib/src/solver/version_solver.dart ('k') | lib/src/source/cached.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 import 'dart:async'; 5 import 'dart:async';
6 6
7 import 'package:pub_semver/pub_semver.dart'; 7 import 'package:pub_semver/pub_semver.dart';
8 8
9 import 'package.dart'; 9 import 'package.dart';
10 import 'pubspec.dart'; 10 import 'pubspec.dart';
11 import 'system_cache.dart'; 11 import 'system_cache.dart';
12 import 'utils.dart'; 12 import 'utils.dart';
13 13
14 /// A source from which to get packages. 14 /// A source from which to get packages.
15 /// 15 ///
16 /// Each source has many packages that it looks up using [PackageId]s. Sources 16 /// Each source has many packages that it looks up using [PackageId]s. Sources
17 /// that inherit this directly (currently just [PathSource]) are *uncached* 17 /// that inherit this directly (currently just [PathSource]) are *uncached*
18 /// sources. They deliver a package directly to the package that depends on it. 18 /// sources. They deliver a package directly to the package that depends on it.
19 /// 19 ///
20 /// Other sources are *cached* sources. These extend [CachedSource]. When a 20 /// Other sources are *cached* sources. These extend [CachedSource]. When a
21 /// package needs a dependency from a cached source, it is first installed in 21 /// package needs a dependency from a cached source, it is first installed in
22 /// the [SystemCache] and then acquired from there. 22 /// the [SystemCache] and then acquired from there.
23 /// 23 ///
24 /// Each user-visible source has two classes: a [Source] that knows how to do
25 /// filesystem-independent operations like parsing and comparing descriptions,
26 /// and a [BoundSource] that knows how to actually install (and potentially
27 /// download) those packages. Only the [BoundSource] has access to the
28 /// [SystemCache].
29 ///
24 /// ## Subclassing 30 /// ## Subclassing
25 /// 31 ///
26 /// All sources should extend this class. In addition to defining the behavior 32 /// All [Source]s should extend this class and all [BoundSource]s should extend
27 /// of various methods, sources define the structure of package descriptions 33 /// [BoundSource]. In addition to defining the behavior of various methods,
28 /// used in [PackageRef]s, [PackageDep]s, and [PackageId]s. There are three 34 /// sources define the structure of package descriptions used in [PackageRef]s,
29 /// distinct types of description, although in practice most sources use the 35 /// [PackageDep]s, and [PackageId]s. There are three distinct types of
30 /// same format for one or more of these: 36 /// description, although in practice most sources use the same format for one
37 /// or more of these:
31 /// 38 ///
32 /// * User descriptions. These are included in pubspecs and usually written by 39 /// * User descriptions. These are included in pubspecs and usually written by
33 /// hand. They're typically more flexible in the formats they allow to 40 /// hand. They're typically more flexible in the formats they allow to
34 /// optimize for ease of authoring. 41 /// optimize for ease of authoring.
35 /// 42 ///
36 /// * Reference descriptions. These are the descriptions in [PackageRef]s and 43 /// * Reference descriptions. These are the descriptions in [PackageRef]s and
37 /// [PackageDep]. They're parsed directly from user descriptions using 44 /// [PackageDep]. They're parsed directly from user descriptions using
38 /// [parseRef], and so add no additional information. 45 /// [parseRef], and so add no additional information.
39 /// 46 ///
40 /// * ID descriptions. These are the descriptions in [PackageId]s, which 47 /// * ID descriptions. These are the descriptions in [PackageId]s, which
41 /// uniquely identify and provide the means to locate the concrete code of a 48 /// uniquely identify and provide the means to locate the concrete code of a
42 /// package. They may contain additional expensive-to-compute information 49 /// package. They may contain additional expensive-to-compute information
43 /// relative to the corresponding reference descriptions. These are the 50 /// relative to the corresponding reference descriptions. These are the
44 /// descriptions stored in lock files. 51 /// descriptions stored in lock files.
45 abstract class Source { 52 abstract class Source {
46 /// The name of the source. 53 /// The name of the source.
47 /// 54 ///
48 /// Should be lower-case, suitable for use in a filename, and unique accross 55 /// Should be lower-case, suitable for use in a filename, and unique accross
49 /// all sources. 56 /// all sources.
50 String get name; 57 String get name;
51 58
52 /// Whether this source can choose between multiple versions of the same 59 /// Whether this source can choose between multiple versions of the same
53 /// package during version solving. 60 /// package during version solving.
54 /// 61 ///
55 /// Defaults to `false`. 62 /// Defaults to `false`.
56 final bool hasMultipleVersions = false; 63 final bool hasMultipleVersions = false;
57 64
58 /// Whether or not this source is the default source.
59 bool get isDefault => systemCache.sources.defaultSource == this;
60
61 /// A cache of pubspecs described by [describe].
62 final _pubspecs = <PackageId, Pubspec>{};
63
64 /// The system cache with which this source is registered.
65 SystemCache get systemCache {
66 assert(_systemCache != null);
67 return _systemCache;
68 }
69
70 /// The system cache variable.
71 ///
72 /// Set by [_bind].
73 SystemCache _systemCache;
74
75 /// Records the system cache to which this source belongs. 65 /// Records the system cache to which this source belongs.
76 /// 66 ///
77 /// This should only be called once for each source, by 67 /// This should only be called once for each source, by
78 /// [SystemCache.register]. It should not be overridden by base classes. 68 /// [SystemCache.register]. It should not be overridden by base classes.
79 void bind(SystemCache systemCache) { 69 BoundSource bind(SystemCache systemCache);
80 assert(_systemCache == null); 70
81 this._systemCache = systemCache; 71 /// Parses a [PackageRef] from a name and a user-provided [description].
72 ///
73 /// When a [Pubspec] is parsed, it reads in the description for each
74 /// dependency. It is up to the dependency's [Source] to determine how that
75 /// should be interpreted. This will be called during parsing to validate that
76 /// the given [description] is well-formed according to this source, and to
77 /// give the source a chance to canonicalize the description.
78 ///
79 /// [containingPath] is the path to the local file (pubspec or lockfile)
80 /// where this description appears. It may be `null` if the description is
81 /// coming from some in-memory source (such as pulling down a pubspec from
82 /// pub.dartlang.org).
83 ///
84 /// The description in the returned [PackageRef] need bear no resemblance to
85 /// the original user-provided description.
86 ///
87 /// Throws a [FormatException] if the description is not valid.
88 PackageRef parseRef(String name, description, {String containingPath});
89
90 /// Parses a [PackageId] from a name and a serialized description.
91 ///
92 /// This only accepts descriptions serialized using [serializeDescription]. It
93 /// should not be used with user-authored descriptions.
94 ///
95 /// Throws a [FormatException] if the description is not valid.
96 PackageId parseId(String name, Version version, description);
97
98 /// When a [LockFile] is serialized, it uses this method to get the
99 /// [description] in the right format.
100 ///
101 /// [containingPath] is the containing directory of the root package.
102 dynamic serializeDescription(String containingPath, description) {
103 return description;
82 } 104 }
83 105
106 /// When a package [description] is shown to the user, this is called to
107 /// convert it into a human-friendly form.
108 ///
109 /// By default, it just converts the description to a string, but sources
110 /// may customize this. [containingPath] is the containing directory of the
111 /// root package.
112 String formatDescription(String containingPath, description) {
113 return description.toString();
114 }
115
116 /// Returns whether or not [description1] describes the same package as
117 /// [description2] for this source.
118 ///
119 /// This method should be light-weight. It doesn't need to validate that
120 /// either package exists.
121 ///
122 /// Note that either description may be a reference description or an ID
123 /// description; they need not be the same type. ID descriptions should be
124 /// considered equal to the reference descriptions that produced them.
125 bool descriptionsEqual(description1, description2);
126
127 /// Returns the source's name.
128 String toString() => name;
129 }
130
131 /// A source bound to a [SystemCache].
132 abstract class BoundSource {
133 /// The unbound source that produced [this].
134 Source get source;
135
136 /// The system cache to which [this] is bound.
137 SystemCache get systemCache;
138
84 /// Get the IDs of all versions that match [ref]. 139 /// Get the IDs of all versions that match [ref].
85 /// 140 ///
86 /// Note that this does *not* require the packages to be downloaded locally, 141 /// Note that this does *not* require the packages to be downloaded locally,
87 /// which is the point. This is used during version resolution to determine 142 /// which is the point. This is used during version resolution to determine
88 /// which package versions are available to be downloaded (or already 143 /// which package versions are available to be downloaded (or already
89 /// downloaded). 144 /// downloaded).
90 /// 145 ///
91 /// By default, this assumes that each description has a single version and 146 /// By default, this assumes that each description has a single version and
92 /// uses [describe] to get that version. 147 /// uses [describe] to get that version.
93 /// 148 ///
94 /// Sources should not override this. Instead, they implement [doGetVersions]. 149 /// Sources should not override this. Instead, they implement [doGetVersions].
95 Future<List<PackageId>> getVersions(PackageRef ref) { 150 Future<List<PackageId>> getVersions(PackageRef ref) {
96 if (ref.isRoot) { 151 if (ref.isRoot) {
97 throw new ArgumentError("Cannot get versions for the root package."); 152 throw new ArgumentError("Cannot get versions for the root package.");
98 } 153 }
99 if (ref.source != name) { 154 if (ref.source != source.name) {
100 throw new ArgumentError("Package $ref does not use source $name."); 155 throw new ArgumentError("Package $ref does not use source ${source.name}." );
101 } 156 }
102 157
103 return doGetVersions(ref); 158 return doGetVersions(ref);
104 } 159 }
105 160
106 /// Get the IDs of all versions that match [ref]. 161 /// Get the IDs of all versions that match [ref].
107 /// 162 ///
108 /// Note that this does *not* require the packages to be downloaded locally, 163 /// Note that this does *not* require the packages to be downloaded locally,
109 /// which is the point. This is used during version resolution to determine 164 /// which is the point. This is used during version resolution to determine
110 /// which package versions are available to be downloaded (or already 165 /// which package versions are available to be downloaded (or already
111 /// downloaded). 166 /// downloaded).
112 /// 167 ///
113 /// By default, this assumes that each description has a single version and 168 /// By default, this assumes that each description has a single version and
114 /// uses [describe] to get that version. 169 /// uses [describe] to get that version.
115 /// 170 ///
116 /// This method is effectively protected: subclasses must implement it, but 171 /// This method is effectively protected: subclasses must implement it, but
117 /// external code should not call this. Instead, call [getVersions]. 172 /// external code should not call this. Instead, call [getVersions].
118 Future<List<PackageId>> doGetVersions(PackageRef ref); 173 Future<List<PackageId>> doGetVersions(PackageRef ref);
119 174
175 /// A cache of pubspecs described by [describe].
176 final _pubspecs = <PackageId, Pubspec>{};
177
120 /// Loads the (possibly remote) pubspec for the package version identified by 178 /// Loads the (possibly remote) pubspec for the package version identified by
121 /// [id]. 179 /// [id].
122 /// 180 ///
123 /// This may be called for packages that have not yet been downloaded during 181 /// This may be called for packages that have not yet been downloaded during
124 /// the version resolution process. Its results are automatically memoized. 182 /// the version resolution process. Its results are automatically memoized.
125 /// 183 ///
126 /// Throws a [DataException] if the pubspec's version doesn't match [id]'s 184 /// Throws a [DataException] if the pubspec's version doesn't match [id]'s
127 /// version. 185 /// version.
128 /// 186 ///
129 /// Sources should not override this. Instead, they implement [doDescribe]. 187 /// Sources should not override this. Instead, they implement [doDescribe].
130 Future<Pubspec> describe(PackageId id) async { 188 Future<Pubspec> describe(PackageId id) async {
131 if (id.isRoot) throw new ArgumentError("Cannot describe the root package."); 189 if (id.isRoot) throw new ArgumentError("Cannot describe the root package.");
132 if (id.source != name) { 190 if (id.source != source.name) {
133 throw new ArgumentError("Package $id does not use source $name."); 191 throw new ArgumentError("Package $id does not use source ${source.name}.") ;
134 } 192 }
135 193
136 var pubspec = _pubspecs[id]; 194 var pubspec = _pubspecs[id];
137 if (pubspec != null) return pubspec; 195 if (pubspec != null) return pubspec;
138 196
139 // Delegate to the overridden one. 197 // Delegate to the overridden one.
140 pubspec = await doDescribe(id); 198 pubspec = await doDescribe(id);
141 if (pubspec.version != id.version) { 199 if (pubspec.version != id.version) {
142 dataError("The pubspec for $id has version ${pubspec.version}."); 200 dataError("The pubspec for $id has version ${pubspec.version}.");
143 } 201 }
(...skipping 14 matching lines...) Expand all
158 216
159 /// Ensures [id] is available locally and creates a symlink at [symlink] 217 /// Ensures [id] is available locally and creates a symlink at [symlink]
160 /// pointing it. 218 /// pointing it.
161 Future get(PackageId id, String symlink); 219 Future get(PackageId id, String symlink);
162 220
163 /// Returns the directory where this package can (or could) be found locally. 221 /// Returns the directory where this package can (or could) be found locally.
164 /// 222 ///
165 /// If the source is cached, this will be a path in the system cache. 223 /// If the source is cached, this will be a path in the system cache.
166 String getDirectory(PackageId id); 224 String getDirectory(PackageId id);
167 225
168 /// Parses a [PackageRef] from a name and a user-provided [description].
169 ///
170 /// When a [Pubspec] is parsed, it reads in the description for each
171 /// dependency. It is up to the dependency's [Source] to determine how that
172 /// should be interpreted. This will be called during parsing to validate that
173 /// the given [description] is well-formed according to this source, and to
174 /// give the source a chance to canonicalize the description.
175 ///
176 /// [containingPath] is the path to the local file (pubspec or lockfile)
177 /// where this description appears. It may be `null` if the description is
178 /// coming from some in-memory source (such as pulling down a pubspec from
179 /// pub.dartlang.org).
180 ///
181 /// The description in the returned [PackageRef] need bear no resemblance to
182 /// the original user-provided description.
183 ///
184 /// Throws a [FormatException] if the description is not valid.
185 PackageRef parseRef(String name, description, {String containingPath});
186
187 /// Parses a [PackageId] from a name and a serialized description.
188 ///
189 /// This only accepts descriptions serialized using [serializeDescription]. It
190 /// should not be used with user-authored descriptions.
191 ///
192 /// Throws a [FormatException] if the description is not valid.
193 PackageId parseId(String name, Version version, description);
194
195 /// When a [LockFile] is serialized, it uses this method to get the
196 /// [description] in the right format.
197 ///
198 /// [containingPath] is the containing directory of the root package.
199 dynamic serializeDescription(String containingPath, description) {
200 return description;
201 }
202
203 /// When a package [description] is shown to the user, this is called to
204 /// convert it into a human-friendly form.
205 ///
206 /// By default, it just converts the description to a string, but sources
207 /// may customize this. [containingPath] is the containing directory of the
208 /// root package.
209 String formatDescription(String containingPath, description) {
210 return description.toString();
211 }
212
213 /// Returns whether or not [description1] describes the same package as
214 /// [description2] for this source.
215 ///
216 /// This method should be light-weight. It doesn't need to validate that
217 /// either package exists.
218 ///
219 /// Note that either description may be a reference description or an ID
220 /// description; they need not be the same type. ID descriptions should be
221 /// considered equal to the reference descriptions that produced them.
222 bool descriptionsEqual(description1, description2);
223
224 /// Stores [pubspec] so it's returned when [describe] is called with [id]. 226 /// Stores [pubspec] so it's returned when [describe] is called with [id].
225 /// 227 ///
226 /// This is notionally protected; it should only be called by subclasses. 228 /// This is notionally protected; it should only be called by subclasses.
227 void memoizePubspec(PackageId id, Pubspec pubspec) { 229 void memoizePubspec(PackageId id, Pubspec pubspec) {
228 _pubspecs[id] = pubspec; 230 _pubspecs[id] = pubspec;
229 } 231 }
230
231 /// Returns the source's name.
232 String toString() => name;
233 } 232 }
OLDNEW
« no previous file with comments | « lib/src/solver/version_solver.dart ('k') | lib/src/source/cached.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698