Fix a "source directories do not exist" regression when configuration paths are relative symlinks and the bootstrap data source hook is enabled (#1292).
This commit is contained in:
parent
3f70cf0b29
commit
f3ae04225d
4 changed files with 32 additions and 7 deletions
4
NEWS
4
NEWS
|
|
@ -1,3 +1,7 @@
|
|||
2.1.5.dev0
|
||||
* #1292: Fix a "source directories do not exist" regression when configuration paths are relative
|
||||
symlinks and the bootstrap data source hook is enabled.
|
||||
|
||||
2.1.4
|
||||
* #1266: Add a stand-alone borgmatic Linux binary to the release downloads to serve as another way
|
||||
to install borgmatic. Consider this binary a beta feature.
|
||||
|
|
|
|||
|
|
@ -28,17 +28,20 @@ def resolve_config_path_symlinks(path):
|
|||
Given a path, resolve and yield each successive symlink until the final non-symlink target. If
|
||||
the given path isn't a symlink, then just yield it.
|
||||
|
||||
The purpose of this is to ensure that configuration files that are behind a symbolic link (or
|
||||
several) actually get backed up.
|
||||
|
||||
Raise ValueError if we have to follow too many symlinks without getting to the final target.
|
||||
'''
|
||||
original_path = path
|
||||
original_path = os.path.normpath(path)
|
||||
|
||||
for _ in range(MAXIMUM_CONFIG_SYMLINKS_TO_FOLLOW):
|
||||
yield os.path.abspath(path)
|
||||
yield path
|
||||
|
||||
if not os.path.islink(path):
|
||||
return
|
||||
|
||||
path = os.readlink(path)
|
||||
path = os.path.normpath(os.path.join(os.path.dirname(path), os.readlink(path)))
|
||||
|
||||
raise ValueError(f'Too many symlinks to follow for configuration path: {original_path}')
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
[project]
|
||||
name = "borgmatic"
|
||||
version = "2.1.4"
|
||||
version = "2.1.5.dev0"
|
||||
authors = [
|
||||
{ name="Dan Helfman", email="witten@torsion.org" },
|
||||
]
|
||||
|
|
|
|||
|
|
@ -7,14 +7,12 @@ from borgmatic.hooks.data_source import bootstrap as module
|
|||
|
||||
|
||||
def test_resolve_config_path_symlinks_passes_through_non_symlink():
|
||||
flexmock(module.os.path).should_receive('abspath').replace_with(lambda path: path)
|
||||
flexmock(module.os.path).should_receive('islink').and_return(False)
|
||||
|
||||
assert tuple(module.resolve_config_path_symlinks('test.yaml')) == ('test.yaml',)
|
||||
|
||||
|
||||
def test_resolve_config_path_symlinks_follows_each_symlink():
|
||||
flexmock(module.os.path).should_receive('abspath').replace_with(lambda path: path)
|
||||
flexmock(module.os.path).should_receive('islink').with_args('test.yaml').and_return(True)
|
||||
flexmock(module.os.path).should_receive('islink').with_args('dest1.yaml').and_return(True)
|
||||
flexmock(module.os.path).should_receive('islink').with_args('dest2.yaml').and_return(False)
|
||||
|
|
@ -29,9 +27,29 @@ def test_resolve_config_path_symlinks_follows_each_symlink():
|
|||
)
|
||||
|
||||
|
||||
def test_resolve_config_path_symlinks_follows_each_relative_symlink():
|
||||
flexmock(module.os.path).should_receive('islink').with_args('foo/bar/test.yaml').and_return(
|
||||
True
|
||||
)
|
||||
flexmock(module.os.path).should_receive('islink').with_args('foo/dest1.yaml').and_return(True)
|
||||
flexmock(module.os.path).should_receive('islink').with_args('dest2.yaml').and_return(False)
|
||||
flexmock(module.os).should_receive('readlink').with_args('foo/bar/test.yaml').and_return(
|
||||
'../dest1.yaml'
|
||||
)
|
||||
flexmock(module.os).should_receive('readlink').with_args('foo/dest1.yaml').and_return(
|
||||
'../dest2.yaml'
|
||||
)
|
||||
flexmock(module.os).should_receive('readlink').with_args('dest2.yaml').never()
|
||||
|
||||
assert tuple(module.resolve_config_path_symlinks('foo/bar/test.yaml')) == (
|
||||
'foo/bar/test.yaml',
|
||||
'foo/dest1.yaml',
|
||||
'dest2.yaml',
|
||||
)
|
||||
|
||||
|
||||
def test_resolve_config_path_symlinks_with_too_many_symlinks_raises():
|
||||
flexmock(module).MAXIMUM_CONFIG_SYMLINKS_TO_FOLLOW = 2
|
||||
flexmock(module.os.path).should_receive('abspath').replace_with(lambda path: path)
|
||||
flexmock(module.os.path).should_receive('islink').with_args('test.yaml').and_return(True)
|
||||
flexmock(module.os.path).should_receive('islink').with_args('dest1.yaml').and_return(True)
|
||||
flexmock(module.os.path).should_receive('islink').with_args('dest2.yaml').and_return(True)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue