Skip to content

Commit

Permalink
fix working_dir and relative paths
Browse files Browse the repository at this point in the history
  • Loading branch information
Ken Kundert authored and Ken Kundert committed Dec 27, 2021
1 parent 4a1079f commit 993de95
Show file tree
Hide file tree
Showing 12 changed files with 284 additions and 267 deletions.
2 changes: 1 addition & 1 deletion doc/configuring.rst
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ done using :ref:`excludes` and :ref:`exclude_from` and using the path keys
(``+``, ``-``, ``!``) in :ref:`patterns` and :ref:`patterns_from`. When you use
a relative path to specify a recursion root then you should also use relative
paths for its include and exclude paths. Similarly, if you use an absolute path
for the a recursion root then you should also use absolute paths for its include
for the recursion root then you should also use absolute paths for its include
and exclude paths. *Borg* is okay with you having some recursion roots specified
with relative paths and some with absolute paths, but this confuses *Emborg*
when it comes time to extract or restore files from your repository. With
Expand Down
10 changes: 5 additions & 5 deletions emborg/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,19 +149,19 @@ def get_available_files(settings, archive):

# get_archive_paths() {{{2
def get_archive_paths(paths, settings):
# need to construct a path to the file that is compatible with those
# Need to construct a path to the file that is compatible with those
# paths stored in borg, thus it must begin with a src_dir (cannot just
# use the absolute path because the corresponding src_dir path may
# contain a symbolic link, in which the absolute path would not be found
# in the borg repository
# convert to paths relative to the working directory
# in the borg repository.
# Convert to paths relative to the working directory.
#
paths_not_found = set(paths)
resolved_paths = []
roots = settings.resolve_patterns([], skip_checks=True)
settings.resolve_patterns([], skip_checks=True)
try:
for root_dir in settings.roots:
resolved_root_dir = root_dir.resolve()
resolved_root_dir = (settings.working_dir / root_dir).resolve()
for name in paths:
path = to_path(name)
resolved_path = path.resolve()
Expand Down
2 changes: 1 addition & 1 deletion emborg/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def main():
inform.narrate = True

Hooks.provision_hooks()
worst_exit_status = 0

try:
# find the command
Expand All @@ -103,7 +104,6 @@ def main():
if exit_status is not None:
terminate(exit_status)

worst_exit_status = 0
queue = ConfigQueue(cmd)
while queue:
with Settings(config, emborg_opts, queue) as settings:
Expand Down
62 changes: 36 additions & 26 deletions emborg/patterns.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@

# Imports {{{1
from os.path import expanduser as expand_user

from inform import Error, error

from inform import Error, error, log
from shlib import to_path


Expand All @@ -31,14 +29,22 @@

# check_root() {{{1
def check_root(root, working_dir):
root = to_path(root)
if not root.exists():
if str(root) == '.':
log(
"Unable to determine whether paths are contained in a root,",
"because '.' is a root."
)
abs_root = working_dir / root
if not abs_root.exists():
raise Error("not found.", culprit=root)
# the following is a bit cleaner, but no available until python 3.9
#if not abs_root.is_relative_to(working_dir):
# raise Error("not in working directory:", working_dir, culprit=root)
try:
root.resolve().relative_to(working_dir.resolve())
abs_root.relative_to(working_dir)
except ValueError:
raise Error("not in working directory:", working_dir, culprit=root)
return root.is_absolute()
return to_path(root).is_absolute()


# check_roots() {{{1
Expand Down Expand Up @@ -80,15 +86,21 @@ def check_pattern(pattern, default_style, roots, expand_tilde):
path = expand_user(path)
pattern = prefix + path
else:
raise Error("borg does not interpret leading tilde as user.")
raise Error(
"do not use leading ~,",
"borg does not treat it as a user home directory.",
)

# check to see that path corresponds to a root
path = str(to_path(path))
if any(path.startswith(str(root)) for root in roots):
return pattern
if style in ["fm", "sh"]:
if any(str(root).startswith(path.partition("*")[0]) for root in roots):
return pattern

if any(str(root) == '.' for root in roots):
# cannot check paths if root is '.'
return pattern
raise Error("path is not in a known root.")


