Set file permissions

This commit is contained in:
Joscha 2026-02-06 13:03:18 +01:00
parent 79da3773fd
commit e236973e82
2 changed files with 22 additions and 6 deletions

View file

@ -4,5 +4,7 @@ TAG = "This file was generated by pasch."
class File(ABC): class File(ABC):
executable: bool = False
@abstractmethod @abstractmethod
def to_bytes(self) -> bytes: ... def to_bytes(self) -> bytes: ...

View file

@ -26,6 +26,17 @@ def atomic_write(path: Path, content: bytes) -> None:
tmp_path.rename(path) tmp_path.rename(path)
def set_executable(path: Path, executable: bool) -> None:
mask = 0o100
mode = path.stat().st_mode
is_executable = (mode & mask) != 0
if executable == is_executable:
return
path.chmod(mode ^ mask)
def hash_data(data: bytes) -> str: def hash_data(data: bytes) -> str:
m = hashlib.sha256() m = hashlib.sha256()
m.update(data) m.update(data)
@ -112,26 +123,28 @@ class Files(Module):
root: Path | None = None, root: Path | None = None,
) -> None: ) -> None:
super().__init__(orchestrator) super().__init__(orchestrator)
self._files: dict[str, bytes] = {} self._files: dict[str, File] = {}
self._file_db = FileDb(self.o.state_dir / file_db_name) self._file_db = FileDb(self.o.state_dir / file_db_name)
self._root = root or Path.home() self._root = root or Path.home()
def _read_path(self, path: Path | str) -> Path: def _read_path(self, path: Path | str) -> Path:
return self._root / path return self._root / path
def add(self, path: Path | str, content: File) -> None: def add(self, path: Path | str, file: File) -> None:
path = self._read_path(path) path = self._read_path(path)
self._files[path_to_str(path)] = content.to_bytes() self._files[path_to_str(path)] = file
def execute(self) -> None: def execute(self) -> None:
for path, content in sorted(self._files.items()): for path, file in sorted(self._files.items()):
self._write_file(self._read_path(path), content) self._write_file(self._read_path(path), file)
for path in self._file_db.paths(): for path in self._file_db.paths():
if path not in self._files: if path not in self._files:
self._remove_file(self._read_path(path)) self._remove_file(self._read_path(path))
def _write_file(self, path: Path, content: bytes) -> None: def _write_file(self, path: Path, file: File) -> None:
content = file.to_bytes()
cur_hash = hash_file(path) cur_hash = hash_file(path)
target_hash = hash_data(content) target_hash = hash_data(content)
if cur_hash == target_hash: if cur_hash == target_hash:
@ -155,6 +168,7 @@ class Files(Module):
# we write a file. # we write a file.
self._file_db.add_hash(path, target_hash) self._file_db.add_hash(path, target_hash)
atomic_write(path, content) atomic_write(path, content)
set_executable(path, file.executable)
def _remove_file(self, path: Path) -> None: def _remove_file(self, path: Path) -> None:
relative_path = path.relative_to(self._root, walk_up=True) relative_path = path.relative_to(self._root, walk_up=True)