Whole file
hirak99/yabsnap
The author described this change as “Fixes a bug where keep_preinstall = 1 did not work correctly”. It counts as a record because the check below fails on the code as it stood at b89df439c and passes on 12bc3b314, with nothing else changed between the two runs.
Projecthirak99/yabsnap
Fix saved2023-11-05
Sharing licenceApache-2.0 · LICENSE
Change size+14 −5
What the code was meant to do, written into the code itself as a save note
Fixes a bug where keep_preinstall = 1 did not work correctly
The change
| 23 | 23 | from . import os_utils | |
| 24 | 24 | from . import snap_holder | |
| 25 | 25 | ||
| 26 | - | from typing import Any, Iterable, Iterator, Optional | |
| 26 | + | from typing import Any, Iterable, Iterator, Optional, TypeVar | |
| 27 | 27 | ||
| 28 | 28 | ||
| 29 | 29 | def _get_old_backups(config: configs.Config) -> Iterator[snap_holder.Snapshot]: | |
| 30 | 30 | """Returns existing backups in chronological order.""" | |
| 31 | - | configdir = os.path.dirname(config.dest_prefix) | |
| 32 | - | for fname in os.listdir(configdir): | |
| 33 | - | pathname = os.path.join(configdir, fname) | |
| 31 | + | destdir = os.path.dirname(config.dest_prefix) | |
| 32 | + | for fname in os.listdir(destdir): | |
| 33 | + | pathname = os.path.join(destdir, fname) | |
| 34 | 34 | if not os.path.isdir(pathname): | |
| 35 | 35 | continue | |
| 36 | 36 | if not pathname.startswith(config.dest_prefix): | |
| ⋯ | |||
| 53 | 53 | return None | |
| 54 | 54 | ||
| 55 | 55 | ||
| 56 | + | _GenericT = TypeVar("_GenericT") | |
| 57 | + | ||
| 58 | + | ||
| 59 | + | def _all_but_last_k(array: list[_GenericT], k: int) -> Iterator[_GenericT]: | |
| 60 | + | if k < 0: | |
| 61 | + | raise ValueError(f"k = {k} < 0") | |
| 62 | + | yield from array[: len(array) - k] | |
| 63 | + | ||
| 64 | + | ||
| 56 | 65 | class SnapOperator: | |
| 57 | 66 | def __init__(self, config: configs.Config, now: datetime.datetime) -> None: | |
| 58 | 67 | self._config = config | |
| ⋯ | |||
| 106 | 115 | snapshot.create_from(self._config.source) | |
| 107 | 116 | ||
| 108 | 117 | # Clean up old snaps; leave count-1 previous snaps (plus the one now created). | |
| 109 | - | for expired in previous_snaps[: -count + 1]: | |
| 118 | + | for expired in _all_but_last_k(previous_snaps, count - 1): | |
| 110 | 119 | expired.delete() | |
| 111 | 120 | self.need_sync = True | |
| 112 | 121 | ||
The check that tells the two apart
fail→pass·src/code/snap_operator_test.py::SnapOperatorTest::test_all_but_k
Check file src/code/snap_operator_test.py, taken without changes from the fix and copied onto the older code, so the exact same check runs against both versions.
Origin and history
The code before itb89df439c99999f2541fef5468432157e10ecb16
Broken version dated2023-11-05
Modulecode.snap_operator
Units changedSnapOperator, _get_old_backups
Fingerprint1c82b90824555f94
Checked2026-08-18 by goldset/0.1
Every field above is generated by our program. None of it is written by hand.