Review of 1.0.3: names a snapshot cannot hold, restore-directory errors under salvage, browse speed

- Leave out and report a file or folder whose name a snapshot cannot hold
- A staging write failure stops a full restore under --salvage
- Browse reuses its repository; empty folders read along with the entries
- Keep leases alive while empty folders are created; exact-prefix empty folder is the target
- Clean up tables that were partly created or before the transaction started
- Bin: no empty message after a read error; longer pages
This commit is contained in:
2026-11-06 19:44:52 +01:00
parent c7a651f269
commit 1736005648
9 changed files with 68 additions and 19 deletions
+10 -6
View File
@@ -59,17 +59,21 @@ final class BackupRun {
$finishedWalk = true;
foreach ($walker->walk($state['after']) as $logical => $path) {
if (!mb_check_encoding($logical, 'UTF-8') || !Repository::isSafePath($logical)) {
// A name a snapshot cannot hold (a backslash, a control character, not UTF-8). One
// such path must not make a backup fail, or the whole snapshot unreadable later.
self::recordUnreadable($state, $stats, mb_scrub($logical, 'UTF-8'));
$state['cur'] = null;
$state['after'] = $logical;
continue;
}
if (is_dir($path)) {
$mtime = @filemtime($path);
if ($mtime === false) {
continue; // removed while walking
}
if (mb_check_encoding($logical, 'UTF-8')) {
$emptyDirs[] = json_encode([$logical, $mtime], JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
$stats['emptyDirs'] = ($stats['emptyDirs'] ?? 0) + 1;
} else {
self::recordUnreadable($state, $stats, $logical); // a snapshot only holds UTF-8
}
$emptyDirs[] = json_encode([$logical, $mtime], JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
$stats['emptyDirs'] = ($stats['emptyDirs'] ?? 0) + 1;
$state['after'] = $logical;
if (microtime(true) >= $deadline) {
$finishedWalk = false;