scratchSpaceResource top-level property

Resource<ScratchSpace> scratchSpaceResource
final

A shared Resource for a ScratchSpace, which cleans up the contents of the ScratchSpace in dispose, but doesn't delete it entirely.

Implementation

final scratchSpaceResource = Resource<ScratchSpace>(() {
  if (!scratchSpace.exists) {
    scratchSpace.tempDir.createSync(recursive: true);
    scratchSpace.exists = true;
  }
  var packageConfigFile = File(
      p.join(scratchSpace.tempDir.path, '.dart_tool', 'package_config.json'));
  if (!packageConfigFile.existsSync()) {
    var originalConfigFile = File(p.join('.dart_tool', 'package_config.json'));
    var packageConfigContents = _scratchSpacePackageConfig(
        originalConfigFile.readAsStringSync(), originalConfigFile.absolute.uri);
    packageConfigFile
      ..createSync(recursive: true)
      ..writeAsStringSync(packageConfigContents);
  }
  return scratchSpace;
}, beforeExit: () async {
  // The workers are running inside the scratch space, so wait for them to
  // shut down before deleting it.
  await dartdevkWorkersAreDone;
  await frontendWorkersAreDone;
  // Attempt to clean up the scratch space. Even after waiting for the workers
  // to shut down we might get file system exceptions on windows for an
  // arbitrary amount of time, so do retries with an exponential backoff.
  var numTries = 0;
  while (true) {
    numTries++;
    if (numTries > 3) {
      _logger
          .warning('Failed to clean up temp dir ${scratchSpace.tempDir.path}.');
      return;
    }
    try {
      // TODO(https://github.com/dart-lang/build/issues/656):  The scratch
      // space throws on `delete` if it thinks it was already deleted.
      // Manually clean up in this case.
      if (scratchSpace.exists) {
        await scratchSpace.delete();
      } else {
        await scratchSpace.tempDir.delete(recursive: true);
      }
      return;
    } on FileSystemException {
      var delayMs = math.pow(10, numTries).floor();
      _logger.info('Failed to delete temp dir ${scratchSpace.tempDir.path}, '
          'retrying in ${delayMs}ms');
      await Future<void>.delayed(Duration(milliseconds: delayMs));
    }
  }
});