list method
All sessions in directory, sorted from oldest to newest (by last activity).
Non-regular directory entries, including symlinks, are ignored.
Implementation
Future<List<FileLogSession>> list() async {
final dir = Directory(directory);
if (!dir.existsSync()) return const [];
final chunksById =
<String, List<({int index, File file, FileStat stat})>>{};
await for (final entity in dir.list(followLinks: false)) {
final file = File(entity.path);
final parsed = parseChunkName(file.uri.pathSegments.last);
if (parsed == null) continue;
if (!_isRegularFile(file)) continue;
final stat = file.statSync();
// The file may have been deleted between list() and statSync
// (rotation or cleanup by another process) — otherwise the session
// would get size -1 and a lastModified near the epoch.
if (stat.type == FileSystemEntityType.notFound) continue;
if (!_isRegularFile(file)) continue;
chunksById
.putIfAbsent(parsed.sessionId, () => [])
.add((index: parsed.index, file: file, stat: stat));
}
final sessions = <FileLogSession>[];
for (final MapEntry(key: id, value: chunks) in chunksById.entries) {
chunks.sort((a, b) => a.index.compareTo(b.index));
var size = 0;
var lastModified = DateTime.fromMillisecondsSinceEpoch(0);
for (final chunk in chunks) {
size += chunk.stat.size;
if (chunk.stat.modified.isAfter(lastModified)) {
lastModified = chunk.stat.modified;
}
}
sessions.add(
FileLogSession._(
id: id,
files: List.unmodifiable(chunks.map((c) => c.file)),
size: size,
lastModified: lastModified,
),
);
}
sessions.sort(
(a, b) => switch (a.lastModified.compareTo(b.lastModified)) {
0 => a.id.compareTo(b.id),
final byTime => byTime,
},
);
return sessions;
}