util/path: new clamp mtime function

New utility function to clamp all mtimes of a given path to a
certain timestamp. Clamp here means that any timestamp later
than the specified upper bound will be set to the upper bound.
This commit is contained in:
Christian Kellner 2022-02-15 13:31:23 +00:00 committed by Tom Gundersen
parent 0007fc2065
commit 39d38d33fd
2 changed files with 75 additions and 0 deletions

View file

@ -1,5 +1,36 @@
"""Path handling utility functions"""
import errno
import os
import os.path
from typing import Optional
from .ctx import suppress_oserror
def clamp_mtime(path: str, start: int, to: int):
"""Clamp all modification times of 'path'
Set the mtime of 'path' to 'to' if it is greater or equal to 'start'.
If 'to' is None, the mtime is set to the current time.
"""
times = (to, to)
def fix_utime(path, dfd: Optional[int] = None):
sb = os.stat(path, dir_fd=dfd, follow_symlinks=False)
if sb.st_mtime < start:
return
# We might get a permission error when the immutable flag is set;
# since there is nothing much we can do, we just ignore it
with suppress_oserror(errno.EPERM):
os.utime(path, times, dir_fd=dfd, follow_symlinks=False)
fix_utime(path)
for _, dirs, files, dfd in os.fwalk(path):
for f in dirs + files:
fix_utime(f, dfd)
def in_tree(path: str, tree: str, must_exist: bool = False) -> bool:

View file

@ -2,10 +2,54 @@
# Tests for the 'osbuild.util.path' module
#
import os
import time
from pathlib import Path
from tempfile import TemporaryDirectory
import pytest
from osbuild.util import path
@pytest.fixture(name="tempdir")
def tempdir_fixture():
with TemporaryDirectory(prefix="path-") as tmp:
yield tmp
def test_clamp_mtime(tempdir):
start = int(time.time())
tree = Path(tempdir, "tree")
tree.mkdir()
os.makedirs(os.path.join(tree, "a", "bunch", "of", "directories"))
file = Path(tree, "file")
file.touch()
folder = Path(tree, "folder")
folder.mkdir()
link = Path(tree, "link")
link.symlink_to(folder, target_is_directory=True)
timepoint = 1644758228
path.clamp_mtime(tree, start, timepoint)
def ensure_mtime(target, dfd):
stat = os.stat(target, dir_fd=dfd, follow_symlinks=False)
assert stat.st_mtime <= timepoint
for _, dirs, files, dfd in os.fwalk(tree):
ensure_mtime(".", dfd)
for d in dirs:
ensure_mtime(d, dfd)
for f in files:
ensure_mtime(f, dfd)
def test_in_tree():
cases = {
("/tmp/file", "/tmp", False): True, # Simple, non-existent