@@ -156,29 +156,37 @@ class Package {
156
156
String toString () => name;
157
157
}
158
158
159
- Stream <Package > findPackages (Directory root) =>
160
- findPackageDirectories (root).asyncMap (
161
- (dir) async {
162
- final pubspec = await PubSpec .load (dir);
163
-
164
- final dirPath = dir.path;
165
- final rootPath = root.path;
166
-
167
- final rootIndex = rootPath.length;
168
- final dirIndex = dirPath.lastIndexOf (Platform .pathSeparator);
169
-
170
- return Package (
171
- directory: dir,
172
- namespace: dirPath.substring (
173
- rootIndex == dirIndex ? rootIndex : rootIndex + 1 ,
174
- dirIndex,
175
- ),
176
- name: pubspec.name,
177
- isFlutter: pubspec.allDependencies.containsKey ("flutter" ),
178
- pubspec: pubspec,
179
- );
180
- },
181
- );
159
+ Stream <Package > findPackages (Directory root) {
160
+ final rootPath = root.path;
161
+ final rootIndex = rootPath.length;
162
+ return findPackageDirectories (root).asyncMap (
163
+ (dir) async {
164
+ final pubspec = await PubSpec .load (dir);
165
+
166
+ final dirPath = dir.path;
167
+ final dirIndex = dirPath.lastIndexOf (Platform .pathSeparator);
168
+
169
+ return Package (
170
+ directory: dir,
171
+ namespace: getNamespace (dirPath, rootIndex, dirIndex),
172
+ name: pubspec.name,
173
+ isFlutter: pubspec.allDependencies.containsKey ("flutter" ),
174
+ pubspec: pubspec,
175
+ );
176
+ },
177
+ );
178
+ }
179
+
180
+ /// The test case(`get_namespace.test.dart` ) shows possible DIRPATH situations
181
+ String getNamespace (String dirPath, int rootIndex, int dirIndex) {
182
+ int namespaceStartIndex = rootIndex == dirIndex ? rootIndex : rootIndex + 1 ;
183
+ if (namespaceStartIndex > dirIndex) namespaceStartIndex = dirIndex;
184
+
185
+ return dirPath.substring (
186
+ namespaceStartIndex,
187
+ dirIndex,
188
+ );
189
+ }
182
190
183
191
Stream <Directory > findPackageDirectories (Directory root) => root
184
192
.list (recursive: true )
@@ -192,28 +200,39 @@ Stream<Directory> findPackageDirectories(Directory root) => root
192
200
(pubspec) => pubspec.parent.absolute,
193
201
);
194
202
203
+ /// step1: Get all packages as `heads` through `findPackages` .
204
+ /// It can be converted to a dependency graph,
205
+ /// whose head is in `heads` and tail is in `heads.data.pubspec.dependencies`
206
+ /// step2: Find a subgraph from dependency graph.
207
+ /// The tail of that subgraph is in `heads`
195
208
Future <DirectedGraph <Package >> getPackageGraph (Directory root) async {
196
- final vertices = await findPackages (root)
209
+ final heads = await findPackages (root)
197
210
.map ((package) => Vertex <Package >(package))
198
211
.toList ();
199
212
213
+ final edges = getEdges (heads);
214
+
200
215
return DirectedGraph <Package >(
201
- {
202
- for (var vertex in vertices)
203
- vertex: vertex.data.pubspec.allDependencies.keys
204
- .map (
205
- (dep) => vertices.firstWhere (
206
- (v) => v.data.name == dep,
207
- orElse: () => null ,
208
- ),
209
- )
210
- .where ((v) => v != null )
211
- .toList (),
212
- },
216
+ edges,
213
217
comparator: (
214
218
Vertex <Package > vertex1,
215
219
Vertex <Package > vertex2,
216
220
) =>
217
221
vertex1.data.name.compareTo (vertex2.data.name),
218
222
);
219
223
}
224
+
225
+ Map <Vertex <Package >, List <Vertex <Package >>> getEdges (
226
+ List <Vertex <Package >> heads) {
227
+ final headsMap = Map .fromIterables (heads.map ((e) => e.data.name), heads);
228
+ return {
229
+ for (Vertex <Package > head in heads)
230
+ // head: tail
231
+ head: head.data.pubspec.dependencies.keys
232
+ .map (
233
+ (dep) => headsMap.containsKey (dep) ? headsMap[dep] : null ,
234
+ )
235
+ .where ((v) => v != null )
236
+ .toList (),
237
+ };
238
+ }
0 commit comments