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 |