util/path: add join_abs() to join potentially absolute paths
It turned out that in many cases, stages need to join two absolute paths, the pipeline tree path and the path on a booted system. However, the standard `os.path.join()` function can't handle such situation as just prepending the root to the subsequent paths. Add a new helper function, which is able to join any paths together, regardless if any of them is absolute or not. If the root is not absolute, the result will be made absolute to the filesystem root `/`. Signed-off-by: Tomáš Hozza <thozza@redhat.com>
This commit is contained in:
parent
67d9663c83
commit
8463394d2c
2 changed files with 54 additions and 1 deletions
|
|
@ -2,7 +2,7 @@
|
|||
import errno
|
||||
import os
|
||||
import os.path
|
||||
from typing import Optional
|
||||
from typing import Optional, Union
|
||||
|
||||
from .ctx import suppress_oserror
|
||||
|
||||
|
|
@ -41,3 +41,18 @@ def in_tree(path: str, tree: str, must_exist: bool = False) -> bool:
|
|||
if path.startswith(tree):
|
||||
return not must_exist or os.path.exists(path)
|
||||
return False
|
||||
|
||||
|
||||
def join_abs(root: Union[str, os.PathLike], *paths: Union[str, os.PathLike]) -> str:
|
||||
"""
|
||||
Join root and paths together, handling the case where paths are absolute paths.
|
||||
In that case, paths are just appended to root as if they were relative paths.
|
||||
The result is always an absolute path relative to the filesystem root '/'.
|
||||
"""
|
||||
final_path = root
|
||||
for path in paths:
|
||||
if os.path.isabs(path):
|
||||
final_path = os.path.join(final_path, os.path.relpath(path, os.sep))
|
||||
else:
|
||||
final_path = os.path.join(final_path, path)
|
||||
return os.path.normpath(os.path.join(os.sep, final_path))
|
||||
|
|
|
|||
|
|
@ -68,3 +68,41 @@ def test_in_tree():
|
|||
|
||||
for args, expected in cases.items():
|
||||
assert path.in_tree(*args) == expected, args
|
||||
|
||||
|
||||
@pytest.mark.parametrize("test_case", (
|
||||
{
|
||||
"args": ("",),
|
||||
"expected": "/"
|
||||
},
|
||||
{
|
||||
"args": ("", "file"),
|
||||
"expected": "/file"
|
||||
},
|
||||
{
|
||||
"args": ("", "/file"),
|
||||
"expected": "/file"
|
||||
},
|
||||
{
|
||||
"args": ("/tmp", "/file"),
|
||||
"expected": "/tmp/file"
|
||||
},
|
||||
{
|
||||
"args": ("/tmp", "/foo", "/bar"),
|
||||
"expected": "/tmp/foo/bar"
|
||||
},
|
||||
{
|
||||
"args": ("/", "/foo"),
|
||||
"expected": "/foo"
|
||||
},
|
||||
{
|
||||
"args": ("/", "/foo", "/bar"),
|
||||
"expected": "/foo/bar"
|
||||
},
|
||||
{
|
||||
"args": (Path("/tmp"), "/foo", "/bar"),
|
||||
"expected": "/tmp/foo/bar"
|
||||
},
|
||||
))
|
||||
def test_join_abs(test_case):
|
||||
assert path.join_abs(*test_case["args"]) == test_case["expected"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue