diff --git a/dwds/CHANGELOG.md b/dwds/CHANGELOG.md index b81c8d3db..6cfd966c0 100644 --- a/dwds/CHANGELOG.md +++ b/dwds/CHANGELOG.md @@ -12,6 +12,7 @@ restart. - Remove verbose printing on receiving DevTools events. - Update `vm_service` version to `^8.2.0`. +- Migrate .packages to package_config.json. - Update error message on expression evaluation using unloaded libraries. **Breaking changes:** diff --git a/dwds/lib/src/readers/frontend_server_asset_reader.dart b/dwds/lib/src/readers/frontend_server_asset_reader.dart index c44cedb0b..f11616208 100644 --- a/dwds/lib/src/readers/frontend_server_asset_reader.dart +++ b/dwds/lib/src/readers/frontend_server_asset_reader.dart @@ -37,8 +37,8 @@ class FrontendServerAssetReader implements AssetReader { /// Corresponding `.json` and `.map` files will be read relative to /// [outputPath]. /// - /// [_packageRoot] is the path to the directory that contains a `.packages` - /// file for the application. + /// [_packageRoot] is the path to the directory that contains a + /// `.dart_tool/package_config.json` file for the application. FrontendServerAssetReader( String outputPath, this._packageRoot, @@ -46,8 +46,8 @@ class FrontendServerAssetReader implements AssetReader { _mapIncremental = File('$outputPath.incremental.map'), _jsonOriginal = File('$outputPath.json'), _jsonIncremental = File('$outputPath.incremental.json'), - _packageConfig = loadPackageConfig( - File(p.absolute(p.join(_packageRoot, '.packages')))); + _packageConfig = loadPackageConfig(File(p + .absolute(p.join(_packageRoot, '.dart_tool/package_config.json')))); @override Future dartSourceContents(String serverPath) async { diff --git a/dwds/lib/src/utilities/dart_uri.dart b/dwds/lib/src/utilities/dart_uri.dart index 4d3fb35cf..9903950af 100644 --- a/dwds/lib/src/utilities/dart_uri.dart +++ b/dwds/lib/src/utilities/dart_uri.dart @@ -157,7 +157,8 @@ class DartUri { /// Record library and script uris to enable resolving library and script paths. static Future initialize(SdkConfiguration sdkConfiguration) async { _sdkConfiguration = sdkConfiguration; - var packagesUri = p.toUri(p.join(currentDirectory, '.packages')); + var packagesUri = + p.toUri(p.join(currentDirectory, '.dart_tool/package_config.json')); clear(); @@ -190,8 +191,8 @@ class DartUri { /// Returns the dirname for the server URI. static String _dirForServerUri(String uri) => p.dirname(Uri.parse(uri).path); - /// Load the .packages file associated with the running application so we can - /// resolve file URLs into package: URLs appropriately. + /// Load the .dart_tool/package_config.json file associated with the running + /// application so we can resolve file URLs into package: URLs appropriately. static Future _loadPackageConfig(Uri uri) async { _packageConfig = await loadPackageConfigUri(uri, onError: (e) { _logger.warning('Cannot read packages spec: $uri', e); diff --git a/dwds/test/fixtures/context.dart b/dwds/test/fixtures/context.dart index e0b483713..b6395054a 100644 --- a/dwds/test/fixtures/context.dart +++ b/dwds/test/fixtures/context.dart @@ -98,11 +98,17 @@ class TestContext { .absolute(directory ?? p.relative(relativeDirectory, from: p.current))); DartUri.currentDirectory = workingDirectory; - _packagesFilePath = p.join(workingDirectory, '.packages'); + _packagesFilePath = + p.join(workingDirectory, '.dart_tool/package_config.json'); - _entryFile = File(p.normalize( - p.absolute(entry ?? p.relative(relativeEntry, from: p.current)))); + var entryFilePath = p.normalize( + p.absolute(entry ?? p.relative(relativeEntry, from: p.current))); + _logger.info('Serving: $pathToServe/$path'); + _logger.info('Packages: $_packagesFilePath'); + _logger.info('Entry: $entryFilePath'); + + _entryFile = File(entryFilePath); _entryContents = _entryFile.readAsStringSync(); } @@ -241,15 +247,14 @@ class TestContext { case CompilationMode.frontendServer: { soundNullSafety ??= true; - var fileSystemRoot = p.dirname(_packagesFilePath); + var projectDirectory = p.dirname(p.dirname(_packagesFilePath)); var entryPath = - _entryFile.path.substring(fileSystemRoot.length + 1); + _entryFile.path.substring(projectDirectory.length + 1); webRunner = ResidentWebRunner( '${Uri.file(entryPath)}', urlEncoder, - fileSystemRoot, _packagesFilePath, - [fileSystemRoot], + [projectDirectory], 'org-dartlang-app', _outputDir.path, verboseCompiler); diff --git a/dwds/test/frontend_server_breakpoint_test.dart b/dwds/test/frontend_server_breakpoint_test.dart index cd0a8a2c5..54cfe877b 100644 --- a/dwds/test/frontend_server_breakpoint_test.dart +++ b/dwds/test/frontend_server_breakpoint_test.dart @@ -15,6 +15,7 @@ import 'package:vm_service/vm_service.dart'; import 'package:webkit_inspection_protocol/webkit_inspection_protocol.dart'; import 'fixtures/context.dart'; +import 'fixtures/logging.dart'; final context = TestContext( directory: p.join('..', 'fixtures', '_testPackage'), @@ -27,10 +28,22 @@ ChromeProxyService get service => WipConnection get tabConnection => context.tabConnection; void main() { + // Enable verbose logging for debugging. + var debug = false; + + // Change to 'true' to print expression compiler messages to console. + // + // Note: expression compiler runs in an isolate, so its output is not + // currently redirected to a logger. As a result, it will be printed + // regardless of the logger settings. + var verboseCompiler = false; + group('shared context', () { setUpAll(() async { + setCurrentLogWriter(debug: debug); await context.setUp( compilationMode: CompilationMode.frontendServer, + verboseCompiler: verboseCompiler, ); }); @@ -46,6 +59,7 @@ void main() { Stream stream; setUp(() async { + setCurrentLogWriter(debug: debug); vm = await service.getVM(); isolate = await service.getIsolate(vm.isolates.first.id); scripts = await service.getScripts(isolate.id); diff --git a/frontend_server_common/lib/src/asset_server.dart b/frontend_server_common/lib/src/asset_server.dart index 756d489f7..776e35e6a 100644 --- a/frontend_server_common/lib/src/asset_server.dart +++ b/frontend_server_common/lib/src/asset_server.dart @@ -27,7 +27,7 @@ class TestAssetServer implements AssetReader { TestAssetServer( this._root, this._httpServer, - this._packages, + this._packageConfig, this.internetAddress, this._fileSystem, ); @@ -47,14 +47,12 @@ class TestAssetServer implements AssetReader { String hostname, int port, UrlEncoder urlTunneller, + PackageConfig packageConfig, ) async { var address = (await InternetAddress.lookup(hostname)).first; var httpServer = await HttpServer.bind(address, port); - var packages = await loadPackageConfigUri(Uri.base.resolve('.packages'), - loader: (Uri uri) => fileSystem.file(uri).readAsBytes()); var server = - TestAssetServer(root, httpServer, packages, address, fileSystem); - + TestAssetServer(root, httpServer, packageConfig, address, fileSystem); return server; } @@ -64,8 +62,7 @@ class TestAssetServer implements AssetReader { final Map _sourcemaps = {}; final Map _metadata = {}; String _mergedMetadata; - // ignore: deprecated_member_use - final PackageConfig _packages; + final PackageConfig _packageConfig; final InternetAddress internetAddress; Uint8List getFile(String path) => _files[path]; @@ -241,7 +238,7 @@ class TestAssetServer implements AssetReader { // The file might have been a package file which is signaled by a // `/packages//` request. if (segments.first == 'packages') { - var packageFile = _fileSystem.file(_packages + var packageFile = _fileSystem.file(_packageConfig .resolve(Uri(scheme: 'package', pathSegments: segments.skip(1)))); if (packageFile.existsSync()) { return packageFile; diff --git a/frontend_server_common/lib/src/devfs.dart b/frontend_server_common/lib/src/devfs.dart index 568d1fad1..df097a498 100644 --- a/frontend_server_common/lib/src/devfs.dart +++ b/frontend_server_common/lib/src/devfs.dart @@ -12,6 +12,7 @@ import 'package:dwds/dwds.dart'; import 'package:file/file.dart'; import 'package:logging/logging.dart'; import 'package:meta/meta.dart'; +import 'package:package_config/package_config.dart'; import 'package:path/path.dart' as p; import 'asset.dart'; @@ -30,8 +31,7 @@ class WebDevFS { this.fileSystem, this.hostname, this.port, - this.packagesFilePath, - this.packagesPath, + this.packageConfigPath, this.root, this.urlTunneller, }); @@ -40,24 +40,31 @@ class WebDevFS { TestAssetServer assetServer; final String hostname; final int port; - final String packagesFilePath; - final String packagesPath; + final String packageConfigPath; final String root; final UrlEncoder urlTunneller; Directory _savedCurrentDirectory; List sources; + PackageConfig _packageConfig; Future create() async { _savedCurrentDirectory = fileSystem.currentDirectory; - fileSystem.currentDirectory = packagesPath; + // package_config.json is located in /.dart_tool/package_config + var projectDirectory = p.dirname(p.dirname(packageConfigPath)); + + fileSystem.currentDirectory = projectDirectory; + + _packageConfig = await loadPackageConfigUri(Uri.file(packageConfigPath), + loader: (Uri uri) => fileSystem.file(uri).readAsBytes()); + assetServer = await TestAssetServer.start( - fileSystem, root, hostname, port, urlTunneller); + fileSystem, root, hostname, port, urlTunneller, _packageConfig); return Uri.parse('http://$hostname:$port'); } Future dispose() { fileSystem.currentDirectory = _savedCurrentDirectory; - return assetServer.close(); + return assetServer?.close(); } Future update({ @@ -102,11 +109,9 @@ class WebDevFS { generator.reset(); var compilerOutput = await generator.recompile( - 'org-dartlang-app:///$mainPath', - invalidatedFiles, - outputPath: p.join(dillOutputPath, 'app.dill'), - packagesFilePath: packagesFilePath, - ); + Uri.parse('org-dartlang-app:///$mainPath'), invalidatedFiles, + outputPath: p.join(dillOutputPath, 'app.dill'), + packageConfig: _packageConfig); if (compilerOutput == null || compilerOutput.errorCount > 0) { return UpdateFSReport(success: false); } diff --git a/frontend_server_common/lib/src/frontend_server_client.dart b/frontend_server_common/lib/src/frontend_server_client.dart index 91ed7ffad..68f9a236b 100644 --- a/frontend_server_common/lib/src/frontend_server_client.dart +++ b/frontend_server_common/lib/src/frontend_server_client.dart @@ -158,68 +158,6 @@ class StdoutHandler { } } -/// Converts filesystem paths to package URIs. -class PackageUriMapper { - PackageUriMapper(String scriptPath, String packagesFilePath, - String fileSystemScheme, List fileSystemRoots) { - init(scriptPath, packagesFilePath, fileSystemScheme, fileSystemRoots); - } - - Future init(String scriptPath, String packagesFilePath, - String fileSystemScheme, List fileSystemRoots) async { - var packageConfig = await loadPackageConfig( - File(fileSystem.path.absolute(packagesFilePath))); - var isWindowsPath = - Platform.isWindows && !scriptPath.startsWith('org-dartlang-app'); - var scriptUri = Uri.file(scriptPath, windows: isWindowsPath).toString(); - for (var package in packageConfig.packages) { - var prefix = package.packageUriRoot.toString(); - // Only perform a multi-root mapping if there are multiple roots. - if (fileSystemScheme != null && - fileSystemRoots != null && - fileSystemRoots.length > 1 && - prefix.contains(fileSystemScheme)) { - _packageName = package.name; - _uriPrefixes = fileSystemRoots - .map((String name) => - Uri.file(name, windows: Platform.isWindows).toString()) - .toList(); - return; - } - if (scriptUri.startsWith(prefix)) { - _packageName = package.name; - _uriPrefixes = [prefix]; - return; - } - } - } - - String _packageName; - List _uriPrefixes; - - Uri map(String scriptPath) { - if (_packageName == null) { - return null; - } - var scriptUri = - Uri.file(scriptPath, windows: Platform.isWindows).toString(); - for (var uriPrefix in _uriPrefixes) { - if (scriptUri.startsWith(uriPrefix)) { - return Uri.parse( - 'package:$_packageName/${scriptUri.substring(uriPrefix.length)}'); - } - } - return null; - } - - static Uri findUri(String scriptPath, String packagesFilePath, - String fileSystemScheme, List fileSystemRoots) { - return PackageUriMapper( - scriptPath, packagesFilePath, fileSystemScheme, fileSystemRoots) - .map(scriptPath); - } -} - /// Class that allows to serialize compilation requests to the compiler. abstract class _CompilationRequest { _CompilationRequest(this.completer); @@ -236,16 +174,16 @@ abstract class _CompilationRequest { class _RecompileRequest extends _CompilationRequest { _RecompileRequest( Completer completer, - this.mainPath, + this.mainUri, this.invalidatedFiles, this.outputPath, - this.packagesFilePath, + this.packageConfig, ) : super(completer); - String mainPath; + Uri mainUri; List invalidatedFiles; String outputPath; - String packagesFilePath; + PackageConfig packageConfig; @override Future _run(DefaultResidentCompiler compiler) async => @@ -316,7 +254,7 @@ class _RejectRequest extends _CompilationRequest { abstract class ResidentCompiler { factory ResidentCompiler( String sdkRoot, { - String packagesPath, + String packageConfigPath, List fileSystemRoots, String fileSystemScheme, String platformDill, @@ -330,18 +268,14 @@ abstract class ResidentCompiler { void addFileSystemRoot(String root); /// If invoked for the first time, it compiles Dart script identified by - /// [mainPath], [invalidatedFiles] list is ignored. + /// [mainUri], [invalidatedFiles] list is ignored. /// On successive runs [invalidatedFiles] indicates which files need to be - /// recompiled. If [mainPath] is null, previously used [mainPath] entry + /// recompiled. If [mainUri] is null, previously used [mainUri] entry /// point that is used for recompilation. /// Binary file name is returned if compilation was successful, otherwise /// null is returned. - Future recompile( - String mainPath, - List invalidatedFiles, { - @required String outputPath, - String packagesFilePath, - }); + Future recompile(Uri mainUri, List invalidatedFiles, + {@required String outputPath, @required PackageConfig packageConfig}); Future compileExpression( String expression, @@ -387,7 +321,7 @@ abstract class ResidentCompiler { class DefaultResidentCompiler implements ResidentCompiler { DefaultResidentCompiler( String sdkRoot, { - this.packagesPath, + this.packageConfigPath, this.fileSystemRoots, this.fileSystemScheme, this.platformDill, @@ -398,7 +332,7 @@ class DefaultResidentCompiler implements ResidentCompiler { // This is a URI, not a file path, so the forward slash is correct even on Windows. sdkRoot = sdkRoot.endsWith('/') ? sdkRoot : '$sdkRoot/'; - final String packagesPath; + final String packageConfigPath; final List fileSystemRoots; final String fileSystemScheme; final String platformDill; @@ -420,8 +354,9 @@ class DefaultResidentCompiler implements ResidentCompiler { StreamController<_CompilationRequest>(); @override - Future recompile(String mainPath, List invalidatedFiles, - {@required String outputPath, String packagesFilePath}) async { + Future recompile(Uri mainUri, List invalidatedFiles, + {@required String outputPath, + @required PackageConfig packageConfig}) async { assert(outputPath != null); if (!_controller.hasListener) { _controller.stream.listen(_handleCompilationRequest); @@ -429,40 +364,34 @@ class DefaultResidentCompiler implements ResidentCompiler { var completer = Completer(); _controller.add(_RecompileRequest( - completer, mainPath, invalidatedFiles, outputPath, packagesFilePath)); + completer, mainUri, invalidatedFiles, outputPath, packageConfig)); return completer.future; } Future _recompile(_RecompileRequest request) async { _stdoutHandler.reset(); - // First time recompile is called we actually have to compile the app from - // scratch ignoring list of invalidated files. - PackageUriMapper packageUriMapper; - if (request.packagesFilePath != null) { - packageUriMapper = PackageUriMapper( - request.mainPath, - request.packagesFilePath, - fileSystemScheme, - fileSystemRoots, - ); - } + final mainUri = + request.packageConfig.toPackageUri(request.mainUri)?.toString() ?? + toMultiRootPath(request.mainUri, fileSystemScheme, fileSystemRoots); _compileRequestNeedsConfirmation = true; if (_server == null) { - return _compile(_mapFilename(request.mainPath, packageUriMapper), - request.outputPath, request.packagesFilePath); + return _compile(mainUri, request.outputPath); } var inputKey = Uuid().generateV4(); - var mainUri = request.mainPath != null - ? '${_mapFilename(request.mainPath, packageUriMapper)} ' - : ''; _server.stdin.writeln('recompile $mainUri$inputKey'); _logger.info('<- recompile $mainUri$inputKey'); for (var fileUri in request.invalidatedFiles) { - var message = _mapFileUri(fileUri.toString(), packageUriMapper); + String message; + if (fileUri.scheme == 'package') { + message = fileUri.toString(); + } else { + message = request.packageConfig.toPackageUri(fileUri)?.toString() ?? + toMultiRootPath(fileUri, fileSystemScheme, fileSystemRoots); + } _server.stdin.writeln(message); _logger.info(message); } @@ -490,7 +419,7 @@ class DefaultResidentCompiler implements ResidentCompiler { } Future _compile( - String scriptUri, String outputFilePath, String packagesFilePath) async { + String scriptUri, String outputFilePath) async { var frontendServer = frontendServerExecutable; var args = [ frontendServer, @@ -501,12 +430,9 @@ class DefaultResidentCompiler implements ResidentCompiler { '-Ddart.developer.causal_async_stacks=true', '--output-dill', outputFilePath, - if (packagesFilePath != null) ...[ + if (packageConfigPath != null) ...[ '--packages', - packagesFilePath, - ] else if (packagesPath != null) ...[ - '--packages', - packagesPath, + packageConfigPath, ], if (fileSystemRoots != null) for (final String root in fileSystemRoots) ...[ @@ -527,8 +453,9 @@ class DefaultResidentCompiler implements ResidentCompiler { ]; _logger.info(args.join(' ')); + var projectDirectory = p.dirname(p.dirname(packageConfigPath)); _server = await Process.start(Platform.resolvedExecutable, args, - workingDirectory: packagesPath); + workingDirectory: projectDirectory); _server.stdout .transform(utf8.decoder) .transform(const LineSplitter()) @@ -693,46 +620,6 @@ class DefaultResidentCompiler implements ResidentCompiler { return _server.exitCode; } - String _mapFilename(String filename, PackageUriMapper packageUriMapper) { - return _doMapFilename(filename, packageUriMapper) ?? filename; - } - - String _mapFileUri(String fileUri, PackageUriMapper packageUriMapper) { - String filename; - try { - filename = Uri.parse(fileUri).toFilePath(); - } on UnsupportedError catch (_) { - return fileUri; - } - return _doMapFilename(filename, packageUriMapper) ?? fileUri; - } - - String _doMapFilename(String filename, PackageUriMapper packageUriMapper) { - if (packageUriMapper != null) { - var packageUri = packageUriMapper.map(filename); - if (packageUri != null) { - return packageUri.toString(); - } - } - - if (fileSystemRoots != null) { - for (var root in fileSystemRoots) { - if (filename.startsWith(root)) { - return Uri( - scheme: fileSystemScheme, - path: filename.substring(root.length)) - .toString(); - } - } - } - if (Platform.isWindows && - fileSystemRoots != null && - fileSystemRoots.length > 1) { - return Uri.file(filename, windows: Platform.isWindows).toString(); - } - return null; - } - @override Future shutdown() async { // Server was never successfully created. @@ -788,3 +675,20 @@ class TestExpressionCompiler implements ExpressionCompiler { @override Future initialize({String moduleFormat, bool soundNullSafety}) async {} } + +/// Convert a file URI into a multi-root scheme URI if provided, otherwise +/// return unmodified. +@visibleForTesting +String toMultiRootPath( + Uri fileUri, String scheme, List fileSystemRoots) { + if (scheme == null || fileSystemRoots.isEmpty || fileUri.scheme != 'file') { + return fileUri.toString(); + } + final filePath = fileUri.toFilePath(windows: Platform.isWindows); + for (final fileSystemRoot in fileSystemRoots) { + if (filePath.startsWith(fileSystemRoot)) { + return '$scheme://${filePath.substring(fileSystemRoot.length)}'; + } + } + return fileUri.toString(); +} diff --git a/frontend_server_common/lib/src/resident_runner.dart b/frontend_server_common/lib/src/resident_runner.dart index 9f14f8704..ed692f8ea 100644 --- a/frontend_server_common/lib/src/resident_runner.dart +++ b/frontend_server_common/lib/src/resident_runner.dart @@ -28,14 +28,13 @@ class ResidentWebRunner { ResidentWebRunner( this.mainPath, this.urlTunneller, - this.packagesPath, - this.packagesFilePath, + this.packageConfigPath, this.fileSystemRoots, this.fileSystemScheme, this.outputPath, bool verbose) { generator = ResidentCompiler(dartSdkPath, - packagesPath: packagesPath, + packageConfigPath: packageConfigPath, platformDill: '$platformDill', fileSystemRoots: fileSystemRoots, fileSystemScheme: fileSystemScheme, @@ -45,8 +44,7 @@ class ResidentWebRunner { final UrlEncoder urlTunneller; final String mainPath; - final String packagesPath; - final String packagesFilePath; + final String packageConfigPath; final String outputPath; final List fileSystemRoots; final String fileSystemScheme; @@ -67,8 +65,7 @@ class ResidentWebRunner { fileSystem: fileSystem, hostname: hostname, port: port, - packagesFilePath: packagesFilePath, - packagesPath: packagesPath, + packageConfigPath: packageConfigPath, root: root, urlTunneller: urlTunneller, ); diff --git a/webdev/test/e2e_test.dart b/webdev/test/e2e_test.dart index e5779b2b9..b5a47980b 100644 --- a/webdev/test/e2e_test.dart +++ b/webdev/test/e2e_test.dart @@ -53,7 +53,9 @@ void main() { await process.shouldExit(0); - await d.file('.packages', isNotEmpty).validate(exampleDirectory); + await d + .file('.dart_tool/package_config.json', isNotEmpty) + .validate(exampleDirectory); await d.file('pubspec.lock', isNotEmpty).validate(exampleDirectory); }); diff --git a/webdev/test/integration_test.dart b/webdev/test/integration_test.dart index 259ed60f8..be766da1b 100644 --- a/webdev/test/integration_test.dart +++ b/webdev/test/integration_test.dart @@ -53,9 +53,9 @@ name: sample )) .create(); - await d.file('.packages', ''' -''').create(); await d.dir('.dart_tool', [d.file('package_config.json', '')]).create(); + await d.file('.dart_tool/package_config.json', ''' +''').create(); var process = await runWebDev(['serve'], workingDirectory: d.sandbox); @@ -84,10 +84,10 @@ name: sample .file('pubspec.lock', _pubspecLock(runnerVersion: null)) .create(); - await d.file('.packages', ''' -''').create(); await d .dir('.dart_tool', [d.file('package_config.json', '')]).create(); + await d.file('.dart_tool/package_config.json', ''' +''').create(); var process = await runWebDev([command], workingDirectory: d.sandbox); @@ -107,10 +107,10 @@ name: sample .file('pubspec.lock', _pubspecLock(webCompilersVersion: null)) .create(); - await d.file('.packages', ''' -''').create(); await d .dir('.dart_tool', [d.file('package_config.json', '')]).create(); + await d.file('.dart_tool/package_config.json', ''' +''').create(); var process = await runWebDev(['serve'], workingDirectory: d.sandbox); @@ -132,10 +132,10 @@ name: sample .file('pubspec.lock', _pubspecLock(webCompilersVersion: null)) .create(); - await d.file('.packages', ''' -''').create(); await d .dir('.dart_tool', [d.file('package_config.json', '')]).create(); + await d.file('.dart_tool/package_config.json', ''' +''').create(); // Required for webdev to not complain about nothing to serve. await d.dir('web').create(); @@ -184,10 +184,10 @@ name: sample daemonVersion: buildDaemonVersion)) .create(); - await d.file('.packages', ''' -''').create(); await d.dir( '.dart_tool', [d.file('package_config.json', '')]).create(); + await d.file('.dart_tool/package_config.json', ''' +''').create(); var process = await runWebDev(['serve'], workingDirectory: d.sandbox); @@ -240,8 +240,8 @@ name: sample test('should fail if there has been a dependency change', () async { await d.file('pubspec.lock', _pubspecLock()).create(); - await d.file('.packages', '').create(); await d.dir('.dart_tool', [d.file('package_config.json', '')]).create(); + await d.file('.dart_tool/package_config.json', '').create(); // Ensure there is a noticeable delta in the creation times await Future.delayed(const Duration(milliseconds: 1100));