3
3
// BSD-style license that can be found in the LICENSE file.
4
4
import 'dart:io' ;
5
5
6
+ import 'package:path/path.dart' as path;
6
7
import 'package:yaml/yaml.dart' ;
7
8
8
9
/// A graph of the package dependencies for an application.
@@ -16,19 +17,19 @@ class PackageGraph {
16
17
PackageGraph ._(this .root, Map <String , PackageNode > allPackages)
17
18
: allPackages = new Map .unmodifiable (allPackages);
18
19
19
- /// Creates a [PackageGraph] for the package in which you are currently
20
- /// running .
21
- factory PackageGraph .forThisPackage ( ) {
20
+ /// Creates a [PackageGraph] for the package whose top level directory lives
21
+ /// at [packagePath] (no trailing slash) .
22
+ factory PackageGraph .forPath ( String packagePath ) {
22
23
/// Read in the pubspec file and parse it as yaml.
23
- var pubspec = new File ('pubspec.yaml' );
24
+ var pubspec = new File (path. join (packagePath, 'pubspec.yaml' ) );
24
25
if (! pubspec.existsSync ()) {
25
26
throw 'Unable to generate package graph, no `pubspec.yaml` found. '
26
27
'This program must be ran from the root directory of your package.' ;
27
28
}
28
- var yaml = loadYaml (pubspec.readAsStringSync ());
29
+ var rootYaml = loadYaml (pubspec.readAsStringSync ());
29
30
30
31
/// Read in the `.packages` file to get the locations of all packages.
31
- var packagesFile = new File ('.packages' );
32
+ var packagesFile = new File (path. join (packagePath, '.packages' ) );
32
33
if (! packagesFile.existsSync ()) {
33
34
throw 'Unable to generate package graph, no `.packages` found. '
34
35
'This program must be ran from the root directory of your package.' ;
@@ -37,18 +38,26 @@ class PackageGraph {
37
38
packagesFile.readAsLinesSync ().skip (1 ).forEach ((line) {
38
39
var firstColon = line.indexOf (':' );
39
40
var name = line.substring (0 , firstColon);
40
- var uriString = line.substring (firstColon + 1 );
41
+ assert (line.endsWith ('lib${Platform .pathSeparator }' ));
42
+ // Start after package_name:, and strip out trailing `lib` dir.
43
+ var uriString = line.substring (firstColon + 1 , line.length - 4 );
44
+ var uri;
41
45
try {
42
- packageLocations[name] = Uri .parse (uriString);
46
+ uri = Uri .parse (uriString);
43
47
} on FormatException catch (_) {
44
48
/// Some types of deps don't have a scheme, and just point to a relative
45
49
/// path.
46
- packageLocations[name] = new Uri .file (uriString);
50
+ uri = new Uri .file (uriString);
47
51
}
52
+ if (! uri.isAbsolute) {
53
+ uri = new Uri .file (path.join (packagePath, uri.path));
54
+ }
55
+ packageLocations[name] = uri;
48
56
});
49
57
50
58
/// Create all [PackageNode] s for all deps.
51
59
var nodes = < String , PackageNode > {};
60
+ Map <String , dynamic > rootDeps;
52
61
PackageNode addNodeAndDeps (YamlMap yaml, PackageDependencyType type,
53
62
{bool isRoot: false }) {
54
63
var name = yaml['name' ];
@@ -57,24 +66,31 @@ class PackageGraph {
57
66
name, yaml['version' ], type, packageLocations[name]);
58
67
nodes[name] = node;
59
68
60
- _depsFromYaml (yaml, withOverrides: isRoot).forEach ((name, source) {
69
+ var deps = _depsFromYaml (yaml, withOverrides: isRoot);
70
+ if (isRoot) rootDeps = deps;
71
+ deps.forEach ((name, source) {
61
72
var dep = nodes[name];
62
73
if (dep == null ) {
63
74
var pubspec = _pubspecForUri (packageLocations[name]);
64
- dep = addNodeAndDeps (pubspec, _dependencyType (source ));
75
+ dep = addNodeAndDeps (pubspec, _dependencyType (rootDeps[name] ));
65
76
}
66
77
node._dependencies.add (dep);
67
78
});
68
79
69
80
return node;
70
81
}
71
82
72
- var root = addNodeAndDeps (yaml, PackageDependencyType .Path , isRoot: true );
83
+ var root =
84
+ addNodeAndDeps (rootYaml, PackageDependencyType .Path , isRoot: true );
73
85
return new PackageGraph ._(root, nodes);
74
86
}
75
87
88
+ /// Creates a [PackageGraph] for the package in which you are currently
89
+ /// running.
90
+ factory PackageGraph .forThisPackage () => new PackageGraph .forPath ('.' );
91
+
76
92
/// Shorthand to get a package by name.
77
- PackageNode operator [] (String packageName) => allPackages[packageName];
93
+ PackageNode operator [] (String packageName) => allPackages[packageName];
78
94
79
95
String toString () {
80
96
var buffer = new StringBuffer ();
@@ -118,7 +134,7 @@ class PackageNode {
118
134
enum PackageDependencyType { Pub , Github , Path , }
119
135
120
136
PackageDependencyType _dependencyType (source) {
121
- if (source is String ) return PackageDependencyType .Pub ;
137
+ if (source is String || source == null ) return PackageDependencyType .Pub ;
122
138
123
139
assert (source is YamlMap );
124
140
assert (source.keys.length == 1 );
@@ -145,14 +161,9 @@ Map<String, YamlMap> _depsFromYaml(YamlMap yaml, {bool withOverrides: false}) {
145
161
return deps;
146
162
}
147
163
148
- /// [uri] should be directly from a `.packages` file, and points to the `lib`
149
- /// dir.
164
+ /// [uri] should point to the top level directory for the package.
150
165
YamlMap _pubspecForUri (Uri uri) {
151
- var libPath = uri.toFilePath ();
152
- assert (libPath.endsWith ('lib/' ));
153
- var pubspecPath =
154
- libPath.replaceRange (libPath.length - 4 , libPath.length, 'pubspec.yaml' );
155
-
166
+ var pubspecPath = path.join (uri.toFilePath (), 'pubspec.yaml' );
156
167
var pubspec = new File (pubspecPath);
157
168
if (! pubspec.existsSync ()) {
158
169
throw 'Unable to generate package graph, no `$pubspecPath ` found.' ;
0 commit comments