Keep only rsync's summary lines when not verbose
Every output line was kept in memory although only the last two were logged, and fewer than two lines (e.g. with --rsync-options q) raised an IndexError.
This commit is contained in:
@@ -24,6 +24,7 @@ import re
|
|||||||
import shlex
|
import shlex
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
from collections import deque
|
||||||
from collections.abc import Callable, Iterator
|
from collections.abc import Callable, Iterator
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
@@ -774,7 +775,8 @@ class Backup:
|
|||||||
assert p.stdin is not None and isinstance(p.stdout, io.BufferedIOBase)
|
assert p.stdin is not None and isinstance(p.stdout, io.BufferedIOBase)
|
||||||
p.stdin.close()
|
p.stdin.close()
|
||||||
|
|
||||||
output = []
|
# Without -v, only the summary (the last two lines) is logged
|
||||||
|
output: list[str] | deque[str] = [] if self._verbose else deque(maxlen=2)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
for r in _read_records(p.stdout):
|
for r in _read_records(p.stdout):
|
||||||
@@ -790,8 +792,9 @@ class Backup:
|
|||||||
if self._verbose:
|
if self._verbose:
|
||||||
logger.info('rsync: %s', output)
|
logger.info('rsync: %s', output)
|
||||||
else:
|
else:
|
||||||
logger.info('rsync: %s', output[-2])
|
# May be fewer than two lines, e.g. with --rsync-options q
|
||||||
logger.info('rsync: %s', output[-1])
|
for r in output:
|
||||||
|
logger.info('rsync: %s', r)
|
||||||
else:
|
else:
|
||||||
self._returncode_log(returncode)
|
self._returncode_log(returncode)
|
||||||
|
|
||||||
|
|||||||
+14
-1
@@ -298,12 +298,13 @@ class FakePopen:
|
|||||||
|
|
||||||
returncode = 0
|
returncode = 0
|
||||||
calls: list[list[str]] = []
|
calls: list[list[str]] = []
|
||||||
|
output = b'sending incremental file list\nsent 1 bytes received 2 bytes\ntotal size is 3\n'
|
||||||
|
|
||||||
def __init__(self, args: list[str], **kwargs: Any) -> None:
|
def __init__(self, args: list[str], **kwargs: Any) -> None:
|
||||||
FakePopen.calls.append(args)
|
FakePopen.calls.append(args)
|
||||||
os.makedirs(args[args.index('/') + 1])
|
os.makedirs(args[args.index('/') + 1])
|
||||||
self.stdin = io.BytesIO()
|
self.stdin = io.BytesIO()
|
||||||
self.stdout = io.BytesIO(b'sending incremental file list\nsent 1 bytes received 2 bytes\ntotal size is 3\n')
|
self.stdout = io.BytesIO(FakePopen.output)
|
||||||
|
|
||||||
def __enter__(self) -> 'FakePopen':
|
def __enter__(self) -> 'FakePopen':
|
||||||
return self
|
return self
|
||||||
@@ -343,6 +344,18 @@ class TestReturnCodes:
|
|||||||
assert f'--link-dest={out}/simple_backup/{old_backups[-1]}' in args
|
assert f'--link-dest={out}/simple_backup/{old_backups[-1]}' in args
|
||||||
assert args[args.index('/') + 1] == f'{out}/simple_backup/2026-10-14_10-00-00'
|
assert args[args.index('/') + 1] == f'{out}/simple_backup/2026-10-14_10-00-00'
|
||||||
|
|
||||||
|
@pytest.mark.parametrize('lines, logged', [
|
||||||
|
([f'file{n}' for n in range(5)] + ['sent 1 bytes', 'total size is 3'], ['sent 1 bytes', 'total size is 3']),
|
||||||
|
([], []),
|
||||||
|
(['total size is 3'], ['total size is 3']),
|
||||||
|
])
|
||||||
|
def test_summary_logged(self, src: Path, out: Path, fake_popen: type[FakePopen], monkeypatch: pytest.MonkeyPatch,
|
||||||
|
caplog: pytest.LogCaptureFixture, lines: list[str], logged: list[str]) -> None:
|
||||||
|
monkeypatch.setattr(fake_popen, 'output', ''.join(f'{line}\n' for line in lines).encode())
|
||||||
|
|
||||||
|
assert run_backup(out, [str(src)]) == 0
|
||||||
|
assert [m[7:] for m in caplog.messages if m.startswith('rsync: ')] == logged
|
||||||
|
|
||||||
def test_rsync_missing(self, src: Path, out: Path, tmp_path: Path, fake_popen: type[FakePopen],
|
def test_rsync_missing(self, src: Path, out: Path, tmp_path: Path, fake_popen: type[FakePopen],
|
||||||
old_backups: list[str], monkeypatch: pytest.MonkeyPatch,
|
old_backups: list[str], monkeypatch: pytest.MonkeyPatch,
|
||||||
caplog: pytest.LogCaptureFixture) -> None:
|
caplog: pytest.LogCaptureFixture) -> None:
|
||||||
|
|||||||
Reference in New Issue
Block a user