Add new root option in Path.which method

This commit adds to Path utility a couple of methods to manipulate
paths. One to rebase given paths to a new root and another one to
trim the given root path. In addition a new option in Path.which
is added to allow searches into chroot evironments.

Fixes #1276
This commit is contained in:
David Cassany 2019-11-27 08:12:06 +01:00
parent 79fca26097
commit dd4d2ed78d
No known key found for this signature in database
GPG Key ID: D91C0AAD9018D486
3 changed files with 59 additions and 2 deletions

View File

@ -810,7 +810,7 @@ class BootLoaderConfigGrub2(BootLoaderConfigBase):
def _get_grub2_mkconfig_tool(self):
for grub_mkconfig_tool in ['grub2-mkconfig', 'grub-mkconfig']:
if Path.which(grub_mkconfig_tool):
if Path.which(grub_mkconfig_tool, root_dir=self.root_dir):
return grub_mkconfig_tool
def _get_grub2_boot_path(self):

View File

@ -159,10 +159,49 @@ class Path:
['rmdir', '--ignore-fail-on-non-empty', sub_path]
)
@staticmethod
def move_to_root(root, elements):
"""
Change the given path elements to a new root directory
:param str root: the root path to trim
:param list elements: list of path names
:return: changed elements
:rtype: list
"""
result = []
for element in elements:
normalized_element = os.path.normpath(element)
result.append(
normalized_element.replace(
os.path.normpath(root), os.sep
).replace('{0}{0}'.format(os.sep), os.sep)
)
return result
@staticmethod
def rebase_to_root(root, elements):
"""
Include the root prefix for the given paths elements
:param str root: the new root path
:param list elements: list of path names
:return: changed elements
:rtype: list
"""
result = []
for element in elements:
result.append(os.path.normpath(os.sep.join([root, element])))
return result
@staticmethod
def which(
filename, alternative_lookup_paths=None,
custom_env=None, access_mode=None
custom_env=None, access_mode=None, root_dir=None
):
"""
Lookup file name in PATH
@ -173,6 +212,7 @@ class Path:
:param int access_mode: one of the os access modes or a combination of
them (os.R_OK, os.W_OK and os.X_OK). If the provided access mode
does not match the file is considered not existing
:param str root_dir: the root path to look at
:return: absolute path to file or None
@ -189,6 +229,8 @@ class Path:
lookup_paths = system_path.split(os.pathsep)
if alternative_lookup_paths:
lookup_paths += alternative_lookup_paths
if root_dir:
lookup_paths = Path.rebase_to_root(root_dir, lookup_paths)
multipart_message[0] += 'in paths "%s"' % ':'.join(lookup_paths)
for path in lookup_paths:
location = os.path.join(path, filename)

View File

@ -63,6 +63,16 @@ class TestPath:
assert 'remove_hierarchy: path /my_root/tmp is protected' in \
self._caplog.text
def test_move_to_root(self):
assert [
'/usr/bin', '/sbin'
] == Path.move_to_root('/root_dir', ['/root_dir/usr/bin', '/sbin'])
def test_rebase_to_root(self):
assert [
'/root_dir/usr/bin', '/root_dir/sbin'
] == Path.rebase_to_root('/root_dir', ['usr/bin', '/sbin'])
@patch('os.access')
@patch('os.environ.get')
@patch('os.path.exists')
@ -84,6 +94,11 @@ class TestPath:
'/usr/local/bin/some-file'
assert Path.which('some-file', custom_env={'PATH': 'custom_path'}) == \
'custom_path/some-file'
assert Path.which(
'some-file',
custom_env={'PATH': 'custom_path'},
root_dir='/root_dir'
) == '/root_dir/custom_path/some-file'
@patch('os.access')
@patch('os.environ.get')