Skip to content

Commit fea7927

Browse files
0. implement topological pub get
1. add test filename 2. fix doc
1 parent 5976b3a commit fea7927

7 files changed

+119
-45
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -13,3 +13,5 @@ doc/api/
1313
.idea/
1414

1515
**/*.iml
16+
.devcontainer/*
17+
.vscode/*

CHANGELOG.md

+4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 0.1.5
2+
3+
- fix #2,implementing topologicalOrdering pub get
4+
15
## 0.1.4
26

37
- implement info command to print GraphViz dor file

README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ multipack create gql_link gql_local_state_link --version 0.1.0 --in ./links/
155155
multipack test
156156
multipack test --coverage
157157
multipack build
158-
multipack clean
158+
multipack pubspec clean
159159
```
160160

161161
### `singlepack`

bin/multipack.dart

+16-5
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,14 @@
11
import "dart:io";
22

33
import "package:args/command_runner.dart";
4+
import "package:directed_graph/directed_graph.dart";
45
import "package:multipack/commands.dart";
56
import "package:multipack/package.dart";
67

78
void main(List<String> arguments) async {
8-
final dependencyGraph = await getPackageGraph(Directory.current);
9-
10-
final orderedPackages = dependencyGraph.sortedTopologicalOrdering.reversed
11-
.map((vertex) => vertex.data)
12-
.toList();
9+
final DirectedGraph<Package> dependencyGraph =
10+
await getPackageGraph(Directory.current);
11+
final List<Package> orderedPackages = getOrderdPackages(dependencyGraph);
1312

1413
final packageNames = orderedPackages
1514
.map(
@@ -55,3 +54,15 @@ void main(List<String> arguments) async {
5554

5655
await runner.run(arguments);
5756
}
57+
58+
List<Package> getOrderdPackages(DirectedGraph<Package> dependencyGraph) {
59+
final List<Package> packages =
60+
dependencyGraph.edgeMap.keys.map((vertex) => vertex.data).toList();
61+
final topologicalOrdering = dependencyGraph.sortedTopologicalOrdering.reversed
62+
.map((vertex) => vertex.data)
63+
.toList();
64+
final freeDependentPackages =
65+
packages.toSet().difference(topologicalOrdering.toSet());
66+
final orderedPackages = [...topologicalOrdering, ...freeDependentPackages];
67+
return orderedPackages;
68+
}

lib/package.dart

+55-36
Original file line numberDiff line numberDiff line change
@@ -156,29 +156,37 @@ class Package {
156156
String toString() => name;
157157
}
158158

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+
}
182190

183191
Stream<Directory> findPackageDirectories(Directory root) => root
184192
.list(recursive: true)
@@ -192,28 +200,39 @@ Stream<Directory> findPackageDirectories(Directory root) => root
192200
(pubspec) => pubspec.parent.absolute,
193201
);
194202

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`
195208
Future<DirectedGraph<Package>> getPackageGraph(Directory root) async {
196-
final vertices = await findPackages(root)
209+
final heads = await findPackages(root)
197210
.map((package) => Vertex<Package>(package))
198211
.toList();
199212

213+
final edges = getEdges(heads);
214+
200215
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,
213217
comparator: (
214218
Vertex<Package> vertex1,
215219
Vertex<Package> vertex2,
216220
) =>
217221
vertex1.data.name.compareTo(vertex2.data.name),
218222
);
219223
}
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+
}

pubspec.yaml

+5-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
name: multipack
22
description: A tool for monorepo management. Link local packages and execute commands in topological order.
3-
version: 0.1.4
3+
version: 0.1.5
44
homepage: https://github.com/gql-dart/multipack
55
environment:
66
sdk: '>=2.8.0 <3.0.0'
@@ -9,10 +9,12 @@ dependencies:
99
args: ^1.6.0
1010
directed_graph: ^0.2.3
1111
meta: ^1.0.0
12-
pubspec: ^0.1.2
13-
pub_semver: ^1.4.4
1412
path: ^1.6.4
13+
pub_semver: ^1.4.4
14+
pubspec: ^0.1.2
1515
dev_dependencies:
1616
gql_pedantic: ^1.0.1
17+
test: ^1.9.4
18+
1719
executables:
1820
multipack: null

test/get_namespace_test.dart

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import "dart:io";
2+
import "package:test/test.dart";
3+
import "package:multipack/package.dart";
4+
5+
void main() {
6+
// group("get namespace", () {
7+
test("pubspec just in root", () {
8+
const String rootPath = "/root";
9+
const String dirPath = "/root";
10+
11+
const rootIndex = rootPath.length;
12+
final int dirIndex = dirPath.lastIndexOf(Platform.pathSeparator);
13+
expect(getNamespace(dirPath, rootIndex, dirIndex), "");
14+
});
15+
16+
// To keep it As before
17+
test("pubspec in subdir of root", () {
18+
const String rootPath = "/root";
19+
const String dirPath = "/root/dir1";
20+
21+
const int rootIndex = rootPath.length;
22+
final int dirIndex = dirPath.lastIndexOf(Platform.pathSeparator);
23+
expect(getNamespace(dirPath, rootIndex, dirIndex), "");
24+
});
25+
26+
// To keep it As before
27+
test("pubspec in Sun of fold", () {
28+
const String rootPath = "/root";
29+
const String dirPath = "/root/dir1/dir2";
30+
31+
const int rootIndex = rootPath.length;
32+
final int dirIndex = dirPath.lastIndexOf(Platform.pathSeparator);
33+
expect(getNamespace(dirPath, rootIndex, dirIndex), "dir1");
34+
});
35+
// });
36+
}

0 commit comments

Comments
 (0)