| OLD | NEW |
| 1 // Copyright (c) 2013, 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 pub.source.path; | 1 library pub.source.path; |
| 6 | |
| 7 import 'dart:async'; | 2 import 'dart:async'; |
| 8 | |
| 9 import 'package:path/path.dart' as p; | 3 import 'package:path/path.dart' as p; |
| 10 | |
| 11 import '../exceptions.dart'; | 4 import '../exceptions.dart'; |
| 12 import '../io.dart'; | 5 import '../io.dart'; |
| 13 import '../package.dart'; | 6 import '../package.dart'; |
| 14 import '../pubspec.dart'; | 7 import '../pubspec.dart'; |
| 15 import '../source.dart'; | 8 import '../source.dart'; |
| 16 import '../utils.dart'; | 9 import '../utils.dart'; |
| 17 | |
| 18 /// A package [Source] that gets packages from a given local file path. | |
| 19 class PathSource extends Source { | 10 class PathSource extends Source { |
| 20 /// Returns a valid description for a reference to a package at [path]. | |
| 21 static describePath(String path) { | 11 static describePath(String path) { |
| 22 return { | 12 return { |
| 23 "path": path, | 13 "path": path, |
| 24 "relative": p.isRelative(path) | 14 "relative": p.isRelative(path) |
| 25 }; | 15 }; |
| 26 } | 16 } |
| 27 | |
| 28 /// Given a valid path reference description, returns the file path it | |
| 29 /// describes. | |
| 30 /// | |
| 31 /// This returned path may be relative or absolute and it is up to the caller | |
| 32 /// to know how to interpret a relative path. | |
| 33 static String pathFromDescription(description) => description["path"]; | 17 static String pathFromDescription(description) => description["path"]; |
| 34 | |
| 35 final name = 'path'; | 18 final name = 'path'; |
| 36 | |
| 37 Future<Pubspec> doDescribe(PackageId id) { | 19 Future<Pubspec> doDescribe(PackageId id) { |
| 38 return syncFuture(() { | 20 return syncFuture(() { |
| 39 var dir = _validatePath(id.name, id.description); | 21 var dir = _validatePath(id.name, id.description); |
| 40 return new Pubspec.load(dir, systemCache.sources, | 22 return new Pubspec.load(dir, systemCache.sources, expectedName: id.name); |
| 41 expectedName: id.name); | |
| 42 }); | 23 }); |
| 43 } | 24 } |
| 44 | |
| 45 bool descriptionsEqual(description1, description2) { | 25 bool descriptionsEqual(description1, description2) { |
| 46 // Compare real paths after normalizing and resolving symlinks. | |
| 47 var path1 = canonicalize(description1["path"]); | 26 var path1 = canonicalize(description1["path"]); |
| 48 var path2 = canonicalize(description2["path"]); | 27 var path2 = canonicalize(description2["path"]); |
| 49 return path1 == path2; | 28 return path1 == path2; |
| 50 } | 29 } |
| 51 | |
| 52 Future get(PackageId id, String symlink) { | 30 Future get(PackageId id, String symlink) { |
| 53 return syncFuture(() { | 31 return syncFuture(() { |
| 54 var dir = _validatePath(id.name, id.description); | 32 var dir = _validatePath(id.name, id.description); |
| 55 createPackageSymlink(id.name, dir, symlink, | 33 createPackageSymlink( |
| 34 id.name, |
| 35 dir, |
| 36 symlink, |
| 56 relative: id.description["relative"]); | 37 relative: id.description["relative"]); |
| 57 }); | 38 }); |
| 58 } | 39 } |
| 59 | |
| 60 Future<String> getDirectory(PackageId id) => | 40 Future<String> getDirectory(PackageId id) => |
| 61 newFuture(() => _validatePath(id.name, id.description)); | 41 newFuture(() => _validatePath(id.name, id.description)); |
| 62 | |
| 63 /// Parses a path dependency. | |
| 64 /// | |
| 65 /// This takes in a path string and returns a map. The "path" key will be the | |
| 66 /// original path but resolved relative to the containing path. The | |
| 67 /// "relative" key will be `true` if the original path was relative. | |
| 68 /// | |
| 69 /// A path coming from a pubspec is a simple string. From a lock file, it's | |
| 70 /// an expanded {"path": ..., "relative": ...} map. | |
| 71 dynamic parseDescription(String containingPath, description, | 42 dynamic parseDescription(String containingPath, description, |
| 72 {bool fromLockFile: false}) { | 43 {bool fromLockFile: false}) { |
| 73 if (fromLockFile) { | 44 if (fromLockFile) { |
| 74 if (description is! Map) { | 45 if (description is! Map) { |
| 75 throw new FormatException("The description must be a map."); | 46 throw new FormatException("The description must be a map."); |
| 76 } | 47 } |
| 77 | |
| 78 if (description["path"] is! String) { | 48 if (description["path"] is! String) { |
| 79 throw new FormatException("The 'path' field of the description must " | 49 throw new FormatException( |
| 80 "be a string."); | 50 "The 'path' field of the description must " "be a string."); |
| 81 } | 51 } |
| 82 | |
| 83 if (description["relative"] is! bool) { | 52 if (description["relative"] is! bool) { |
| 84 throw new FormatException("The 'relative' field of the description " | 53 throw new FormatException( |
| 85 "must be a boolean."); | 54 "The 'relative' field of the description " "must be a boolean."); |
| 86 } | 55 } |
| 87 | |
| 88 return description; | 56 return description; |
| 89 } | 57 } |
| 90 | |
| 91 if (description is! String) { | 58 if (description is! String) { |
| 92 throw new FormatException("The description must be a path string."); | 59 throw new FormatException("The description must be a path string."); |
| 93 } | 60 } |
| 94 | |
| 95 // Resolve the path relative to the containing file path, and remember | |
| 96 // whether the original path was relative or absolute. | |
| 97 var isRelative = p.isRelative(description); | 61 var isRelative = p.isRelative(description); |
| 98 if (p.isRelative(description)) { | 62 if (p.isRelative(description)) { |
| 99 // Can't handle relative paths coming from pubspecs that are not on the | |
| 100 // local file system. | |
| 101 assert(containingPath != null); | 63 assert(containingPath != null); |
| 102 | 64 description = p.normalize(p.join(p.dirname(containingPath), description)); |
| 103 description = p.normalize( | |
| 104 p.join(p.dirname(containingPath), description)); | |
| 105 } | 65 } |
| 106 | |
| 107 return { | 66 return { |
| 108 "path": description, | 67 "path": description, |
| 109 "relative": isRelative | 68 "relative": isRelative |
| 110 }; | 69 }; |
| 111 } | 70 } |
| 112 | |
| 113 /// Serializes path dependency's [description]. | |
| 114 /// | |
| 115 /// For the descriptions where `relative` attribute is `true`, tries to make | |
| 116 /// `path` relative to the specified [containingPath]. | |
| 117 dynamic serializeDescription(String containingPath, description) { | 71 dynamic serializeDescription(String containingPath, description) { |
| 118 if (description["relative"]) { | 72 if (description["relative"]) { |
| 119 return { | 73 return { |
| 120 "path": p.relative(description['path'], from: containingPath), | 74 "path": p.relative(description['path'], from: containingPath), |
| 121 "relative": true | 75 "relative": true |
| 122 }; | 76 }; |
| 123 } | 77 } |
| 124 return description; | 78 return description; |
| 125 } | 79 } |
| 126 | |
| 127 /// Converts a parsed relative path to its original relative form. | |
| 128 String formatDescription(String containingPath, description) { | 80 String formatDescription(String containingPath, description) { |
| 129 var sourcePath = description["path"]; | 81 var sourcePath = description["path"]; |
| 130 if (description["relative"]) { | 82 if (description["relative"]) { |
| 131 sourcePath = p.relative(description['path'], from: containingPath); | 83 sourcePath = p.relative(description['path'], from: containingPath); |
| 132 } | 84 } |
| 133 | |
| 134 return sourcePath; | 85 return sourcePath; |
| 135 } | 86 } |
| 136 | |
| 137 /// Ensures that [description] is a valid path description and returns a | |
| 138 /// normalized path to the package. | |
| 139 /// | |
| 140 /// It must be a map, with a "path" key containing a path that points to an | |
| 141 /// existing directory. Throws an [ApplicationException] if the path is | |
| 142 /// invalid. | |
| 143 String _validatePath(String name, description) { | 87 String _validatePath(String name, description) { |
| 144 var dir = description["path"]; | 88 var dir = description["path"]; |
| 145 | |
| 146 if (dirExists(dir)) return dir; | 89 if (dirExists(dir)) return dir; |
| 147 | |
| 148 if (fileExists(dir)) { | 90 if (fileExists(dir)) { |
| 149 fail('Path dependency for package $name must refer to a directory, ' | 91 fail( |
| 150 'not a file. Was "$dir".'); | 92 'Path dependency for package $name must refer to a directory, ' |
| 93 'not a file. Was "$dir".'); |
| 151 } | 94 } |
| 152 | |
| 153 throw new PackageNotFoundException( | 95 throw new PackageNotFoundException( |
| 154 'Could not find package $name at "$dir".'); | 96 'Could not find package $name at "$dir".'); |
| 155 } | 97 } |
| 156 } | 98 } |
| OLD | NEW |