From 1ad8316217a1e2762fc32e1ca2abb60eb4e49e5d Mon Sep 17 00:00:00 2001 From: evanweible-wf Date: Thu, 25 Aug 2022 12:51:57 -0600 Subject: [PATCH] Add and use an abstraction over system and URL paths --- lib/src/executable.dart | 46 ++++++++---------- lib/src/utils/dart_dev_paths.dart | 31 ++++++++++++ lib/src/utils/dart_tool_cache.dart | 10 +--- test/utils/dart_dev_paths_test.dart | 73 +++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+), 35 deletions(-) create mode 100644 lib/src/utils/dart_dev_paths.dart create mode 100644 test/utils/dart_dev_paths_test.dart diff --git a/lib/src/executable.dart b/lib/src/executable.dart index 7fae07dc..c1bd5e00 100644 --- a/lib/src/executable.dart +++ b/lib/src/executable.dart @@ -4,51 +4,43 @@ import 'dart:io'; import 'package:analyzer/dart/analysis/utilities.dart'; import 'package:args/command_runner.dart'; import 'package:dart_dev/dart_dev.dart'; -import 'package:dart_dev/src/dart_dev_tool.dart'; -import 'package:dart_dev/src/utils/format_tool_builder.dart'; -import 'package:dart_dev/src/utils/get_dart_version_comment.dart'; -import 'package:dart_dev/src/utils/parse_flag_from_args.dart'; import 'package:io/ansi.dart'; import 'package:io/io.dart' show ExitCode; import 'package:logging/logging.dart'; import 'package:path/path.dart' as p; -import '../utils.dart'; import 'dart_dev_runner.dart'; import 'tools/over_react_format_tool.dart'; import 'utils/assert_dir_is_dart_package.dart'; +import 'utils/cached_pubspec.dart'; +import 'utils/dart_dev_paths.dart'; import 'utils/dart_tool_cache.dart'; import 'utils/ensure_process_exit.dart'; +import 'utils/format_tool_builder.dart'; +import 'utils/get_dart_version_comment.dart'; import 'utils/logging.dart'; +import 'utils/parse_flag_from_args.dart'; typedef _ConfigGetter = Map Function(); -final _runScriptPath = p.join(cacheDirPath, 'run.dart'); +final paths = DartDevPaths(); -final _runScript = File(_runScriptPath); - -final _configPath = p.join('tool', 'dart_dev', 'config.dart'); - -final _oldDevDartPath = p.join('tool', 'dev.dart'); - -final _relativeDevDartPath = p.relative( - p.absolute(_configPath), - from: p.absolute(p.dirname(_runScriptPath)), -); +final _runScript = File(paths.runScript); Future run(List args) async { attachLoggerToStdio(args); - final configExists = File(_configPath).existsSync(); - final oldDevDartExists = File(_oldDevDartPath).existsSync(); + + final configExists = File(paths.config).existsSync(); + final oldDevDartExists = File(paths.legacyConfig).existsSync(); if (!configExists) { - log.fine('No custom `$_configPath` file found; ' + log.fine('No custom `${paths.config}` file found; ' 'using default config.'); } if (oldDevDartExists) { log.warning(yellow.wrap( - 'dart_dev v3 now expects configuration to be at `$_configPath`,\n' - 'but `$_oldDevDartPath` still exists. View the guide to see how to upgrade:\n' + 'dart_dev v3 now expects configuration to be at `${paths.config}`,\n' + 'but `${paths.legacyConfig}` still exists. View the guide to see how to upgrade:\n' 'https://github.com/Workiva/dart_dev/blob/master/doc/v3-upgrade-guide.md')); } @@ -60,7 +52,7 @@ Future run(List args) async { generateRunScript(); final process = await Process.start( - Platform.executable, [_runScriptPath, ...args], + Platform.executable, [paths.runScript, ...args], mode: ProcessStartMode.inheritStdio); ensureProcessExit(process); exitCode = await process.exitCode; @@ -70,7 +62,7 @@ Future handleFastFormat(List args) async { assertDirIsDartPackage(); DevTool formatTool; - final configFile = File(_configPath); + final configFile = File(paths.config); if (configFile.existsSync()) { final toolBuilder = FormatToolBuilder(); parseString(content: configFile.readAsStringSync()) @@ -119,11 +111,11 @@ bool get shouldWriteRunScript => const _isDartDevNullSafe = false; String buildDartDevRunScriptContents() { - final hasCustomToolDevDart = File(_configPath).existsSync(); + final hasCustomToolDevDart = File(paths.config).existsSync(); // If the config has a dart version comment (e.g., if it opts out of null safety), // copy it over to the entrypoint so the program is run in that language version. var dartVersionComment = hasCustomToolDevDart - ? getDartVersionComment(File(_configPath).readAsStringSync()) + ? getDartVersionComment(File(paths.config).readAsStringSync()) : null; // If dart_dev itself is not null-safe, opt the entrypoint out of null-safety // so the entrypoint doesn't fail to run in packages that have opted into null-safety. @@ -137,7 +129,7 @@ import 'dart:io'; import 'package:dart_dev/src/core_config.dart'; import 'package:dart_dev/src/executable.dart' as executable; -${hasCustomToolDevDart ? "import '$_relativeDevDartPath' as custom_dev;" : ""} +${hasCustomToolDevDart ? "import '${paths.configFromRunScriptForDart}' as custom_dev;" : ""} void main(List args) async { await executable.runWithConfig(args, @@ -162,7 +154,7 @@ Future runWithConfig( config = configGetter(); } catch (error) { stderr - ..writeln('Invalid "$_configPath" in ${p.absolute(p.current)}') + ..writeln('Invalid "${paths.config}" in ${p.absolute(p.current)}') ..writeln() ..writeln('It should provide a `Map config;` getter,' ' but it either does not exist or threw unexpectedly:') diff --git a/lib/src/utils/dart_dev_paths.dart b/lib/src/utils/dart_dev_paths.dart new file mode 100644 index 00000000..6d83a038 --- /dev/null +++ b/lib/src/utils/dart_dev_paths.dart @@ -0,0 +1,31 @@ +import 'package:path/path.dart' as p; + +/// A collection of paths to files and directories constructed to be compatible +/// with a given [p.Context]. +class DartDevPaths { + final p.Context _context; + + DartDevPaths({p.Context context}) : _context = context ?? p.context; + + String cache([String subPath]) => _context.normalize( + _context.joinAll([..._cacheParts, if (subPath != null) subPath])); + + String get _cacheForDart => p.url.joinAll(_cacheParts); + + final List _cacheParts = ['.dart_tool', 'dart_dev']; + + String get config => _context.joinAll(_configParts); + + String get configForDart => p.url.joinAll(_configParts); + + final List _configParts = ['tool', 'dart_dev', 'config.dart']; + + String get configFromRunScriptForDart => p.url.relative( + p.url.absolute(configForDart), + from: p.url.absolute(_cacheForDart), + ); + + String get legacyConfig => _context.join('tool', 'dev.dart'); + + String get runScript => cache('run.dart'); +} diff --git a/lib/src/utils/dart_tool_cache.dart b/lib/src/utils/dart_tool_cache.dart index 00a6772b..21d05a00 100644 --- a/lib/src/utils/dart_tool_cache.dart +++ b/lib/src/utils/dart_tool_cache.dart @@ -1,15 +1,9 @@ import 'dart:io'; -import 'package:path/path.dart' as p; - -const cacheDirPath = '.dart_tool/dart_dev'; +import 'package:dart_dev/src/utils/dart_dev_paths.dart'; void createCacheDir({String subPath}) { - var path = cacheDirPath; - if (subPath != null) { - path = p.join(path, subPath); - } - final dir = Directory(path); + final dir = Directory(DartDevPaths().cache(subPath)); if (!dir.existsSync()) { dir.createSync(recursive: true); } diff --git a/test/utils/dart_dev_paths_test.dart b/test/utils/dart_dev_paths_test.dart new file mode 100644 index 00000000..c64f7c2b --- /dev/null +++ b/test/utils/dart_dev_paths_test.dart @@ -0,0 +1,73 @@ +import 'package:dart_dev/src/utils/dart_dev_paths.dart'; +import 'package:path/path.dart' as p; +import 'package:test/test.dart'; + +void main() { + group('DartDevPaths', () { + group('posix', () { + DartDevPaths paths; + + setUp(() { + paths = DartDevPaths(context: p.posix); + }); + + test('cache', () { + expect(paths.cache(), '.dart_tool/dart_dev'); + }); + + test('cache with subpath', () { + expect(paths.cache('sub/path'), '.dart_tool/dart_dev/sub/path'); + }); + + test('config', () { + expect(paths.config, 'tool/dart_dev/config.dart'); + }); + + test('configFromRunScriptForDart', () { + expect(paths.configFromRunScriptForDart, + '../../tool/dart_dev/config.dart'); + }); + + test('legacyConfig', () { + expect(paths.legacyConfig, 'tool/dev.dart'); + }); + + test('runScript', () { + expect(paths.runScript, '.dart_tool/dart_dev/run.dart'); + }); + }); + + group('windows', () { + DartDevPaths paths; + + setUp(() { + paths = DartDevPaths(context: p.windows); + }); + + test('cache', () { + expect(paths.cache(), r'.dart_tool\dart_dev'); + }); + + test('cache with subpath', () { + expect(paths.cache('sub/path'), r'.dart_tool\dart_dev\sub\path'); + }); + + test('config', () { + expect(paths.config, r'tool\dart_dev\config.dart'); + }); + + test('configFromRunScriptForDart', () { + expect(paths.configFromRunScriptForDart, + r'../../tool/dart_dev/config.dart'); + }); + + test('legacyConfig', () { + expect(paths.legacyConfig, r'tool\dev.dart'); + }); + + test('runScript', () { + expect(paths.runScript, r'.dart_tool\dart_dev\run.dart'); + }); + }); + }); +}