Estimate progress while rsync scans from the last backup's file count

With incremental recursion rsync only knows the total near the end, so the bar showed
no ETA for most of the backup. Save the file count as a third line of the state file
and use it as an estimate until rsync reports the real total.
This commit is contained in:
Fuxino
2026-11-02 20:56:12 +01:00
parent 5e33781974
commit ec27b8d77f
6 changed files with 142 additions and 19 deletions
+37
View File
@@ -207,6 +207,19 @@ class TestRsync:
assert 'rsync: total size' in caplog.text
assert '%' not in caplog.text
def test_file_count(self, src: Path, out: Path) -> None:
backup = make_backup(out, [str(src)], progress=True)
assert backup.run() == 0
# The source folder, its two files and the implied parent folders
assert backup.file_count is not None and backup.file_count >= 3
def test_no_file_count_without_progress(self, src: Path, out: Path) -> None:
backup = make_backup(out, [str(src)])
assert backup.run() == 0
assert backup.file_count is None
def test_cli(self, src: Path, out: Path, tmp_path: Path, run_cli: Callable[..., int]) -> None:
config_file = str(tmp_path / 'missing.conf')
@@ -280,6 +293,30 @@ class TestProgressBar:
assert bar.update(' 3.00M 2% 1.47MB/s 0:00:03')
assert capsys.readouterr().err.endswith('] 50% 2/4 files 3.00M copied ETA 0:00:30\033[K')
def test_estimate_while_scanning(self, monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture[str]) -> None:
monkeypatch.setattr(sb, 'get_terminal_size', lambda: os.terminal_size((100, 24)))
bar = sb._ProgressBar(estimate=4000)
assert bar.update(' 2.00M 25% 1.47MB/s 0:00:02 (xfr#1, ir-chk=1000/2000)')
assert bar.total is None
assert capsys.readouterr().err == \
'\r[#######-----------------------] ~25% 1,000/~4,000 files 2.00M copied ETA ~0:01:30\033[K'
def test_estimate_exceeded(self, capsys: pytest.CaptureFixture[str]) -> None:
bar = sb._ProgressBar(estimate=1000)
# More files than in the last backup: back to plain scanning
assert bar.update(' 2.00M 25% 1.47MB/s 0:00:02 (xfr#1, ir-chk=500/2000)')
assert capsys.readouterr().err == '\r1,500 files checked 2.00M copied (scanning)\033[K'
def test_real_total_replaces_estimate(self, capsys: pytest.CaptureFixture[str]) -> None:
bar = sb._ProgressBar(estimate=4000)
assert bar.update(' 4,000,000 1% 2.97MB/s 0:00:01 (xfr#2, to-chk=1/4)')
assert bar.total == 4
assert ' 75% 3/4 files' in capsys.readouterr().err
def test_not_progress(self, capsys: pytest.CaptureFixture[str]) -> None:
bar = sb._ProgressBar()