feat: add package source compatibility controls

This commit is contained in:
gem
2026-06-10 17:54:12 +08:00
parent 6608d0a975
commit 79ee35db2f
12 changed files with 611 additions and 30 deletions

View File

@@ -32,34 +32,31 @@ class StablePackageStore {
return;
}
final marker = await _markerFile(package.manifest.gameId);
marker.createSync(recursive: true);
marker.parent.createSync(recursive: true);
final previous = await stablePackage(package.manifest.gameId);
final data = {
'current': package.rootPath,
if (previous != null && previous.rootPath != package.rootPath)
'previous': previous.rootPath,
};
marker.writeAsStringSync(const JsonEncoder.withIndent(' ').convert(data));
final temporary = File('${marker.path}.tmp');
temporary.writeAsStringSync(
const JsonEncoder.withIndent(' ').convert(data),
);
if (marker.existsSync()) {
marker.deleteSync();
}
temporary.renameSync(marker.path);
}
Future<GamePackage?> stablePackage(String gameId) async {
final marker = await _markerFile(gameId);
if (!marker.existsSync()) {
return null;
}
final data =
jsonDecode(await marker.readAsString()) as Map<String, Object?>;
return _packageFromPath(data['current']);
final data = await _readMarker(gameId);
return _packageFromPath(data?['current']);
}
Future<GamePackage?> previousStablePackage(String gameId) async {
final marker = await _markerFile(gameId);
if (!marker.existsSync()) {
return null;
}
final data =
jsonDecode(await marker.readAsString()) as Map<String, Object?>;
return _packageFromPath(data['previous']);
final data = await _readMarker(gameId);
return _packageFromPath(data?['previous']);
}
Future<File> _markerFile(String gameId) async {
@@ -67,6 +64,26 @@ class StablePackageStore {
return File(p.join(root.path, gameId, 'stable.json'));
}
Future<Map<String, Object?>?> _readMarker(String gameId) async {
final marker = await _markerFile(gameId);
if (!marker.existsSync()) {
return null;
}
final source = await marker.readAsString();
if (source.trim().isEmpty) {
return null;
}
try {
final value = jsonDecode(source);
if (value is Map) {
return Map<String, Object?>.from(value);
}
} catch (_) {
return null;
}
return null;
}
GamePackage? _packageFromPath(Object? pathValue) {
if (pathValue is! String || pathValue.isEmpty) {
return null;