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

Side by Side Diff: package_config/lib/packages_file.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 | « package_config/lib/packages.dart ('k') | package_config/lib/src/packages_impl.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.packages_file;
6
7 import "package:charcode/ascii.dart";
8 import "src/util.dart" show isValidPackageName;
9
10 /// Parses a `.packages` file into a map from package name to base URI.
11 ///
12 /// The [source] is the byte content of a `.packages` file, assumed to be
13 /// UTF-8 encoded. In practice, all significant parts of the file must be ASCII,
14 /// so Latin-1 or Windows-1252 encoding will also work fine.
15 ///
16 /// If the file content is available as a string, its [String.codeUnits] can
17 /// be used as the `source` argument of this function.
18 ///
19 /// The [baseLocation] is used as a base URI to resolve all relative
20 /// URI references against.
21 /// If the content was read from a file, `baseLocation` should be the
22 /// location of that file.
23 ///
24 /// Returns a simple mapping from package name to package location.
25 Map<String, Uri> parse(List<int> source, Uri baseLocation) {
26 int index = 0;
27 Map<String, Uri> result = <String, Uri>{};
28 while (index < source.length) {
29 bool isComment = false;
30 int start = index;
31 int separatorIndex = -1;
32 int end = source.length;
33 int char = source[index++];
34 if (char == $cr || char == $lf) {
35 continue;
36 }
37 if (char == $colon) {
38 throw new FormatException("Missing package name", source, index - 1);
39 }
40 isComment = char == $hash;
41 while (index < source.length) {
42 char = source[index++];
43 if (char == $colon && separatorIndex < 0) {
44 separatorIndex = index - 1;
45 } else if (char == $cr || char == $lf) {
46 end = index - 1;
47 break;
48 }
49 }
50 if (isComment) continue;
51 if (separatorIndex < 0) {
52 throw new FormatException("No ':' on line", source, index - 1);
53 }
54 var packageName = new String.fromCharCodes(source, start, separatorIndex);
55 if (!isValidPackageName(packageName)) {
56 throw new FormatException("Not a valid package name", packageName, 0);
57 }
58 var packageUri = new String.fromCharCodes(source, separatorIndex + 1, end);
59 var packageLocation = Uri.parse(packageUri);
60 packageLocation = baseLocation.resolveUri(packageLocation);
61 if (!packageLocation.path.endsWith('/')) {
62 packageLocation =
63 packageLocation.replace(path: packageLocation.path + "/");
64 }
65 if (result.containsKey(packageName)) {
66 throw new FormatException(
67 "Same package name occured twice.", source, start);
68 }
69 result[packageName] = packageLocation;
70 }
71 return result;
72 }
73
74 /// Writes the mapping to a [StringSink].
75 ///
76 /// If [comment] is provided, the output will contain this comment
77 /// with `# ` in front of each line.
78 /// Lines are defined as ending in line feed (`'\n'`). If the final
79 /// line of the comment doesn't end in a line feed, one will be added.
80 ///
81 /// If [baseUri] is provided, package locations will be made relative
82 /// to the base URI, if possible, before writing.
83 ///
84 /// All the keys of [packageMapping] must be valid package names,
85 /// and the values must be URIs that do not have the `package:` scheme.
86 void write(StringSink output, Map<String, Uri> packageMapping,
87 {Uri baseUri, String comment}) {
88 if (baseUri != null && !baseUri.isAbsolute) {
89 throw new ArgumentError.value(baseUri, "baseUri", "Must be absolute");
90 }
91
92 if (comment != null) {
93 var lines = comment.split('\n');
94 if (lines.last.isEmpty) lines.removeLast();
95 for (var commentLine in lines) {
96 output.write('# ');
97 output.writeln(commentLine);
98 }
99 } else {
100 output.write("# generated by package:package_config at ");
101 output.write(new DateTime.now());
102 output.writeln();
103 }
104
105 packageMapping.forEach((String packageName, Uri uri) {
106 // Validate packageName.
107 if (!isValidPackageName(packageName)) {
108 throw new ArgumentError('"$packageName" is not a valid package name');
109 }
110 if (uri.scheme == "package") {
111 throw new ArgumentError.value(
112 "Package location must not be a package: URI", uri.toString());
113 }
114 output.write(packageName);
115 output.write(':');
116 // If baseUri provided, make uri relative.
117 if (baseUri != null) {
118 uri = _relativize(uri, baseUri);
119 }
120 output.write(uri);
121 if (!uri.path.endsWith('/')) {
122 output.write('/');
123 }
124 output.writeln();
125 });
126 }
127
128 /// Attempts to return a relative URI for [uri].
129 ///
130 /// The result URI satisfies `baseUri.resolveUri(result) == uri`,
131 /// but may be relative.
132 /// The `baseUri` must be absolute.
133 Uri _relativize(Uri uri, Uri baseUri) {
134 assert(baseUri.isAbsolute);
135 if (uri.hasQuery || uri.hasFragment) {
136 uri = new Uri(
137 scheme: uri.scheme,
138 userInfo: uri.hasAuthority ? uri.userInfo : null,
139 host: uri.hasAuthority ? uri.host : null,
140 port: uri.hasAuthority ? uri.port : null,
141 path: uri.path);
142 }
143
144 // Already relative. We assume the caller knows what they are doing.
145 if (!uri.isAbsolute) return uri;
146
147 if (baseUri.scheme != uri.scheme) {
148 return uri;
149 }
150
151 // If authority differs, we could remove the scheme, but it's not worth it.
152 if (uri.hasAuthority != baseUri.hasAuthority) return uri;
153 if (uri.hasAuthority) {
154 if (uri.userInfo != baseUri.userInfo ||
155 uri.host.toLowerCase() != baseUri.host.toLowerCase() ||
156 uri.port != baseUri.port) {
157 return uri;
158 }
159 }
160
161 baseUri = _normalizePath(baseUri);
162 List<String> base = baseUri.pathSegments.toList();
163 if (base.isNotEmpty) {
164 base = new List<String>.from(base)..removeLast();
165 }
166 uri = _normalizePath(uri);
167 List<String> target = uri.pathSegments.toList();
168 if (target.isNotEmpty && target.last.isEmpty) target.removeLast();
169 int index = 0;
170 while (index < base.length && index < target.length) {
171 if (base[index] != target[index]) {
172 break;
173 }
174 index++;
175 }
176 if (index == base.length) {
177 if (index == target.length) {
178 return new Uri(path: "./");
179 }
180 return new Uri(path: target.skip(index).join('/'));
181 } else if (index > 0) {
182 return new Uri(
183 path: '../' * (base.length - index) + target.skip(index).join('/'));
184 } else {
185 return uri;
186 }
187 }
188
189 // TODO: inline to uri.normalizePath() when we move to 1.11
190 Uri _normalizePath(Uri uri) => new Uri().resolveUri(uri);
OLDNEW
« no previous file with comments | « package_config/lib/packages.dart ('k') | package_config/lib/src/packages_impl.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698