From fea7927093d0651cab84d609642e803b93ca28f8 Mon Sep 17 00:00:00 2001 From: huang12zheng Date: Fri, 12 Feb 2021 00:24:35 +0000 Subject: [PATCH 1/2] 0. implement topological pub get 1. add test filename 2. fix doc --- .gitignore | 2 + CHANGELOG.md | 4 ++ README.md | 2 +- bin/multipack.dart | 21 +++++++-- lib/package.dart | 91 ++++++++++++++++++++++-------------- pubspec.yaml | 8 ++-- test/get_namespace_test.dart | 36 ++++++++++++++ 7 files changed, 119 insertions(+), 45 deletions(-) create mode 100644 test/get_namespace_test.dart diff --git a/.gitignore b/.gitignore index 2708a6b..6adf89b 100644 --- a/.gitignore +++ b/.gitignore @@ -13,3 +13,5 @@ doc/api/ .idea/ **/*.iml +.devcontainer/* +.vscode/* diff --git a/CHANGELOG.md b/CHANGELOG.md index 4818e4e..2727aa2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +## 0.1.5 + +- fix #2,implementing topologicalOrdering pub get + ## 0.1.4 - implement info command to print GraphViz dor file diff --git a/README.md b/README.md index 3b93dd0..8122938 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,7 @@ multipack create gql_link gql_local_state_link --version 0.1.0 --in ./links/ multipack test multipack test --coverage multipack build -multipack clean +multipack pubspec clean ``` ### `singlepack` diff --git a/bin/multipack.dart b/bin/multipack.dart index ae4d42c..1a30e59 100644 --- a/bin/multipack.dart +++ b/bin/multipack.dart @@ -1,15 +1,14 @@ import "dart:io"; import "package:args/command_runner.dart"; +import "package:directed_graph/directed_graph.dart"; import "package:multipack/commands.dart"; import "package:multipack/package.dart"; void main(List arguments) async { - final dependencyGraph = await getPackageGraph(Directory.current); - - final orderedPackages = dependencyGraph.sortedTopologicalOrdering.reversed - .map((vertex) => vertex.data) - .toList(); + final DirectedGraph dependencyGraph = + await getPackageGraph(Directory.current); + final List orderedPackages = getOrderdPackages(dependencyGraph); final packageNames = orderedPackages .map( @@ -55,3 +54,15 @@ void main(List arguments) async { await runner.run(arguments); } + +List getOrderdPackages(DirectedGraph dependencyGraph) { + final List packages = + dependencyGraph.edgeMap.keys.map((vertex) => vertex.data).toList(); + final topologicalOrdering = dependencyGraph.sortedTopologicalOrdering.reversed + .map((vertex) => vertex.data) + .toList(); + final freeDependentPackages = + packages.toSet().difference(topologicalOrdering.toSet()); + final orderedPackages = [...topologicalOrdering, ...freeDependentPackages]; + return orderedPackages; +} diff --git a/lib/package.dart b/lib/package.dart index d0b2222..a22ebfe 100644 --- a/lib/package.dart +++ b/lib/package.dart @@ -156,29 +156,37 @@ class Package { String toString() => name; } -Stream findPackages(Directory root) => - findPackageDirectories(root).asyncMap( - (dir) async { - final pubspec = await PubSpec.load(dir); - - final dirPath = dir.path; - final rootPath = root.path; - - final rootIndex = rootPath.length; - final dirIndex = dirPath.lastIndexOf(Platform.pathSeparator); - - return Package( - directory: dir, - namespace: dirPath.substring( - rootIndex == dirIndex ? rootIndex : rootIndex + 1, - dirIndex, - ), - name: pubspec.name, - isFlutter: pubspec.allDependencies.containsKey("flutter"), - pubspec: pubspec, - ); - }, - ); +Stream findPackages(Directory root) { + final rootPath = root.path; + final rootIndex = rootPath.length; + return findPackageDirectories(root).asyncMap( + (dir) async { + final pubspec = await PubSpec.load(dir); + + final dirPath = dir.path; + final dirIndex = dirPath.lastIndexOf(Platform.pathSeparator); + + return Package( + directory: dir, + namespace: getNamespace(dirPath, rootIndex, dirIndex), + name: pubspec.name, + isFlutter: pubspec.allDependencies.containsKey("flutter"), + pubspec: pubspec, + ); + }, + ); +} + +/// The test case(`get_namespace.test.dart`) shows possible DIRPATH situations +String getNamespace(String dirPath, int rootIndex, int dirIndex) { + int namespaceStartIndex = rootIndex == dirIndex ? rootIndex : rootIndex + 1; + if (namespaceStartIndex > dirIndex) namespaceStartIndex = dirIndex; + + return dirPath.substring( + namespaceStartIndex, + dirIndex, + ); +} Stream findPackageDirectories(Directory root) => root .list(recursive: true) @@ -192,24 +200,20 @@ Stream findPackageDirectories(Directory root) => root (pubspec) => pubspec.parent.absolute, ); +/// step1: Get all packages as `heads` through `findPackages`. +/// It can be converted to a dependency graph, +/// whose head is in `heads` and tail is in `heads.data.pubspec.dependencies` +/// step2: Find a subgraph from dependency graph. +/// The tail of that subgraph is in `heads` Future> getPackageGraph(Directory root) async { - final vertices = await findPackages(root) + final heads = await findPackages(root) .map((package) => Vertex(package)) .toList(); + final edges = getEdges(heads); + return DirectedGraph( - { - for (var vertex in vertices) - vertex: vertex.data.pubspec.allDependencies.keys - .map( - (dep) => vertices.firstWhere( - (v) => v.data.name == dep, - orElse: () => null, - ), - ) - .where((v) => v != null) - .toList(), - }, + edges, comparator: ( Vertex vertex1, Vertex vertex2, @@ -217,3 +221,18 @@ Future> getPackageGraph(Directory root) async { vertex1.data.name.compareTo(vertex2.data.name), ); } + +Map, List>> getEdges( + List> heads) { + final headsMap = Map.fromIterables(heads.map((e) => e.data.name), heads); + return { + for (Vertex head in heads) + // head: tail + head: head.data.pubspec.dependencies.keys + .map( + (dep) => headsMap.containsKey(dep) ? headsMap[dep] : null, + ) + .where((v) => v != null) + .toList(), + }; +} diff --git a/pubspec.yaml b/pubspec.yaml index 423bd6c..4b4aaab 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,6 +1,6 @@ name: multipack description: A tool for monorepo management. Link local packages and execute commands in topological order. -version: 0.1.4 +version: 0.1.5 homepage: https://github.com/gql-dart/multipack environment: sdk: '>=2.8.0 <3.0.0' @@ -9,10 +9,12 @@ dependencies: args: ^1.6.0 directed_graph: ^0.2.3 meta: ^1.0.0 - pubspec: ^0.1.2 - pub_semver: ^1.4.4 path: ^1.6.4 + pub_semver: ^1.4.4 + pubspec: ^0.1.2 dev_dependencies: gql_pedantic: ^1.0.1 + test: ^1.9.4 + executables: multipack: null diff --git a/test/get_namespace_test.dart b/test/get_namespace_test.dart new file mode 100644 index 0000000..4a383f8 --- /dev/null +++ b/test/get_namespace_test.dart @@ -0,0 +1,36 @@ +import "dart:io"; +import "package:test/test.dart"; +import "package:multipack/package.dart"; + +void main() { + // group("get namespace", () { + test("pubspec just in root", () { + const String rootPath = "/root"; + const String dirPath = "/root"; + + const rootIndex = rootPath.length; + final int dirIndex = dirPath.lastIndexOf(Platform.pathSeparator); + expect(getNamespace(dirPath, rootIndex, dirIndex), ""); + }); + + // To keep it As before + test("pubspec in subdir of root", () { + const String rootPath = "/root"; + const String dirPath = "/root/dir1"; + + const int rootIndex = rootPath.length; + final int dirIndex = dirPath.lastIndexOf(Platform.pathSeparator); + expect(getNamespace(dirPath, rootIndex, dirIndex), ""); + }); + + // To keep it As before + test("pubspec in Sun of fold", () { + const String rootPath = "/root"; + const String dirPath = "/root/dir1/dir2"; + + const int rootIndex = rootPath.length; + final int dirIndex = dirPath.lastIndexOf(Platform.pathSeparator); + expect(getNamespace(dirPath, rootIndex, dirIndex), "dir1"); + }); + // }); +} From 2a0635b5ca659360f90ba9264de9dbe8a8973eec Mon Sep 17 00:00:00 2001 From: huang12zheng Date: Fri, 12 Feb 2021 11:25:43 +0800 Subject: [PATCH 2/2] fix git workflow bug --- .github/workflows/dart.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml index 7c9a6d9..d09df15 100644 --- a/.github/workflows/dart.yml +++ b/.github/workflows/dart.yml @@ -28,5 +28,5 @@ jobs: dartanalyzer --fatal-warnings --no-hints . - name: Run tests run: | - exec [ ! -d ./test ] && exit 0 + `exec [ ! -d ./test ]` && exit 0 pub run test