Expand All @@ -100,7 +112,8 @@ def check_patterns(
default_style = "sh"
for pattern in patterns:
pattern = pattern.strip()
culprit = (str(src), repr(pattern))
culprit = src
codicil = repr(pattern)
kind = pattern[0:1]
arg = pattern[1:].lstrip()
if kind in ["", "#"]:
Expand All @@ -109,35 +122,32 @@ def check_patterns(
error("unknown type", culprit=culprit)
continue
if kind == "R":
try:
if arg[0] == "~" and not expand_tilde:
error(
"borg does not interpret leading tilde as user.",
culprit=culprit,
)
root = expand_user(arg)
if not skip_checks:
check_root(root, working_dir)
roots.append(to_path(root))
except AttributeError:
error("can no longer add roots.", culprit=culprit)
if arg[0] == "~" and not expand_tilde:
error(
"borg does not interpret leading tilde as user.",
culprit=culprit, codicil=codicil
)
root = expand_user(arg)
if not skip_checks:
check_root(root, working_dir)
roots.append(to_path(root))
paths.append(kind + " " + root)
elif kind == "P":
if arg in known_styles:
default_style = arg
else:
error("unknown pattern style.", culprit=culprit)
error("unknown pattern style.", culprit=culprit, codicil=codicil)
paths.append(kind + " " + arg)
elif not roots:
error("no roots available.", culprit=culprit)
error("no roots available.", culprit=culprit, codicil=codicil)
return []
else:
try:
paths.append(
kind + " " + check_pattern(arg, default_style, roots, expand_tilde)
)
except Error as e:
e.report(culprit=culprit)
e.report(culprit=culprit, codicil=codicil)
return paths


Expand All @@ -155,7 +165,7 @@ def check_excludes(patterns, roots, src, expand_tilde=True):
try:
paths.append(check_pattern(pattern, "fm", roots, expand_tilde))
except Error as e:
e.report(culprit=(str(src), repr(pattern)))
e.report(culprit=src, codicil=repr(pattern))
return paths


Expand Down
2 changes: 1 addition & 1 deletion emborg/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -343,7 +343,7 @@ def check(self):

self.working_dir = to_path(self.settings.get("working_dir", "/"))
if not self.working_dir.exists():
raise Error("{self.working_dir!s} not found.", culprit="working_dir")
raise Error(f"{self.working_dir!s} not found.", culprit="working_dir")
if not self.working_dir.is_absolute():
raise Error("must be an absolute path.", culprit="working_dir")

Expand Down
18 changes: 12 additions & 6 deletions tests/CONFIGS/README
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
There are 7 base configurations and one composite configurations.
There are 9 base configurations and one composite configurations.
Before the start of testing, 'CONFIGS' is copied to 'configs'

The tests back up only this directory or the 'configs' subdirectory
Expand Down Expand Up @@ -29,25 +29,31 @@ test3:
test4:
- backs up the ./configs directory
- uses patterns with root and excludes to select which files to backup
- sets working_dir to . (relative paths)
- sets working_dir to .. (relative paths)
- uses default mount point

test5
test5:
- backs up the . directory
- uses patterns with root, includes and excludes to select which files to
backup
- uses default mount point

test6
test6:
- backs up the . directory
- uses patterns_from with root and excludes to select which files to backup
- sets working_dir to . (relative paths)
- sets working_dir to .. (relative paths)
- uses default mount point

test7
test7:
- backs up the . directory
- uses patterns_from with root, includes and excludes to select which files
to backup
- uses default mount point

test8:
- backs up the ./configs.symlink/subdir directory
- uses patterns with root and excludes to select which files to backup
- sets working_dir to . (relative paths)
- uses default mount point

tests contains test{0,1,2,3}
17 changes: 10 additions & 7 deletions tests/CONFIGS/test4
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from shlib import cwd
working_dir = str(cwd())
patterns = '''
R ./configs
- fm:*/.viminfo
- **/.*.swp
- **/.*.swo
'''
current_dir = cwd()
parent_dir = str(current_dir.parent)
this_dir = current_dir.name
working_dir = parent_dir
patterns = f"""
R {this_dir}/configs
- fm:{this_dir}/*/.viminfo
- {this_dir}/**/.*.swp
- {this_dir}/**/.*.swo
"""
default_mount_point = '~/EMBORG'
report_diffs_cmd = "diff -r"
2 changes: 1 addition & 1 deletion tests/CONFIGS/test6
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from shlib import cwd
working_dir = str(cwd())
working_dir = str(cwd().parent)
patterns_from = '{config_dir}/test6patterns'
default_mount_point = '~/EMBORG'
8 changes: 4 additions & 4 deletions tests/CONFIGS/test6patterns
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
R ./configs
- fm:*/.viminfo
- **/.*.swp
- **/.*.swo
R ./tests/configs
- fm:./tests/*/.viminfo
- ./tests/**/.*.swp
- ./tests/**/.*.swo
6 changes: 3 additions & 3 deletions tests/CONFIGS/test7patterns
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
R «TESTS»
+ «TESTS»/configs
- «TESTS»
R ⟪EMBORG⟫/tests
+ ⟪EMBORG⟫/tests/configs
- ⟪EMBORG⟫/tests
- fm:*/.viminfo
- **/.*.swp
- **/.*.swo

0 comments on commit 993de95

Please sign in to comment.