Skip to content

Commit 2522559

Browse files
authored
Migrate some simple tasks to a simple package:args command (dart-lang#3456)
1 parent c2ed703 commit 2522559

File tree

2 files changed

+119
-182
lines changed

2 files changed

+119
-182
lines changed

tool/grind.dart

Lines changed: 6 additions & 182 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,16 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'dart:async';
6-
import 'dart:convert';
76
import 'dart:io' hide ProcessException;
87

98
import 'package:analyzer/file_system/physical_file_system.dart';
10-
import 'package:collection/collection.dart';
11-
import 'package:crypto/crypto.dart' as crypto;
129
import 'package:dartdoc/src/io_utils.dart';
1310
import 'package:dartdoc/src/package_meta.dart';
1411
import 'package:grinder/grinder.dart';
1512
import 'package:path/path.dart' as p;
16-
import 'package:yaml/yaml.dart' as yaml;
1713

1814
import 'subprocess_launcher.dart';
15+
import 'task.dart' as task;
1916

2017
void main(List<String> args) => grind(args);
2118

@@ -115,9 +112,6 @@ Directory cleanFlutterDir = Directory(
115112

116113
final Directory _flutterDir = createTempSync('flutter');
117114

118-
final Directory _languageTestPackageDir =
119-
createTempSync('languageTestPackageDir');
120-
121115
Directory get testPackage => Directory(p.joinAll(['testing', 'test_package']));
122116

123117
Directory get testPackageExperiments =>
@@ -248,10 +242,6 @@ void presubmit() {}
248242
@Depends(presubmit, test, testDartdoc)
249243
void buildbot() {}
250244

251-
@Task('Run buildbot tests, but without publish test')
252-
@Depends(analyze, checkFormat, checkBuild, test, testDartdoc)
253-
void buildbotNoPublish() {}
254-
255245
@Task('Generate docs for the Dart SDK')
256246
Future<void> buildSdkDocs() async {
257247
log('building SDK docs');
@@ -562,26 +552,12 @@ Future<void> buildTestPackageDocs() async {
562552
_testPackageDocsDir.absolute.path, Directory.current.path);
563553
}
564554

565-
@Task('Build test package docs (Markdown) with inherited docs and source code')
566-
@Depends(clean)
567-
Future<void> buildTestPackageDocsMd() async {
568-
await _buildTestPackageDocs(
569-
_testPackageDocsDir.absolute.path, Directory.current.path,
570-
params: ['--format', 'md']);
571-
}
572-
573555
@Task('Serve test package docs locally with dhttpd on port 8002')
574556
@Depends(buildTestPackageDocs)
575557
Future<void> serveTestPackageDocs() async {
576558
await startTestPackageDocsServer();
577559
}
578560

579-
@Task('Serve test package docs (in Markdown) locally with dhttpd on port 8002')
580-
@Depends(buildTestPackageDocsMd)
581-
Future<void> serveTestPackageDocsMd() async {
582-
await startTestPackageDocsServer();
583-
}
584-
585561
Future<void> startTestPackageDocsServer() async {
586562
log('launching dhttpd on port 8002 for SDK');
587563
var launcher = SubprocessLauncher('serve-test-package-docs');
@@ -710,86 +686,6 @@ Future<void> serveFlutterDocs() async {
710686
]);
711687
}
712688

713-
@Task('Serve language test directory docs on port 8004')
714-
@Depends(buildLanguageTestDocs)
715-
Future<void> serveLanguageTestDocs() async {
716-
log('launching dhttpd on port 8004 for language tests');
717-
var launcher = SubprocessLauncher('serve-language-test-docs');
718-
await launcher.runStreamed(Platform.resolvedExecutable, ['pub', 'get']);
719-
await launcher.runStreamed(Platform.resolvedExecutable, [
720-
'pub',
721-
'global',
722-
'run',
723-
'dhttpd',
724-
'--port',
725-
'8004',
726-
'--path',
727-
p.join(_languageTestPackageDir.path, 'doc', 'api'),
728-
]);
729-
}
730-
731-
@Task('Build docs for a language test directory in the SDK')
732-
Future<void> buildLanguageTestDocs() async {
733-
// The path to the base directory for language tests.
734-
var languageTestPath = Platform.environment['LANGUAGE_TESTS'];
735-
if (languageTestPath == null) {
736-
fail(
737-
'LANGUAGE_TESTS must be set to the SDK language test directory from which to copy tests');
738-
}
739-
var launcher = SubprocessLauncher('build-language-test-docs');
740-
var pubspecFile = File(p.join(_languageTestPackageDir.path, 'pubspec.yaml'));
741-
pubspecFile.writeAsStringSync('''name: _language_test_package
742-
version: 0.0.1
743-
environment:
744-
sdk: '>=${Platform.version.split(' ').first}'
745-
''');
746-
747-
var analyzerOptionsFile =
748-
File(p.join(_languageTestPackageDir.path, 'analysis_options.yaml'));
749-
var analyzerOptions = languageExperiments.map((e) => ' - $e').join('\n');
750-
analyzerOptionsFile.writeAsStringSync('''analyzer:
751-
enable-experiment:
752-
$analyzerOptions
753-
''');
754-
755-
var libDir = Directory(p.join(_languageTestPackageDir.path, 'lib'))
756-
..createSync();
757-
var languageTestDir = Directory(p.context.resolveTildePath(languageTestPath));
758-
if (!languageTestDir.existsSync()) {
759-
fail('language test dir does not exist: $languageTestDir');
760-
}
761-
762-
for (var entry in languageTestDir.listSync(recursive: true)) {
763-
if (entry is File &&
764-
entry.existsSync() &&
765-
!entry.path.endsWith('_error_test.dart') &&
766-
!entry.path.endsWith('_error_lib.dart')) {
767-
var destDir = Directory(p.join(
768-
libDir.path,
769-
p.dirname(entry.absolute.path
770-
.replaceFirst(languageTestDir.absolute.path + p.separator, ''))));
771-
if (!destDir.existsSync()) destDir.createSync(recursive: true);
772-
copy(entry, destDir);
773-
}
774-
}
775-
776-
await launcher.runStreamed(Platform.resolvedExecutable, ['pub', 'get'],
777-
workingDirectory: _languageTestPackageDir.absolute.path);
778-
await launcher.runStreamed(
779-
Platform.resolvedExecutable,
780-
[
781-
'--enable-asserts',
782-
p.join(Directory.current.absolute.path, 'bin', 'dartdoc.dart'),
783-
'--json',
784-
'--link-to-remote',
785-
'--show-progress',
786-
'--enable-experiment',
787-
languageExperiments.join(','),
788-
..._extraDartdocParameters,
789-
],
790-
workingDirectory: _languageTestPackageDir.absolute.path);
791-
}
792-
793689
@Task('Validate flutter docs')
794690
@Depends(buildFlutterDocs, testDartdocFlutterPlugin)
795691
void validateFlutterDocs() {}
@@ -982,29 +878,6 @@ Future<void> servePubPackage() async {
982878
await _serveDocsFrom(await buildPubPackage(), 9000, 'serve-pub-package');
983879
}
984880

985-
@Task('Checks that CHANGELOG mentions current version')
986-
Future<void> checkChangelogHasVersion() async {
987-
var changelog = File('CHANGELOG.md');
988-
if (!changelog.existsSync()) {
989-
fail('ERROR: No CHANGELOG.md found in ${Directory.current}');
990-
}
991-
992-
var version = _getPackageVersion();
993-
994-
if (!changelog.readAsLinesSync().contains('## $version')) {
995-
fail('ERROR: CHANGELOG.md does not mention version $version');
996-
}
997-
}
998-
999-
String _getPackageVersion() {
1000-
var pubspec = File('pubspec.yaml');
1001-
if (!pubspec.existsSync()) {
1002-
fail('Cannot find pubspec.yaml in ${Directory.current}');
1003-
}
1004-
var yamlDoc = yaml.loadYaml(pubspec.readAsStringSync()) as yaml.YamlMap;
1005-
return yamlDoc['version'] as String;
1006-
}
1007-
1008881
@Task('Rebuild generated files')
1009882
@Depends(clean, buildWeb)
1010883
Future<void> build() async {
@@ -1013,34 +886,13 @@ Future<void> build() async {
1013886
// issues with Windows.
1014887
return;
1015888
}
1016-
await SubprocessLauncher('build').runStreamed(Platform.resolvedExecutable,
1017-
[p.join('tool', 'mustachio', 'builder.dart')]);
1018-
1019-
var version = _getPackageVersion();
1020-
var dartdocOptions = File('dartdoc_options.yaml');
1021-
await dartdocOptions.writeAsString('''dartdoc:
1022-
linkToSource:
1023-
root: '.'
1024-
uriTemplate: 'https://github.com/dart-lang/dartdoc/blob/v$version/%f%#L%l%'
1025-
''');
889+
890+
await task.buildRenderers();
891+
await task.buildDartdocOptions();
1026892
}
1027893

1028894
@Task('Build the web frontend')
1029-
Future<void> buildWeb() async {
1030-
// Compile the web app.
1031-
var launcher = SubprocessLauncher('build');
1032-
await launcher.runStreamed(Platform.resolvedExecutable, [
1033-
'compile',
1034-
'js',
1035-
'--output=lib/resources/docs.dart.js',
1036-
'web/docs.dart',
1037-
'-O4',
1038-
]);
1039-
delete(File('lib/resources/docs.dart.js.deps'));
1040-
1041-
final compileSig = await _calcDartFilesSig(Directory('web'));
1042-
File(p.join('web', 'sig.txt')).writeAsStringSync('$compileSig\n');
1043-
}
895+
Future<void> buildWeb() async => await task.buildWeb();
1044896

1045897
/// Paths in this list are relative to lib/.
1046898
final _generatedFilesList = <String>[
@@ -1089,7 +941,7 @@ Future<void> checkBuild() async {
1089941
}
1090942

1091943
// Verify that the web frontend has been compiled.
1092-
final currentCodeSig = await _calcDartFilesSig(Directory('web'));
944+
final currentCodeSig = await task.calcDartFilesSig(Directory('web'));
1093945
final lastCompileSig =
1094946
File(p.join('web', 'sig.txt')).readAsStringSync().trim();
1095947
if (currentCodeSig != lastCompileSig) {
@@ -1101,7 +953,6 @@ Future<void> checkBuild() async {
1101953
}
1102954

1103955
@Task('Dry run of publish to pub.dev')
1104-
@Depends(checkChangelogHasVersion)
1105956
Future<void> tryPublish() async {
1106957
var launcher = SubprocessLauncher('try-publish');
1107958
await launcher
@@ -1273,30 +1124,3 @@ int _findCount(String str, String match) {
12731124
}
12741125
return count;
12751126
}
1276-
1277-
Future<String> _calcDartFilesSig(Directory dir) async {
1278-
final digest = await _dartFileLines(dir)
1279-
.transform(utf8.encoder)
1280-
.transform(crypto.md5)
1281-
.single;
1282-
1283-
return digest.bytes
1284-
.map((byte) => byte.toRadixString(16).padLeft(2, '0').toUpperCase())
1285-
.join();
1286-
}
1287-
1288-
/// Yields all of the trimmed lines of all of the `.dart` files in [dir].
1289-
Stream<String> _dartFileLines(Directory dir) async* {
1290-
final files = dir
1291-
.listSync(recursive: true)
1292-
.whereType<File>()
1293-
.where((file) => file.path.endsWith('.dart'))
1294-
.toList()
1295-
..sort((a, b) => compareAsciiLowerCase(a.path, b.path));
1296-
1297-
for (var file in files) {
1298-
for (var line in file.readAsLinesSync()) {
1299-
yield line.trim();
1300-
}
1301-
}
1302-
}

tool/task.dart

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import 'dart:convert';
2+
import 'dart:io';
3+
4+
import 'package:args/args.dart';
5+
import 'package:collection/collection.dart';
6+
import 'package:crypto/crypto.dart' as crypto;
7+
import 'package:path/path.dart' as p;
8+
import 'package:yaml/yaml.dart' as yaml;
9+
10+
import 'subprocess_launcher.dart';
11+
12+
void main(List<String> args) async {
13+
var parser = ArgParser();
14+
parser.addCommand('build');
15+
var results = parser.parse(args);
16+
var commandResults = results.command;
17+
if (commandResults == null) {
18+
return;
19+
}
20+
21+
return switch (commandResults.name) {
22+
'build' => await runBuild(commandResults),
23+
// TODO(srawlins): Implement tasks that document various code.
24+
'doc' => throw UnimplementedError(),
25+
// TODO(srawlins): Implement tasks that serve various docs, after generating
26+
// them.
27+
'serve' => throw UnimplementedError(),
28+
_ => throw ArgumentError(),
29+
};
30+
}
31+
32+
String _getPackageVersion() {
33+
var pubspec = File('pubspec.yaml');
34+
if (!pubspec.existsSync()) {
35+
throw StateError('Cannot find pubspec.yaml in ${Directory.current}');
36+
}
37+
var yamlDoc = yaml.loadYaml(pubspec.readAsStringSync()) as yaml.YamlMap;
38+
return yamlDoc['version'] as String;
39+
}
40+
41+
Future<void> runBuild(ArgResults commandResults) async {
42+
for (var target in commandResults.rest) {
43+
// ignore: unnecessary_statements, unnecessary_parenthesis
44+
(switch (target) {
45+
'renderers' => await buildRenderers(),
46+
'dartdoc-options' => await buildDartdocOptions(),
47+
'web' => await buildWeb(),
48+
_ => throw UnimplementedError('Unknown build target: "$target"'),
49+
});
50+
}
51+
}
52+
53+
Future<void> buildRenderers() async =>
54+
await SubprocessLauncher('build').runStreamed(Platform.resolvedExecutable,
55+
[p.join('tool', 'mustachio', 'builder.dart')]);
56+
57+
Future<void> buildDartdocOptions() async {
58+
var version = _getPackageVersion();
59+
var dartdocOptions = File('dartdoc_options.yaml');
60+
await dartdocOptions.writeAsString('''dartdoc:
61+
linkToSource:
62+
root: '.'
63+
uriTemplate: 'https://github.com/dart-lang/dartdoc/blob/v$version/%f%#L%l%'
64+
''');
65+
}
66+
67+
Future<void> buildWeb() async {
68+
await SubprocessLauncher('build').runStreamed(Platform.resolvedExecutable, [
69+
'compile',
70+
'js',
71+
'--output=lib/resources/docs.dart.js',
72+
'web/docs.dart',
73+
'-O4',
74+
]);
75+
delete(File('lib/resources/docs.dart.js.deps'));
76+
77+
var compileSig = await calcDartFilesSig(Directory('web'));
78+
File(p.join('web', 'sig.txt')).writeAsStringSync('$compileSig\n');
79+
}
80+
81+
/// Delete the given file entity reference.
82+
void delete(FileSystemEntity entity) {
83+
if (entity.existsSync()) {
84+
print('deleting ${entity.path}');
85+
entity.deleteSync(recursive: true);
86+
}
87+
}
88+
89+
Future<String> calcDartFilesSig(Directory dir) async {
90+
final digest = await _dartFileLines(dir)
91+
.transform(utf8.encoder)
92+
.transform(crypto.md5)
93+
.single;
94+
95+
return digest.bytes
96+
.map((byte) => byte.toRadixString(16).padLeft(2, '0').toUpperCase())
97+
.join();
98+
}
99+
100+
/// Yields all of the trimmed lines of all of the `.dart` files in [dir].
101+
Stream<String> _dartFileLines(Directory dir) {
102+
var files = dir
103+
.listSync(recursive: true)
104+
.whereType<File>()
105+
.where((file) => file.path.endsWith('.dart'))
106+
.toList()
107+
..sort((a, b) => compareAsciiLowerCase(a.path, b.path));
108+
109+
return Stream.fromIterable([
110+
for (var file in files)
111+
for (var line in file.readAsLinesSync()) line.trim(),
112+
]);
113+
}

0 commit comments

Comments
 (0)