Compare commits

...
3 Commits
Author SHA1 Message Date
Fuxino 50546f2ebb Bump version to 4.6.4 2026-11-14 11:08:39 +01:00
Fuxino 2c7233ce45 Keep the progress bar estimate when the last file count is exceeded
When a backup has more files than the last one, estimate the total from the files rsync has found so far,
capped at 99% until the scan ends, instead of falling back to "(scanning)".
2026-11-14 11:08:21 +01:00
Fuxino 68b6d77f30 Update PKGBUILD 2026-11-08 14:38:35 +01:00
5 changed files with 37 additions and 14 deletions
+2 -2
View File
@@ -4,7 +4,7 @@
pkgname=simple_backup pkgname=simple_backup
pkgdesc='Simple backup script that uses rsync to copy files' pkgdesc='Simple backup script that uses rsync to copy files'
pkgver=4.6.2 pkgver=4.6.3
pkgrel=1 pkgrel=1
url="https://git.shouldnt.work/fuxino/$pkgname" url="https://git.shouldnt.work/fuxino/$pkgname"
arch=('any') arch=('any')
@@ -24,7 +24,7 @@ checkdepends=('python-pytest'
conflicts=('simple_backup-git') conflicts=('simple_backup-git')
source=("git+$url?signed#tag=$pkgver") source=("git+$url?signed#tag=$pkgver")
validpgpkeys=('7E12BC1FF3B6EDB2CD8053EB981A2B2A3BBF5514') validpgpkeys=('7E12BC1FF3B6EDB2CD8053EB981A2B2A3BBF5514')
sha256sums=('bbe7b79669fe02ca4dc62fb08b8b5eaed809b5f1ece9586017af8ebf20d2faa0') sha256sums=('b1e7802fcd5e615c92f6007238b3699d69e3005e140d87a742283ef1cc6bd37f')
build() build()
{ {
+4 -3
View File
@@ -1,4 +1,4 @@
.TH SIMPLE_BACKUP 1 2026-11-08 SIMPLE_BACKUP 4.6.3 .TH SIMPLE_BACKUP 1 2026-11-14 SIMPLE_BACKUP 4.6.4
.SH NAME .SH NAME
simple_backup \- Backup files and folders using rsync simple_backup \- Backup files and folders using rsync
.SH SYNOPSIS .SH SYNOPSIS
@@ -117,8 +117,9 @@ Don't use systemd journal for logging.
Don't show a progress bar while rsync copies the files. The progress bar is only shown when Don't show a progress bar while rsync copies the files. The progress bar is only shown when
the output is a terminal, so it never appears in the systemd journal or in redirected output. the output is a terminal, so it never appears in the systemd journal or in redirected output.
While rsync is still looking for files, the percentage and estimated time (marked with While rsync is still looking for files, the percentage and estimated time (marked with
\(aq~\(aq) are based on the number of files in the last backup, or the bar shows \(aq~\(aq) are based on the number of files in the last backup (or on the files found so far,
\(aq(scanning)\(aq if that is unknown or already exceeded. once this backup has more), and stay below 100%. Without a previous count the bar shows
\(aq(scanning)\(aq instead.
.TP .TP
.B \-\-rsync\-options OPTIONS [OPTION...] .B \-\-rsync\-options OPTIONS [OPTION...]
By default, the following rsync options are used: By default, the following rsync options are used:
+1 -1
View File
@@ -1,3 +1,3 @@
"""Init.""" """Init."""
__version__ = '4.6.3' __version__ = '4.6.4'
+8 -5
View File
@@ -135,13 +135,16 @@ class _ProgressBar:
percent: int | None percent: int | None
if self.total is None: if self.total is None:
# Estimate from the last backup, unless this one already has more files # Estimate from the last backup; past it, from the files found so far, as the scan is then nearly done
if 0 < self._checked < self._estimate: estimate = max(self._estimate, self._total)
percent = self._checked * 100 // self._estimate
text = f'{f"~{percent}":>3}% {self._checked:,}/~{self._estimate:,} files {size} copied' if self._estimate > 0 and self._checked > 0:
# The real total is still unknown, so never claim 100%
percent = min(self._checked * 100 // estimate, 99)
text = f'{f"~{percent}":>3}% {self._checked:,}/~{estimate:,} files {size} copied'
if percent > 0: if percent > 0:
text += f' ETA ~{self._eta(self._estimate)}' text += f' ETA ~{self._eta(estimate)}'
else: else:
text = f'{self._checked:,} files checked {size} copied (scanning)' text = f'{self._checked:,} files checked {size} copied (scanning)'
percent = None percent = None
+22 -3
View File
@@ -303,12 +303,31 @@ class TestProgressBar:
assert capsys.readouterr().err == \ assert capsys.readouterr().err == \
'\r[#######-----------------------] ~25% 1,000/~4,000 files 2.00M copied ETA ~0:01:30\033[K' '\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: def test_estimate_exceeded(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=1000) bar = sb._ProgressBar(estimate=1000)
# More files than in the last backup: back to plain scanning # More files than in the last backup: estimate from the files found so far
assert bar.update(' 2.00M 25% 1.47MB/s 0:00:02 (xfr#1, ir-chk=500/2000)') 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' assert capsys.readouterr().err == \
'\r[######################--------] ~75% 1,500/~2,000 files 2.00M copied ETA ~0:00:10\033[K'
def test_estimate_capped_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=1000)
# All files found so far are checked, but rsync may still find more
assert bar.update(' 2.00M 25% 1.47MB/s 0:00:02 (xfr#1, ir-chk=0/2000)')
assert bar.total is None
assert ' ~99% 2,000/~2,000 files 2.00M copied ETA ~0:00:00\033[K' in capsys.readouterr().err
def test_no_estimate_without_last_count(self, capsys: pytest.CaptureFixture[str]) -> None:
bar = sb._ProgressBar()
# The files found so far are only a guess at the total near the end of the scan
assert bar.update(' 2.00M 25% 1.47MB/s 0:00:02 (xfr#1, ir-chk=0/2000)')
assert capsys.readouterr().err == '\r2,000 files checked 2.00M copied (scanning)\033[K'
def test_real_total_replaces_estimate(self, capsys: pytest.CaptureFixture[str]) -> None: def test_real_total_replaces_estimate(self, capsys: pytest.CaptureFixture[str]) -> None:
bar = sb._ProgressBar(estimate=4000) bar = sb._ProgressBar(estimate=4000)