lib.util.copy(): Support FileContext source, file types, and --parents #144

Merged
Jan Lindemann merged 8 commits from jan/feature/20261017-lib-util-copy-support-filecontext-source-file-types-and-parents into master 2026-10-17 11:57:05 +02:00 AGit
Showing only changes of commit 9abeb4ebca - Show all commits

lib.FileContext.is_gettable: Add property

Analogous to the is_dir() method, add an is_gettable() method: The last
commit introduces FT_COMPOUND, a file type which is a hybrid between
directory and regular file. is_dir() succeeds on it, so is_gettable()
symmetrically provides a test find out if get() also works on a file.

Signed-off-by: Jan Lindemann <jan@janware.com>
Jan Lindemann 2026-10-16 16:09:21 +02:00
Signed by: Jan Lindemann
GPG key ID: 3750640C9E25DD61

View file

@ -308,6 +308,30 @@ class FileContext(abc.ABC):
async def is_dir(self, path: str, follow_symlinks: bool = True) -> bool:
return await self._is_dir(self._chroot(path), follow_symlinks = follow_symlinks)
async def _is_gettable(self, path: str, follow_symlinks: bool) -> bool:
try:
return (await self._stat(path, follow_symlinks)).is_gettable
except NotImplementedError:
log(
DEBUG,
(
f"{self.log_name} doesn't implement stat(), judging by "
f'trailing slash if {path} is a file'
),
)
return path[-1] != '/'
except FileNotFoundError as e:
log(DEBUG, f'{self.log_name}: Failed to stat({path}) ({str(e)})')
return False
except Exception as e:
log(ERR, f'{self.log_name}: Failed to stat({path}) ({str(e)})')
raise
async def is_gettable(self, path: str, follow_symlinks: bool = True) -> bool:
return await self._is_gettable(
self._chroot(path), follow_symlinks = follow_symlinks
)
async def _readdir(self, path: str) -> Iterable[str]:
raise NotImplementedError(
f'{self.log_name}: readdir("{path}") is not implemented'