Index: lib/packagemap.dart |
diff --git a/lib/packagemap.dart b/lib/packagemap.dart |
deleted file mode 100644 |
index 25f27b9a2ff53e6f430ebc9d51d67a08027b7d40..0000000000000000000000000000000000000000 |
--- a/lib/packagemap.dart |
+++ /dev/null |
@@ -1,228 +0,0 @@ |
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file |
-// for details. All rights reserved. Use of this source code is governed by a |
-// BSD-style license that can be found in the LICENSE file. |
- |
-library package_config.packagemap; |
- |
-class Packages { |
- static const int _EQUALS = 0x3d; |
- static const int _CR = 0x0d; |
- static const int _NL = 0x0a; |
- static const int _NUMBER_SIGN = 0x23; |
- |
- final Map<String, Uri> packageMapping; |
- |
- Packages(this.packageMapping); |
- |
- /// Resolves a URI to a non-package URI. |
- /// |
- /// If [uri] is a `package:` URI, the location is resolved wrt. the |
- /// [packageMapping]. |
- /// Otherwise the original URI is returned. |
- Uri resolve(Uri uri) { |
- if (uri.scheme.toLowerCase() != "package") { |
- return uri; |
- } |
- if (uri.hasAuthority) { |
- throw new ArgumentError.value(uri, "uri", "Must not have authority"); |
- } |
- if (uri.path.startsWith("/")) { |
- throw new ArgumentError.value( |
- uri, "uri", "Path must not start with '/'."); |
- } |
- // Normalizes the path by removing '.' and '..' segments. |
- uri = uri.normalizePath(); |
- String path = uri.path; |
- var slashIndex = path.indexOf('/'); |
- String packageName; |
- String rest; |
- if (slashIndex < 0) { |
- packageName = path; |
- rest = ""; |
- } else { |
- packageName = path.substring(0, slashIndex); |
- rest = path.substring(slashIndex + 1); |
- } |
- Uri packageLocation = packageMapping[packageName]; |
- if (packageLocation == null) { |
- throw new ArgumentError.value( |
- uri, "uri", "Unknown package name: $packageName"); |
- } |
- return packageLocation.resolveUri(new Uri(path: rest)); |
- } |
- |
- /// Parses a `packages.cfg` file into a `Packages` object. |
- /// |
- /// The [baseLocation] is used as a base URI to resolve all relative |
- /// URI references against. |
- /// |
- /// The `Packages` object allows resolving package: URIs and writing |
- /// the mapping back to a file or string. |
- /// The [packageMapping] will contain a simple mapping from package name |
- /// to package location. |
- static Packages parse(String source, Uri baseLocation) { |
- int index = 0; |
- Map<String, Uri> result = <String, Uri>{}; |
- while (index < source.length) { |
- bool isComment = false; |
- int start = index; |
- int eqIndex = -1; |
- int end = source.length; |
- int char = source.codeUnitAt(index++); |
- if (char == _CR || char == _NL) { |
- continue; |
- } |
- if (char == _EQUALS) { |
- throw new FormatException("Missing package name", source, index - 1); |
- } |
- isComment = char == _NUMBER_SIGN; |
- while (index < source.length) { |
- char = source.codeUnitAt(index++); |
- if (char == _EQUALS && eqIndex < 0) { |
- eqIndex = index - 1; |
- } else if (char == _NL || char == _CR) { |
- end = index - 1; |
- break; |
- } |
- } |
- if (isComment) continue; |
- if (eqIndex < 0) { |
- throw new FormatException("No '=' on line", source, index - 1); |
- } |
- _checkIdentifier(source, start, eqIndex); |
- var packageName = source.substring(start, eqIndex); |
- |
- var packageLocation = Uri.parse(source, eqIndex + 1, end); |
- if (!packageLocation.path.endsWith('/')) { |
- packageLocation = |
- packageLocation.replace(path: packageLocation.path + "/"); |
- } |
- packageLocation = baseLocation.resolveUri(packageLocation); |
- if (result.containsKey(packageName)) { |
- throw new FormatException( |
- "Same package name occured twice.", source, start); |
- } |
- result[packageName] = packageLocation; |
- } |
- return new Packages(result); |
- } |
- |
- /** |
- * Writes the mapping to a [StringSink]. |
- * |
- * If [comment] is provided, the output will contain this comment |
- * with `#` in front of each line. |
- * |
- * If [baseUri] is provided, package locations will be made relative |
- * to the base URI, if possible, before writing. |
- */ |
- void write(StringSink output, {Uri baseUri, String comment}) { |
- if (baseUri != null && !baseUri.isAbsolute) { |
- throw new ArgumentError.value(baseUri, "baseUri", "Must be absolute"); |
- } |
- |
- if (comment != null) { |
- for (var commentLine in comment.split('\n')) { |
- output.write('#'); |
- output.writeln(commentLine); |
- } |
- } else { |
- output.write("# generated by package:packagecfg at "); |
- output.write(new DateTime.now()); |
- output.writeln(); |
- } |
- |
- packageMapping.forEach((String packageName, Uri uri) { |
- // Validate packageName. |
- _checkIdentifier(packageName, 0, packageName.length); |
- output.write(packageName); |
- |
- output.write('='); |
- |
- // If baseUri provided, make uri relative. |
- if (baseUri != null) { |
- uri = relativize(uri, baseUri); |
- } |
- output.write(uri); |
- if (!uri.path.endsWith('/')) { |
- output.write('/'); |
- } |
- output.writeln(); |
- }); |
- } |
- |
- String toString() { |
- StringBuffer buffer = new StringBuffer(); |
- write(buffer); |
- return buffer.toString(); |
- } |
- |
- static Uri relativize(Uri uri, Uri baseUri) { |
- if (uri.hasQuery || uri.hasFragment) { |
- uri = new Uri( |
- scheme: uri.scheme, |
- userInfo: uri.hasAuthority ? uri.userInfo : null, |
- host: uri.hasAuthority ? uri.host : null, |
- port: uri.hasAuthority ? uri.port : null, |
- path: uri.path); |
- } |
- if (!baseUri.isAbsolute) { |
- throw new ArgumentError("Base uri '$baseUri' must be absolute."); |
- } |
- // Already relative. |
- if (!uri.isAbsolute) return uri; |
- |
- if (baseUri.scheme.toLowerCase() != uri.scheme.toLowerCase()) { |
- return uri; |
- } |
- // If authority differs, we could remove the scheme, but it's not worth it. |
- if (uri.hasAuthority != baseUri.hasAuthority) return uri; |
- if (uri.hasAuthority) { |
- if (uri.userInfo != baseUri.userInfo || |
- uri.host.toLowerCase() != baseUri.host.toLowerCase() || |
- uri.port != baseUri.port) { |
- return uri; |
- } |
- } |
- |
- baseUri = baseUri.normalizePath(); |
- List<String> base = baseUri.pathSegments.toList(); |
- if (base.isNotEmpty) { |
- base = new List<String>.from(base)..removeLast(); |
- } |
- uri = uri.normalizePath(); |
- List<String> target = uri.pathSegments.toList(); |
- int index = 0; |
- while (index < base.length && index < target.length) { |
- if (base[index] != target[index]) { |
- break; |
- } |
- index++; |
- } |
- if (index == base.length) { |
- return new Uri(path: target.skip(index).join('/')); |
- } else if (index > 0) { |
- return new Uri( |
- path: '../' * (base.length - index) + target.skip(index).join('/')); |
- } else { |
- return uri; |
- } |
- } |
- |
- static bool _checkIdentifier(String string, int start, int end) { |
- const int a = 0x61; |
- const int z = 0x7a; |
- const int _ = 0x5f; |
- const int $ = 0x24; |
- if (start == end) return false; |
- for (int i = start; i < end; i++) { |
- var char = string.codeUnitAt(i); |
- if (char == _ || char == $) continue; |
- if ((char ^ 0x30) <= 9 && i > 0) continue; |
- char |= 0x20; // Lower-case letters. |
- if (char >= a && char <= z) continue; |
- throw new FormatException("Not an identifier", string, i); |
- } |
- return true; |
- } |
-} |