Skip to content

Commit

Permalink
Support for resolving package config and pubspec.lock in workspaces (#…
Browse files Browse the repository at this point in the history
…3684)

Instead of expecting pubspec.lock and .dart_tool/package_config.json to reside in the same folder as pubspec.yaml, we visit each parent of the current directory until we find a .dart_tool/package_config.json, and expect pubspec.lock to exist next to that.

Also invoke the generated scripts with an explicit packageConfig.

This is to support running build_runner build in a workspace package, as implemented in dart-lang/pub#4127

---------

Co-authored-by: Jake Macdonald <jakemac@google.com>
  • Loading branch information
sigurdm and jakemac53 committed Jun 4, 2024
1 parent 264dee9 commit b6b4a21
Show file tree
Hide file tree
Showing 11 changed files with 118 additions and 5 deletions.
3 changes: 3 additions & 0 deletions build_runner/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
## 2.4.11-wip

- Explicitly pass the current isolates package config instead of assuming the
location, to support the upcoming pub workspaces feature.

## 2.4.10

- Support version `1.x` and `2.x` of `shelf_web_socket` and `2.x` and `3.x`
Expand Down
1 change: 1 addition & 0 deletions build_runner/lib/src/build_script_generate/bootstrap.dart
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ Future<int> _createKernelIfNeeded(
'lib/_internal/vm_platform_strong.dill',
enabledExperiments: experiments,
printIncrementalDependencies: false,
packagesJson: (await Isolate.packageConfig)!.toFilePath(),
);

var hadOutput = false;
Expand Down
1 change: 1 addition & 0 deletions build_runner_core/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
## 7.3.1-wip

- Support the upcoming pub workspaces feature.
- Bump the min sdk to 3.4.0.
- Remove some unnecessary casts and non-null assertions now that we have private
field promotion.
Expand Down
33 changes: 28 additions & 5 deletions build_runner_core/lib/src/package_graph/package_graph.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,35 @@ class PackageGraph {
'pubspec.yaml.');
}

final packageConfig =
await findPackageConfig(Directory(packagePath), recurse: false);
// The path of the directory that contains .dart_tool/package_config.json.
//
// Should also contain `pubspec.lock`.
var rootDir = packagePath;
PackageConfig? packageConfig;
// Manually recurse through parent directories, to obtain the [rootDir]
// where a package config was found. It doesn't seem possible to obtain this
// directly with package:package_config.
while (true) {
packageConfig =
await findPackageConfig(Directory(rootDir), recurse: false);
File(p.join(rootDir, '.dart_tool', 'package_config.json'));
if (packageConfig != null) {
break;
}
final next = p.dirname(rootDir);
if (next == rootDir) {
// We have reached the file system root.
break;
}
rootDir = next;
}

if (packageConfig == null) {
throw StateError(
'Unable to find package config for package at $packagePath.');
}

final dependencyTypes = _parseDependencyTypes(packagePath);
final dependencyTypes = _parseDependencyTypes(rootDir);

final nodes = <String, PackageNode>{};
// A consistent package order _should_ mean a consistent order of build
Expand All @@ -94,11 +115,13 @@ class PackageGraph {
final consistentlyOrderedPackages = packageConfig.packages.toList()
..sort((a, b) => a.name.compareTo(b.name));
for (final package in consistentlyOrderedPackages) {
var isRoot = package.name == rootPackageName;
final isRoot = package.name == rootPackageName;
nodes[package.name] = PackageNode(
package.name,
package.root.toFilePath(),
isRoot ? DependencyType.path : dependencyTypes[package.name],
// If the package is missing from pubspec.lock, assume it is a path
// dependency.
dependencyTypes[package.name] ?? DependencyType.path,
package.languageVersion,
isRoot: isRoot);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"configVersion": 2,
"packages": [
{
"name": "workspace",
"rootUri": "../",
"packageUri": "lib/",
"languageVersion": "3.5"
},
{
"name": "a",
"rootUri": "../pkgs/a",
"packageUri": "lib/",
"languageVersion": "3.5"
},
{
"name": "b",
"rootUri": "../pkgs/b",
"packageUri": "lib/",
"languageVersion": "3.5"
}
]
}
5 changes: 5 additions & 0 deletions build_runner_core/test/fixtures/workspace/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Take special care to include the .dart_tool/package_config.json
#
!.dart_tool
.dart_tool/*
!.dart_tool/package_config.json
6 changes: 6 additions & 0 deletions build_runner_core/test/fixtures/workspace/pkgs/a/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: a
environment:
sdk: ^3.5.0-0
resolution: workspace
dependencies:
b:
4 changes: 4 additions & 0 deletions build_runner_core/test/fixtures/workspace/pkgs/b/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
name: b
environment:
sdk: ^3.5.0-0
resolution: workspace
5 changes: 5 additions & 0 deletions build_runner_core/test/fixtures/workspace/pubspec.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Generated by pub
# See https://dart.dev/tools/pub/glossary#lockfile
packages: {}
sdks:
dart: ">=3.5.0-0 <4.0.0"
6 changes: 6 additions & 0 deletions build_runner_core/test/fixtures/workspace/pubspec.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
name: workspace
environment:
sdk: ^3.5.0-0
workspace:
- pkgs/a
- pkgs/b
36 changes: 36 additions & 0 deletions build_runner_core/test/package_graph/package_graph_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,42 @@ void main() {
throwsA(anything));
});
});

group('workspace ', () {
var workspaceFixturePath = 'test/fixtures/workspace';

test('Loads all packages in workspace. Has correct root', () async {
Matcher packageNodeEquals(PackageNode node) => isA<PackageNode>()
.having((c) => c.path, 'path', node.path)
.having((c) => c.dependencies, 'dependencies',
node.dependencies.map(packageNodeEquals))
.having(
(c) => c.dependencyType, 'dependencyType', node.dependencyType);

final graph = await PackageGraph.forPath('$workspaceFixturePath/pkgs/a');
var a = PackageNode(
'a', '$workspaceFixturePath/pkgs/a', DependencyType.path, null,
isRoot: true);
var b = PackageNode(
'b', '$workspaceFixturePath/pkgs/b', DependencyType.path, null);
a.dependencies.add(b);
var workspace = PackageNode(
'workspace',
workspaceFixturePath,
DependencyType.path,
null,
);

expect(graph.allPackages, {
'a': packageNodeEquals(a),
'b': packageNodeEquals(b),
'workspace': packageNodeEquals(workspace),
r'$sdk': anything
});

expect(graph.root, packageNodeEquals(a));
});
});
}

void expectPkg(PackageNode node, String name, String location,
Expand Down

0 comments on commit b6b4a21

Please sign in to comment.