94 lines
2.5 KiB
Dart
94 lines
2.5 KiB
Dart
import 'dart:io';
|
|
|
|
const _commonPath = 'tool/lua_runtime_defs_common.lua';
|
|
const _runtimeMarker = 'runtime = runtime';
|
|
const _gamesRoot = 'assets/games';
|
|
|
|
void main(List<String> args) {
|
|
final checkOnly = args.contains('--check');
|
|
final commonFile = File(_commonPath);
|
|
if (!commonFile.existsSync()) {
|
|
stderr.writeln('Missing common Lua runtime defs template: $_commonPath');
|
|
exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
final common = _normalizeCommon(commonFile.readAsStringSync());
|
|
var changed = false;
|
|
final targets = _runtimeDefTargets();
|
|
if (targets.isEmpty) {
|
|
stderr.writeln('No Lua runtime defs targets found under $_gamesRoot');
|
|
exitCode = 1;
|
|
return;
|
|
}
|
|
|
|
for (final target in targets) {
|
|
final targetPath = target.path;
|
|
final current = target.existsSync() ? target.readAsStringSync() : '';
|
|
final suffix = current.isEmpty
|
|
? ''
|
|
: _gameSpecificSuffix(current, targetPath);
|
|
final generated = suffix.isEmpty ? common : '$common\n$suffix';
|
|
|
|
if (current == generated) {
|
|
stdout.writeln('up to date: $targetPath');
|
|
continue;
|
|
}
|
|
|
|
changed = true;
|
|
if (checkOnly) {
|
|
stderr.writeln('out of date: $targetPath');
|
|
} else {
|
|
target.writeAsStringSync(generated);
|
|
stdout.writeln('generated: $targetPath');
|
|
}
|
|
}
|
|
|
|
if (checkOnly && changed) {
|
|
stderr.writeln(
|
|
'Lua runtime defs are out of date. Run: dart run tool/generate_lua_runtime_defs.dart',
|
|
);
|
|
exitCode = 1;
|
|
}
|
|
}
|
|
|
|
List<File> _runtimeDefTargets() {
|
|
final root = Directory(_gamesRoot);
|
|
if (!root.existsSync()) {
|
|
return const [];
|
|
}
|
|
final targets = <File>[];
|
|
for (final entity in root.listSync()) {
|
|
if (entity is! Directory) {
|
|
continue;
|
|
}
|
|
final scripts = Directory('${entity.path}/scripts');
|
|
if (!scripts.existsSync()) {
|
|
continue;
|
|
}
|
|
targets.add(File('${scripts.path}/runtime_defs.lua'));
|
|
}
|
|
targets.sort((a, b) => a.path.compareTo(b.path));
|
|
return targets;
|
|
}
|
|
|
|
String _normalizeCommon(String source) {
|
|
final text = source.replaceAll('\r\n', '\n').trimRight();
|
|
if (!text.contains(_runtimeMarker)) {
|
|
throw const FormatException(
|
|
'Common template must contain runtime = runtime',
|
|
);
|
|
}
|
|
return '$text\n';
|
|
}
|
|
|
|
String _gameSpecificSuffix(String source, String targetPath) {
|
|
final text = source.replaceAll('\r\n', '\n');
|
|
final index = text.indexOf(_runtimeMarker);
|
|
if (index < 0) {
|
|
throw FormatException('$targetPath must contain $_runtimeMarker');
|
|
}
|
|
final suffixStart = index + _runtimeMarker.length;
|
|
return text.substring(suffixStart).trimLeft();
|
|
}
|