mirror of
https://github.com/borgmatic-collective/borgmatic.git
synced 2026-07-22 10:13:00 +02:00
Compare commits
5
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6ac2c86d2d | ||
|
|
b7ecc9c6c3 | ||
|
|
4f728b1cd4 | ||
|
|
78db924b70 | ||
|
|
b55834c1ca |
@@ -1,6 +1,9 @@
|
||||
2.1.6
|
||||
* #1256: Fix a race condition in which borgmatic sometimes swallows Borg error output without
|
||||
logging it.
|
||||
2.1.6.dev0
|
||||
* #1267: Support multiple borgmatic instances run in parallel—as long as they're operating on
|
||||
different Borg repositories. This required an internal change to the runtime directory path,
|
||||
which may cause a one-time performance hit (Borg cache misses) for Borg 1.x users of database and
|
||||
filesystem hooks. See the documentation for more information:
|
||||
https://torsion.org/borgmatic/how-to/make-per-application-backups/#parallelism
|
||||
* #1300: Fix the "source_directories_must_exist" option to support source directories relative to a
|
||||
"working_directory".
|
||||
* #1301: Expand the "patterns_from" and "exclude_from" options to support paths containing tildes
|
||||
@@ -10,16 +13,6 @@
|
||||
* #1303: For the MariaDB hook, include only a subset of system data when dumping the "mysql" system
|
||||
database (or "all" databases), so the dump is actually restorable. See the documentation for more
|
||||
information: https://torsion.org/borgmatic/reference/configuration/data-sources/mariadb/
|
||||
* #1314: Add a minimal stand-alone borgmatic binary in addition to the standard one. The minimal
|
||||
binary omits support for the Apprise monitoring hook.
|
||||
* Add an experimental "browse" action providing a console UI for browsing your backups. See the
|
||||
documentation for more information:
|
||||
https://torsion.org/borgmatic/how-to/inspect-your-backups/#browsing-backups
|
||||
* #1308: Update the Apprise monitoring hook's "url" option to support loading credentials with the
|
||||
"{credential ...}" syntax. See the documentation for more information:
|
||||
https://torsion.org/borgmatic/reference/configuration/credentials/
|
||||
* #1309: Add a "--quick-stats" flag and corresponding "quick_statistics" option for showing only
|
||||
abbreviated statistics for the "create" action. Borg 1.4.5+ only.
|
||||
* Update the KeePassXC credential hook to support KeePassXC's secret service integration. See the
|
||||
documentation for more information:
|
||||
https://torsion.org/borgmatic/reference/configuration/credentials/keepassxc/
|
||||
|
||||
@@ -3,10 +3,10 @@
|
||||
apprise==1.10.0 # via -r binary_requirements.in
|
||||
attrs==26.1.0 # via jsonschema, referencing, -r binary_requirements.in
|
||||
. # via -r binary_requirements.in
|
||||
certifi==2026.5.20 # via apprise, requests, -r binary_requirements.in
|
||||
certifi==2026.4.22 # via apprise, requests, -r binary_requirements.in
|
||||
charset-normalizer==3.4.7 # via requests, -r binary_requirements.in
|
||||
click==8.4.1 # via apprise, -r binary_requirements.in
|
||||
idna==3.16 # via requests, -r binary_requirements.in
|
||||
click==8.3.3 # via apprise, -r binary_requirements.in
|
||||
idna==3.13 # via requests, -r binary_requirements.in
|
||||
jsonschema==4.26.0 # via borgmatic, -r binary_requirements.in
|
||||
jsonschema-specifications==2025.9.1 # via jsonschema, -r binary_requirements.in
|
||||
markdown==3.10.2 # via apprise, -r binary_requirements.in
|
||||
@@ -14,8 +14,8 @@ oauthlib==3.3.1 # via requests-oauthlib, -r binary_requirements.in
|
||||
packaging==26.2 # via borgmatic, -r binary_requirements.in
|
||||
pyyaml==6.0.3 # via apprise, -r binary_requirements.in
|
||||
referencing==0.37.0 # via jsonschema, jsonschema-specifications, -r binary_requirements.in
|
||||
requests==2.34.2 # via apprise, borgmatic, requests-oauthlib, -r binary_requirements.in
|
||||
requests==2.33.1 # via apprise, borgmatic, requests-oauthlib, -r binary_requirements.in
|
||||
requests-oauthlib==2.0.0 # via apprise, -r binary_requirements.in
|
||||
rpds-py==0.30.0 # via jsonschema, referencing, -r binary_requirements.in
|
||||
ruamel-yaml==0.19.1 # via borgmatic, -r binary_requirements.in
|
||||
urllib3==2.7.0 # via requests, -r binary_requirements.in
|
||||
urllib3==2.6.3 # via requests, -r binary_requirements.in
|
||||
|
||||
@@ -1,108 +0,0 @@
|
||||
import signal
|
||||
|
||||
import textual.app
|
||||
import textual.binding
|
||||
import textual.widgets
|
||||
|
||||
import borgmatic.actions.browse.carousel
|
||||
import borgmatic.actions.browse.configuration_files_list
|
||||
import borgmatic.actions.browse.logs
|
||||
import borgmatic.actions.browse.repositories_list
|
||||
|
||||
|
||||
class Browse_app(textual.app.App):
|
||||
'''
|
||||
The main app / entry point for the browse action UI.
|
||||
'''
|
||||
|
||||
BINDINGS = (
|
||||
textual.binding.Binding(key='q', action='quit', description='quit'),
|
||||
textual.binding.Binding(key='v', action='toggle_logs', description='view logs'),
|
||||
textual.binding.Binding(
|
||||
key='c', action='command_palette', description='commands', show=False
|
||||
),
|
||||
)
|
||||
COMMAND_PALETTE_BINDING = 'c'
|
||||
CSS = '''
|
||||
.panel {
|
||||
border: round $primary;
|
||||
border-title-color: $text-primary;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#logs {
|
||||
width: 100%;
|
||||
height: 50%;
|
||||
display: none;
|
||||
}
|
||||
'''
|
||||
|
||||
def __init__(self, configs):
|
||||
self.configs = configs
|
||||
|
||||
super().__init__()
|
||||
|
||||
def get_system_commands(self, screen): # pragma: no cover
|
||||
'''
|
||||
Remove the screenshot system command because it produces broken screenshots. (Emoji
|
||||
weirdness, etc.) Also remove minimize and maximize because they don't accomplish much with
|
||||
out particular layout.
|
||||
'''
|
||||
yield from (
|
||||
command
|
||||
for command in super().get_system_commands(screen)
|
||||
if command.title not in {'Screenshot', 'Minimize', 'Maximize'}
|
||||
)
|
||||
|
||||
def compose(self):
|
||||
'''
|
||||
Compose a UI consisting of:
|
||||
|
||||
* a header with the application name
|
||||
* a carousel container that contains the main UI panels
|
||||
* a logs panel where Python logs show up (panel hidden by default)
|
||||
* a footer with available keys listed
|
||||
'''
|
||||
yield textual.widgets.Header()
|
||||
yield borgmatic.actions.browse.carousel.Carousel(
|
||||
[
|
||||
borgmatic.actions.browse.configuration_files_list.Configuration_files_list(
|
||||
self.configs
|
||||
)
|
||||
]
|
||||
if len(self.configs) > 1
|
||||
else [
|
||||
borgmatic.actions.browse.repositories_list.Repositories_list(
|
||||
next(iter(self.configs.values()))
|
||||
)
|
||||
]
|
||||
)
|
||||
|
||||
logs_panel = borgmatic.actions.browse.logs.Logs()
|
||||
yield logs_panel
|
||||
yield textual.widgets.Footer()
|
||||
|
||||
borgmatic.actions.browse.logs.log_to_widget(logs_panel)
|
||||
|
||||
def on_mount(self):
|
||||
'''
|
||||
Set the application title, which ends up in the header.
|
||||
'''
|
||||
self.title = 'borgmatic browse'
|
||||
|
||||
def action_toggle_logs(self):
|
||||
'''
|
||||
Toggle the show/hide status of the logs panel.
|
||||
'''
|
||||
logs_panel = self.query_one('#logs')
|
||||
logs_panel.styles.display = 'none' if logs_panel.styles.display == 'block' else 'block'
|
||||
|
||||
def exit(self): # pragma: no cover
|
||||
'''
|
||||
Exit the application. But first raise a SIGTERM (handled in borgmatic/signals.py) to
|
||||
encourage a fast exit by killing any ongoing Borg subprocesses.
|
||||
'''
|
||||
signal.raise_signal(signal.SIGTERM)
|
||||
|
||||
super().exit()
|
||||
@@ -1,143 +0,0 @@
|
||||
import argparse
|
||||
import collections
|
||||
import enum
|
||||
import json
|
||||
import logging
|
||||
|
||||
import binaryornot.helpers
|
||||
|
||||
import borgmatic.borg.extract
|
||||
import borgmatic.borg.list
|
||||
import borgmatic.borg.repo_list
|
||||
import borgmatic.borg.version
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class Path_type(enum.Enum):
|
||||
DIRECTORY = 'd'
|
||||
LINK = 'l'
|
||||
PIPE = 'p'
|
||||
FILE = '-'
|
||||
|
||||
|
||||
# A data structure capturing a path stored in a Borg archive.
|
||||
Archive_path = collections.namedtuple(
|
||||
'Archive_path',
|
||||
('path_type', 'file_path', 'link_target'),
|
||||
)
|
||||
|
||||
|
||||
def get_repository_archives(config, repository):
|
||||
'''
|
||||
Given a configuration dict and a repository dict, return a list of the repository's archives,
|
||||
one dict per archive.
|
||||
'''
|
||||
with borgmatic.logger.Log_prefix(repository.get('label', repository['path'])):
|
||||
logger.info('Listing repository')
|
||||
repo_list_arguments = argparse.Namespace(
|
||||
repository=repository['path'],
|
||||
short=None,
|
||||
format=None,
|
||||
json=True,
|
||||
prefix=None,
|
||||
match_archives=None,
|
||||
sort_by=None,
|
||||
first=None,
|
||||
last=None,
|
||||
)
|
||||
global_arguments = argparse.Namespace()
|
||||
local_path = config.get('local_path', 'borg')
|
||||
remote_path = config.get('remote_path')
|
||||
local_borg_version = borgmatic.borg.version.local_borg_version(config, local_path)
|
||||
|
||||
return json.loads(
|
||||
borgmatic.borg.repo_list.list_repository(
|
||||
repository['path'],
|
||||
config,
|
||||
local_borg_version,
|
||||
repo_list_arguments,
|
||||
global_arguments,
|
||||
local_path,
|
||||
remote_path,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def get_archive_paths(config, repository, archive_name):
|
||||
'''
|
||||
Given a configuration dict, a repository dict, and an archive name in that repository, get a
|
||||
generator of files, directories, symlinks, etc. found in the archive, each as an Archive_path
|
||||
instance.
|
||||
'''
|
||||
with borgmatic.logger.Log_prefix(repository.get('label', repository['path'])):
|
||||
logger.info(f'Listing archive {archive_name}')
|
||||
|
||||
global_arguments = argparse.Namespace()
|
||||
local_path = config.get('local_path', 'borg')
|
||||
remote_path = config.get('remote_path')
|
||||
local_borg_version = borgmatic.borg.version.local_borg_version(config, local_path)
|
||||
|
||||
return (
|
||||
Archive_path(
|
||||
path_data['type'],
|
||||
path_data['path'],
|
||||
path_data.get('linktarget'),
|
||||
)
|
||||
for path_data in borgmatic.borg.list.capture_archive_listing(
|
||||
repository['path'],
|
||||
archive_name,
|
||||
config,
|
||||
local_borg_version,
|
||||
global_arguments,
|
||||
local_path=local_path,
|
||||
remote_path=remote_path,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
READLINES_HINT_BYTES = 100000
|
||||
TRUNCATION_MESSAGE = '[... truncated for display ...]'
|
||||
|
||||
|
||||
def get_archive_file_content(config, repository, archive_name, file_path):
|
||||
'''
|
||||
Given a configuration dict, a repository dict, an archive name in that repository, and a file
|
||||
path in that archive, return the file's contents or None if the file can't be loaded, e.g.
|
||||
because it's binary or can't be decoded.
|
||||
|
||||
If the file is too large, then truncate the returned content.
|
||||
'''
|
||||
with borgmatic.logger.Log_prefix(repository.get('label', repository['path'])):
|
||||
logger.info(f'Getting archive content of file {file_path}')
|
||||
local_path = config.get('local_path', 'borg')
|
||||
remote_path = config.get('remote_path')
|
||||
|
||||
lines = borgmatic.borg.extract.extract_archive(
|
||||
dry_run=False,
|
||||
repository=repository['path'],
|
||||
archive=archive_name,
|
||||
paths=(file_path,),
|
||||
config=config,
|
||||
local_borg_version=borgmatic.borg.version.local_borg_version(config, local_path),
|
||||
global_arguments=argparse.Namespace(),
|
||||
local_path=local_path,
|
||||
remote_path=remote_path,
|
||||
destination_path=None,
|
||||
strip_components=None,
|
||||
extract_to_stdout=True,
|
||||
).stdout.readlines(READLINES_HINT_BYTES)
|
||||
|
||||
content = b''.join(lines)
|
||||
|
||||
if binaryornot.helpers.is_binary_string(content):
|
||||
return None
|
||||
|
||||
try:
|
||||
return (
|
||||
content.decode()
|
||||
if len(content) < READLINES_HINT_BYTES
|
||||
else f'{content.decode()}\n{TRUNCATION_MESSAGE}'
|
||||
)
|
||||
except UnicodeDecodeError:
|
||||
return None
|
||||
@@ -1,89 +0,0 @@
|
||||
import textual.widgets
|
||||
|
||||
import borgmatic.actions.browse.bindings
|
||||
import borgmatic.actions.browse.loading
|
||||
import borgmatic.actions.browse.workers
|
||||
|
||||
|
||||
class Archives_list(textual.widgets.OptionList):
|
||||
'''
|
||||
A widget for selecting a single Borg archive from among the archives in a repository. The item
|
||||
selection event is handled in a Carousel instance, the parent widget of an Archives_list.
|
||||
'''
|
||||
|
||||
BINDINGS = borgmatic.actions.browse.bindings.OPTION_LIST_BINDINGS
|
||||
|
||||
def __init__(self, config, repository):
|
||||
'''
|
||||
Given a configuration dict and a repository dict, prepare to load the archives from the
|
||||
repository for eventual display in this widget. Actual loading kicks off in on_mount()
|
||||
below.
|
||||
'''
|
||||
self.config = config
|
||||
self.repository = repository
|
||||
|
||||
super().__init__(classes='panel')
|
||||
self.border_title = '📚 archives'
|
||||
self.highlighted_option_changed = False
|
||||
self.archive_loaded = borgmatic.actions.browse.workers.Archive_loaded(
|
||||
self, 'archive loaded'
|
||||
)
|
||||
|
||||
self.loading_timer = borgmatic.actions.browse.loading.add_inline_loading_indicator(self)
|
||||
|
||||
def on_mount(self):
|
||||
'''
|
||||
When this widget gets mounted in the DOM, subscribe to archive loaded events so that we can
|
||||
find out about archives as they load. Also start loading archives from the repository.
|
||||
|
||||
Loading is started *after* subscribing to the archive loaded signal so that there's not a
|
||||
gap where we might miss out on signal publishes.
|
||||
'''
|
||||
self.archive_loaded.subscribe(self, self.on_archive_loaded)
|
||||
|
||||
borgmatic.actions.browse.workers.add_repository_archives(
|
||||
self.app,
|
||||
archive_loaded=self.archive_loaded,
|
||||
config=self.config,
|
||||
repository=self.repository,
|
||||
)
|
||||
|
||||
def on_archive_loaded(self, archive_name):
|
||||
'''
|
||||
When an archive loads, add it as an option to this archives list. But if we get a
|
||||
signal that all path loading is complete, stop and remove our loading indicator.
|
||||
'''
|
||||
if archive_name is borgmatic.actions.browse.workers.LOADING_DONE:
|
||||
self.loading_timer.stop()
|
||||
self.remove_option('loading-indicator')
|
||||
return
|
||||
|
||||
label_pieces = (
|
||||
(archive_name, '[dim](latest)[/dim]') if len(self.options) == 1 else (archive_name,)
|
||||
)
|
||||
highlighted_option = self.highlighted_option
|
||||
|
||||
loading_indicator = self.get_option('loading-indicator')
|
||||
self.remove_option('loading-indicator')
|
||||
self.add_options(
|
||||
(
|
||||
textual.widgets.option_list.Option(' '.join(label_pieces), id=archive_name),
|
||||
loading_indicator,
|
||||
),
|
||||
)
|
||||
|
||||
# Retain the highlighted option position even as other options load around it.
|
||||
self.highlighted = (
|
||||
self.get_option_index(highlighted_option.id)
|
||||
if highlighted_option and self.highlighted_option_changed
|
||||
else 0
|
||||
)
|
||||
|
||||
def on_option_list_option_highlighted(self, event):
|
||||
'''
|
||||
When the highlighted option changes, record that fact. This flag is consumed in
|
||||
borgmatic.actions.browse.workers.add_repository_archives() in order to retain the
|
||||
highlighted option even as other options load around it.
|
||||
'''
|
||||
if self.highlighted not in {None, 0}:
|
||||
self.highlighted_option_changed = True
|
||||
@@ -1,22 +0,0 @@
|
||||
import textual.binding
|
||||
import textual.widgets
|
||||
|
||||
OPTION_LIST_BINDINGS = (
|
||||
*textual.widgets.OptionList.BINDINGS,
|
||||
textual.binding.Binding(
|
||||
key='up,k', action='cursor_up', description='scroll up', show=True, priority=True
|
||||
),
|
||||
textual.binding.Binding(
|
||||
key='down,j', action='cursor_down', description='scroll down', show=True, priority=True
|
||||
),
|
||||
textual.binding.Binding(
|
||||
key='pageup', action='page_up', description='page up', show=True, priority=True
|
||||
),
|
||||
textual.binding.Binding(
|
||||
key='pagedown', action='page_down', description='page down', show=True, priority=True
|
||||
),
|
||||
textual.binding.Binding(
|
||||
key='enter', action='select', description='select', show=True, priority=True
|
||||
),
|
||||
textual.binding.Binding(key='right,l', action='select', description='select', show=False),
|
||||
)
|
||||
@@ -1,153 +0,0 @@
|
||||
import os
|
||||
|
||||
import textual.binding
|
||||
import textual.containers
|
||||
|
||||
import borgmatic.actions.browse.archive
|
||||
import borgmatic.actions.browse.archives_list
|
||||
import borgmatic.actions.browse.configuration_files_list
|
||||
import borgmatic.actions.browse.directory_list
|
||||
import borgmatic.actions.browse.file_preview
|
||||
import borgmatic.actions.browse.icons
|
||||
import borgmatic.actions.browse.repositories_list
|
||||
|
||||
|
||||
def make_next_panel(focused_panel, option_id):
|
||||
'''
|
||||
Given a focused panel widget and the selected option ID, return the next panel corresponding to
|
||||
that selection. This is the mechanism by which the user can successively drill down from
|
||||
configuration file to repository to archive to root directory to non-root directory or file.
|
||||
|
||||
If the particular option ID on the focused panel doesn't have a supported next panel, then
|
||||
return None.
|
||||
'''
|
||||
if isinstance(
|
||||
focused_panel, borgmatic.actions.browse.configuration_files_list.Configuration_files_list
|
||||
):
|
||||
return borgmatic.actions.browse.repositories_list.Repositories_list(
|
||||
config=focused_panel.configs[option_id]
|
||||
)
|
||||
|
||||
if isinstance(focused_panel, borgmatic.actions.browse.repositories_list.Repositories_list):
|
||||
return borgmatic.actions.browse.archives_list.Archives_list(
|
||||
config=focused_panel.config, repository=focused_panel.repositories[option_id]
|
||||
)
|
||||
|
||||
if isinstance(focused_panel, borgmatic.actions.browse.archives_list.Archives_list):
|
||||
return borgmatic.actions.browse.directory_list.Directory_list(
|
||||
config=focused_panel.config, repository=focused_panel.repository, archive_name=option_id
|
||||
)
|
||||
|
||||
if isinstance(focused_panel, borgmatic.actions.browse.directory_list.Directory_list):
|
||||
option = focused_panel.get_option(option_id)
|
||||
|
||||
if option.prompt.startswith(
|
||||
borgmatic.actions.browse.icons.PATH_TYPE_ICONS[
|
||||
borgmatic.actions.browse.archive.Path_type.DIRECTORY.value
|
||||
]
|
||||
):
|
||||
return borgmatic.actions.browse.directory_list.Directory_list(
|
||||
focused_panel.config,
|
||||
focused_panel.repository,
|
||||
focused_panel.archive_name,
|
||||
path_loaded=focused_panel.path_loaded,
|
||||
path_components=(*focused_panel.path_components, option_id),
|
||||
)
|
||||
|
||||
if option.prompt.startswith(
|
||||
borgmatic.actions.browse.icons.PATH_TYPE_ICONS[
|
||||
borgmatic.actions.browse.archive.Path_type.FILE.value
|
||||
]
|
||||
):
|
||||
return borgmatic.actions.browse.file_preview.File_preview(
|
||||
focused_panel.config,
|
||||
focused_panel.repository,
|
||||
focused_panel.archive_name,
|
||||
file_path=os.path.sep.join((*focused_panel.path_components, option_id)),
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
class Carousel(textual.containers.Horizontal):
|
||||
BINDINGS = (
|
||||
textual.binding.Binding(
|
||||
key='left,h', action='previous', description='previous', priority=True
|
||||
),
|
||||
)
|
||||
|
||||
def __init__(self, panels):
|
||||
self.panels = panels
|
||||
self.focused_panel = panels[0]
|
||||
|
||||
super().__init__()
|
||||
|
||||
def compose(self):
|
||||
'''
|
||||
Compose with each of the contained panels and focus the first one.
|
||||
'''
|
||||
yield from self.panels
|
||||
|
||||
self.focused_panel.focus()
|
||||
|
||||
def action_previous(self):
|
||||
'''
|
||||
Make the previous panel into the focused panel.
|
||||
'''
|
||||
previous_panel_index = self.panels.index(self.focused_panel) - 1
|
||||
|
||||
if previous_panel_index < 0:
|
||||
return
|
||||
|
||||
self.focused_panel.styles.display = 'none'
|
||||
|
||||
self.focused_panel = self.panels[previous_panel_index]
|
||||
self.focused_panel.styles.display = 'block'
|
||||
self.focused_panel.focus()
|
||||
|
||||
def action_next(self, option_id):
|
||||
'''
|
||||
Hide the current focused panel and create the next one.
|
||||
'''
|
||||
next_panel_index = self.panels.index(self.focused_panel) + 1
|
||||
|
||||
if next_panel_index < len(self.panels):
|
||||
next_panel = self.panels[next_panel_index]
|
||||
next_panel.styles.display = 'block'
|
||||
else:
|
||||
next_panel = make_next_panel(self.focused_panel, option_id)
|
||||
|
||||
if next_panel is None:
|
||||
self.notify('Cannot display this content', severity='warning')
|
||||
return
|
||||
|
||||
self.panels.append(next_panel)
|
||||
next_panel.highlighted = 0
|
||||
|
||||
self.focused_panel.styles.display = 'none'
|
||||
self.focused_panel = next_panel
|
||||
self.focused_panel.focus()
|
||||
self.mount(self.focused_panel)
|
||||
|
||||
def on_option_list_option_highlighted(self, event):
|
||||
'''
|
||||
The highlighted option has changed, so truncate any next panels.
|
||||
'''
|
||||
next_panel_index = self.panels.index(self.focused_panel) + 1
|
||||
|
||||
del self.panels[next_panel_index:]
|
||||
|
||||
def on_option_list_option_selected(self, event):
|
||||
'''
|
||||
An option has been selected, so advance to the next panel—unless the option selected is
|
||||
"..", in which case go to the previous panel.
|
||||
'''
|
||||
if (
|
||||
event.option_list != self.focused_panel or event.option_id == 'loading-indicator'
|
||||
): # pragma: no cover
|
||||
return
|
||||
|
||||
if event.option_id == '..':
|
||||
self.action_previous()
|
||||
else:
|
||||
self.action_next(event.option_id)
|
||||
@@ -1,33 +0,0 @@
|
||||
import os
|
||||
|
||||
import textual.widgets
|
||||
|
||||
import borgmatic.actions.browse.bindings
|
||||
|
||||
|
||||
class Configuration_files_list(textual.widgets.OptionList):
|
||||
'''
|
||||
A widget for selecting a single borgmatic configuration file from among available configuration
|
||||
files. The item selection event is handled in a Carousel instance, the parent widget of an
|
||||
Configuration_files_list.
|
||||
'''
|
||||
|
||||
BINDINGS = borgmatic.actions.browse.bindings.OPTION_LIST_BINDINGS
|
||||
|
||||
def __init__(self, configs):
|
||||
'''
|
||||
Given a dict mapping from configuration path to corresponding configuration dict, add each
|
||||
configuration path as an option to this widget.
|
||||
'''
|
||||
self.configs = configs
|
||||
home_directory = os.path.expanduser('~')
|
||||
|
||||
super().__init__(
|
||||
*(
|
||||
textual.widgets.option_list.Option(unexpanded_path, id=config_path)
|
||||
for config_path in configs
|
||||
for unexpanded_path in (config_path.replace(home_directory, '~'),)
|
||||
),
|
||||
classes='panel',
|
||||
)
|
||||
self.border_title = '📄 configuration files'
|
||||
@@ -1,211 +0,0 @@
|
||||
import os
|
||||
|
||||
import textual.widgets
|
||||
|
||||
import borgmatic.actions.browse.bindings
|
||||
import borgmatic.actions.browse.icons
|
||||
import borgmatic.actions.browse.loading
|
||||
import borgmatic.actions.browse.workers
|
||||
|
||||
|
||||
def get_relative_archive_path_components(archive_path, current_directory_path_components):
|
||||
'''
|
||||
Given an Archive_path instance and a tuple of path components for the currently browsed
|
||||
directory, get the path components as a tuple for the archive path relative to that directory.
|
||||
|
||||
For instance, given an archive path with a path of 'foo/bar/baz/quux.txt' and current
|
||||
directory path components of ('foo', 'bar'), return ('baz', 'quux.txt').
|
||||
|
||||
If the archive path is not actually relative to the current directory, return None.
|
||||
'''
|
||||
archive_path_components = tuple(archive_path.file_path.split(os.path.sep))
|
||||
|
||||
if not current_directory_path_components:
|
||||
return archive_path_components
|
||||
|
||||
# If the loaded path doesn't match this directory list's own path, then we don't care about
|
||||
# it for purposes of displaying this particular directory.
|
||||
if (
|
||||
tuple(archive_path_components[: len(current_directory_path_components)])
|
||||
!= current_directory_path_components
|
||||
):
|
||||
return None
|
||||
|
||||
# Strip off the portion of the archive path that matches the directory list's own path.
|
||||
return archive_path_components[len(current_directory_path_components) :]
|
||||
|
||||
|
||||
def make_directory_list_option(archive_path, relative_path_components):
|
||||
'''
|
||||
Given an Archive_path instance and a tuple of relative path components for it, make a
|
||||
textual.widgets.option_list.Option for the path. Use an the icon based on whether this looks
|
||||
like a terminal filename or a directory.
|
||||
'''
|
||||
pieces = (
|
||||
borgmatic.actions.browse.icons.PATH_TYPE_ICONS.get(
|
||||
archive_path.path_type if len(relative_path_components) == 1 else 'd', '❓'
|
||||
),
|
||||
relative_path_components[0],
|
||||
) + (('→', archive_path.link_target) if archive_path.link_target else ())
|
||||
|
||||
return textual.widgets.option_list.Option(
|
||||
prompt=' '.join(pieces), id=relative_path_components[0]
|
||||
)
|
||||
|
||||
|
||||
def add_archive_paths(
|
||||
directory_list,
|
||||
config,
|
||||
repository,
|
||||
archive_name,
|
||||
archive_paths,
|
||||
):
|
||||
'''
|
||||
Given a DirectoryList instance, a configuration dict, a repository dict, an archive name, and a
|
||||
sequence of ArchivePath instances, add the paths to the directory list as options, sorting and
|
||||
deduplicating the resulting directory list's options.
|
||||
|
||||
After all of this reshuffling, make sure the original highlighted option remains highlighted.
|
||||
'''
|
||||
highlighted_option = directory_list.highlighted_option
|
||||
original_options_count = len(directory_list.options)
|
||||
|
||||
sorted_options = sorted(
|
||||
(
|
||||
*directory_list.options,
|
||||
*(
|
||||
make_directory_list_option(archive_path, relative_path_components)
|
||||
for archive_path in archive_paths
|
||||
for relative_path_components in (
|
||||
get_relative_archive_path_components(
|
||||
archive_path,
|
||||
directory_list.path_components,
|
||||
),
|
||||
)
|
||||
if relative_path_components
|
||||
if relative_path_components[0] not in directory_list._id_to_option
|
||||
),
|
||||
),
|
||||
# The loading indicator "option" always goes to the bottom.
|
||||
key=lambda option: ((option.id == 'loading-indicator'), option.prompt),
|
||||
)
|
||||
|
||||
# If there aren't actually any options to add (due to deduplication), bail.
|
||||
if len(sorted_options) == original_options_count:
|
||||
return
|
||||
|
||||
# Retain the highlighted option position even as other options load around it.
|
||||
directory_list.set_options(sorted_options)
|
||||
directory_list.highlighted = (
|
||||
directory_list.get_option_index(highlighted_option.id)
|
||||
if highlighted_option and directory_list.highlighted_option_changed
|
||||
else 0
|
||||
)
|
||||
|
||||
|
||||
class Directory_list(textual.widgets.OptionList):
|
||||
'''
|
||||
A widget for selecting a path from among the contents of a particular directory in a Borg
|
||||
archive. The item selection event is handled in a Carousel instance, the parent widget of a
|
||||
Directory_list.
|
||||
'''
|
||||
|
||||
BINDINGS = borgmatic.actions.browse.bindings.OPTION_LIST_BINDINGS
|
||||
|
||||
def __init__(self, config, repository, archive_name, path_loaded=None, path_components=None):
|
||||
'''
|
||||
Given a configuration dict, a repository dict, an archive name, an optional
|
||||
Archive_path_loaded instance for signalling new paths as they load, and an optional tuple of
|
||||
path components indicating this directory's position in the backed up filesystem, prepare to
|
||||
load paths from the archive for eventual display in this widget. Actual loading kicks off in
|
||||
on_mount() below.
|
||||
'''
|
||||
self.config = config
|
||||
self.repository = repository
|
||||
self.archive_name = archive_name
|
||||
self.path_components = path_components or ()
|
||||
self.highlighted_option_changed = False
|
||||
|
||||
super().__init__(classes='panel')
|
||||
|
||||
self.border_title = ' '.join(
|
||||
(
|
||||
'📁',
|
||||
os.path.sep.join(self.path_components)
|
||||
if self.path_components
|
||||
else f'{archive_name}',
|
||||
)
|
||||
)
|
||||
|
||||
if self.path_components:
|
||||
self.add_option(
|
||||
textual.widgets.option_list.Option(
|
||||
'📁 ..',
|
||||
id='..',
|
||||
),
|
||||
)
|
||||
|
||||
self.path_loaded = path_loaded or borgmatic.actions.browse.workers.Archive_path_loaded(
|
||||
self, 'archive path loaded'
|
||||
)
|
||||
|
||||
if not self.path_loaded.complete:
|
||||
self.timer = borgmatic.actions.browse.loading.add_inline_loading_indicator(self)
|
||||
|
||||
def on_mount(self):
|
||||
'''
|
||||
When this widget gets mounted in the DOM, subscribe to path loaded events so that we can
|
||||
find out about relevant archive paths as they load. And if this is a root directory list,
|
||||
start loading paths from the archive. If this is a non-root directory list, add any already
|
||||
loaded archive paths to this widget as options.
|
||||
|
||||
Loading is started *after* subscribing to path loaded signals so that there's not a gap
|
||||
where we might miss out on any paths.
|
||||
'''
|
||||
self.path_loaded.subscribe(self, self.on_archive_path_loaded)
|
||||
|
||||
if self.path_components:
|
||||
add_archive_paths(
|
||||
directory_list=self,
|
||||
config=self.config,
|
||||
repository=self.repository,
|
||||
archive_name=self.archive_name,
|
||||
archive_paths=borgmatic.actions.browse.workers.get_paths(
|
||||
self.path_loaded.path_hierarchy, self.path_components
|
||||
),
|
||||
)
|
||||
else:
|
||||
borgmatic.actions.browse.workers.load_archive_paths(
|
||||
self.app,
|
||||
path_loaded=self.path_loaded,
|
||||
config=self.config,
|
||||
repository=self.repository,
|
||||
archive_name=self.archive_name,
|
||||
)
|
||||
|
||||
def on_archive_path_loaded(self, data):
|
||||
'''
|
||||
When an archive path loads, add it as an option to this directory list. But if we get a
|
||||
signal that all path loading is complete, stop and remove our loading indicator.
|
||||
'''
|
||||
if data is borgmatic.actions.browse.workers.LOADING_DONE:
|
||||
self.timer.stop()
|
||||
self.remove_option('loading-indicator')
|
||||
return
|
||||
|
||||
add_archive_paths(
|
||||
directory_list=self,
|
||||
config=self.config,
|
||||
repository=self.repository,
|
||||
archive_name=self.archive_name,
|
||||
archive_paths=(data,),
|
||||
)
|
||||
|
||||
def on_option_list_option_highlighted(self, event):
|
||||
'''
|
||||
When the highlighted option changes, record that fact. This flag is consumed in
|
||||
add_archive_paths() in order to retain the highlighted option even as other options load
|
||||
around it.
|
||||
'''
|
||||
if self.highlighted not in {None, 0}:
|
||||
self.highlighted_option_changed = True
|
||||
@@ -1,87 +0,0 @@
|
||||
import logging
|
||||
|
||||
import rich.syntax
|
||||
import textual.binding
|
||||
import textual.widgets
|
||||
|
||||
import borgmatic.actions.browse.loading
|
||||
import borgmatic.actions.browse.workers
|
||||
|
||||
logger = logging.getLogger('__name__')
|
||||
|
||||
|
||||
class File_preview(textual.widgets.RichLog):
|
||||
'''
|
||||
A widget for extracting and previewing the contents of a file stored in a Borg archive.
|
||||
'''
|
||||
|
||||
BINDINGS = (
|
||||
*textual.widgets.RichLog.BINDINGS,
|
||||
textual.binding.Binding(
|
||||
key='up,k', action='scroll_up', description='scroll up', show=True, priority=True
|
||||
),
|
||||
textual.binding.Binding(
|
||||
key='down,j', action='scroll_down', description='scroll down', show=True, priority=True
|
||||
),
|
||||
textual.binding.Binding(
|
||||
key='pageup', action='page_up', description='page up', show=True, priority=True
|
||||
),
|
||||
textual.binding.Binding(
|
||||
key='pagedown', action='page_down', description='page down', show=True, priority=True
|
||||
),
|
||||
)
|
||||
|
||||
def __init__(self, config, repository, archive_name, file_path):
|
||||
'''
|
||||
Given a configuration dict, a repository dict, an archive name, and the path of a file in
|
||||
the archive, prepare to load the file's contents for eventual display in this widget. Actual
|
||||
loading kicks off in on_mount() below.
|
||||
'''
|
||||
self.config = config
|
||||
self.repository = repository
|
||||
self.archive_name = archive_name
|
||||
self.file_path = file_path
|
||||
|
||||
super().__init__(classes='panel')
|
||||
self.border_title = f'📄 {self.file_path} preview'
|
||||
self.auto_scroll = False
|
||||
self.file_preview_loaded = borgmatic.actions.browse.workers.File_preview_loaded(
|
||||
self, 'file preview loaded'
|
||||
)
|
||||
|
||||
self.loading_timer = borgmatic.actions.browse.loading.add_inline_loading_indicator(self)
|
||||
|
||||
def on_mount(self):
|
||||
'''
|
||||
When this widget gets mounted in the DOM, subscribe to archive loaded events so that we can
|
||||
find out about archives as they load. Also start loading file contents from the archive.
|
||||
|
||||
Loading is started *after* subscribing to the file preview loaded signal so that there's not
|
||||
a gap where we might miss out on signal publishes.
|
||||
'''
|
||||
self.file_preview_loaded.subscribe(self, self.on_file_preview_loaded)
|
||||
|
||||
borgmatic.actions.browse.workers.load_file_preview(
|
||||
self.app,
|
||||
file_preview_loaded=self.file_preview_loaded,
|
||||
config=self.config,
|
||||
repository=self.repository,
|
||||
archive_name=self.archive_name,
|
||||
file_path=self.file_path,
|
||||
)
|
||||
|
||||
def on_file_preview_loaded(self, file_contents):
|
||||
'''
|
||||
When a file loads, write its contents (syntax highlighted) to this file preview widget.
|
||||
'''
|
||||
self.loading_timer.stop()
|
||||
self.clear()
|
||||
|
||||
if file_contents is None:
|
||||
self.write('Cannot display a preview for this file')
|
||||
else:
|
||||
# Only pass the file path and not its contents to guess_lexer(). Passing the contents is
|
||||
# more accurate, but also much slower.
|
||||
self.write(
|
||||
rich.syntax.Syntax(file_contents, rich.syntax.Syntax.guess_lexer(self.file_path))
|
||||
)
|
||||
@@ -1,8 +0,0 @@
|
||||
import borgmatic.actions.browse.archive
|
||||
|
||||
PATH_TYPE_ICONS = {
|
||||
borgmatic.actions.browse.archive.Path_type.DIRECTORY.value: '📁',
|
||||
borgmatic.actions.browse.archive.Path_type.LINK.value: '🔗',
|
||||
borgmatic.actions.browse.archive.Path_type.PIPE.value: '🚰',
|
||||
borgmatic.actions.browse.archive.Path_type.FILE.value: '📄',
|
||||
}
|
||||
@@ -1,54 +0,0 @@
|
||||
import contextlib
|
||||
import functools
|
||||
import logging
|
||||
|
||||
import textual.widgets
|
||||
import textual.widgets.option_list
|
||||
|
||||
LOADING_DOT_INTERVAL_SECONDS = 0.3
|
||||
|
||||
|
||||
logger = logging.getLogger('__name__')
|
||||
|
||||
|
||||
def update_inline_loading_indicator(widget):
|
||||
'''
|
||||
Given a textual.widgets.OptionList or a textual.widgets.RichLog instance, animate the existing
|
||||
loading indicator inside it.
|
||||
'''
|
||||
if isinstance(widget, textual.widgets.OptionList):
|
||||
with contextlib.suppress(textual.widgets.option_list.OptionDoesNotExist):
|
||||
widget.replace_option_prompt(
|
||||
'loading-indicator',
|
||||
(str(widget.get_option('loading-indicator').prompt) + '.').replace('....', ''),
|
||||
)
|
||||
elif isinstance(widget, textual.widgets.RichLog):
|
||||
with contextlib.suppress(IndexError):
|
||||
loading_message = str(widget.lines[0].text)
|
||||
widget.clear()
|
||||
widget.write((loading_message + '.').replace('....', ''))
|
||||
else:
|
||||
raise ValueError(f'Unsupported widget type: {type(widget)}')
|
||||
|
||||
|
||||
LOADING_MESSAGE = '⏳ loading...'
|
||||
|
||||
|
||||
def add_inline_loading_indicator(widget):
|
||||
'''
|
||||
Given a textual.widgets.OptionList or a textual.widgets.RichLog instance, add a loading
|
||||
indicator to it.
|
||||
'''
|
||||
if isinstance(widget, textual.widgets.OptionList):
|
||||
loading_option = textual.widgets.option_list.Option(LOADING_MESSAGE, id='loading-indicator')
|
||||
widget.add_option(loading_option)
|
||||
widget.highlighted = None
|
||||
elif isinstance(widget, textual.widgets.RichLog):
|
||||
widget.write(LOADING_MESSAGE)
|
||||
else:
|
||||
raise ValueError(f'Unsupported widget type: {type(widget)}')
|
||||
|
||||
return widget.set_interval(
|
||||
LOADING_DOT_INTERVAL_SECONDS,
|
||||
functools.partial(update_inline_loading_indicator, widget),
|
||||
)
|
||||
@@ -1,102 +0,0 @@
|
||||
import contextlib
|
||||
import logging
|
||||
|
||||
import textual._context
|
||||
import textual.widgets
|
||||
import textual.worker
|
||||
|
||||
import borgmatic.logger
|
||||
|
||||
|
||||
class Rich_color_formatter(logging.Formatter):
|
||||
'''
|
||||
A Python logging formatter that formats log records with Rich-compatible color markup according
|
||||
to their levels.
|
||||
'''
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.prefix = None
|
||||
super().__init__(
|
||||
'{prefix}{message}',
|
||||
*args,
|
||||
style='{',
|
||||
**kwargs,
|
||||
)
|
||||
|
||||
def format(self, record):
|
||||
'''
|
||||
Given a log record, format it with Rich-compatibe color markup corresponding to its log
|
||||
level.
|
||||
'''
|
||||
borgmatic.logger.add_custom_log_levels()
|
||||
|
||||
color = {
|
||||
logging.CRITICAL: 'bright_red',
|
||||
logging.ERROR: 'bright_red',
|
||||
logging.WARNING: 'bright_yellow',
|
||||
logging.ANSWER: 'bright_magenta',
|
||||
logging.INFO: 'bright_green',
|
||||
logging.DEBUG: 'bright_cyan',
|
||||
}.get(record.levelno)
|
||||
record.prefix = f'{self.prefix}: ' if self.prefix else ''
|
||||
|
||||
return f'[{color}]{super().format(record)}[/{color}]'
|
||||
|
||||
|
||||
class Browse_log_handler(logging.Handler):
|
||||
'''
|
||||
A Python log handler that writes any log records to a logging widget.
|
||||
'''
|
||||
|
||||
def __init__(self, logs_widget):
|
||||
'''
|
||||
Given a logs widget, save it for use below.
|
||||
'''
|
||||
self.logs_widget = logs_widget
|
||||
|
||||
super().__init__()
|
||||
|
||||
def emit(self, record):
|
||||
'''
|
||||
Given a log record, format it and log it to the logs widgets. This works whether or not the
|
||||
logging is happening in the main thread.
|
||||
'''
|
||||
message = self.format(record)
|
||||
|
||||
try:
|
||||
textual.worker.get_current_worker()
|
||||
self.logs_widget.app.call_from_thread(self.logs_widget.write, message)
|
||||
except (RuntimeError, textual.worker.NoActiveWorker):
|
||||
with contextlib.suppress(textual._context.NoActiveAppError):
|
||||
self.logs_widget.write(message)
|
||||
|
||||
|
||||
def log_to_widget(logs_widget):
|
||||
'''
|
||||
Given a Textual RichLog logs widget, add a log handler and formatter that logs to it. Also
|
||||
remove the default borgmatic console log handler so it doesn't try to log all over our UI.
|
||||
'''
|
||||
handler = Browse_log_handler(logs_widget)
|
||||
handler.setFormatter(Rich_color_formatter())
|
||||
logger = logging.getLogger()
|
||||
logger.setLevel(min(handler.level for handler in logger.handlers))
|
||||
logger.addHandler(handler)
|
||||
|
||||
with contextlib.suppress(StopIteration):
|
||||
console_handler = next(
|
||||
handler
|
||||
for handler in logging.getLogger().handlers
|
||||
if isinstance(handler, borgmatic.logger.Multi_stream_handler)
|
||||
)
|
||||
logger.removeHandler(console_handler)
|
||||
|
||||
|
||||
class Logs(textual.widgets.RichLog):
|
||||
'''
|
||||
A widget for viewing borgmatic logs in realtime. The log level is determined by borgmatic's
|
||||
current verbosity level.
|
||||
'''
|
||||
|
||||
def __init__(self):
|
||||
super().__init__(markup=True, id='logs', classes='panel')
|
||||
self.border_title = '🪵 logs'
|
||||
@@ -1,30 +0,0 @@
|
||||
import textual.widgets
|
||||
|
||||
import borgmatic.actions.browse.bindings
|
||||
|
||||
|
||||
class Repositories_list(textual.widgets.OptionList):
|
||||
'''
|
||||
A widget for selecting a single Borg repository from among the repositories in a borgmatic
|
||||
configuration file. The item selection event is handled in a Carousel instance, the parent
|
||||
widget of a Repositories_list.
|
||||
'''
|
||||
|
||||
BINDINGS = borgmatic.actions.browse.bindings.OPTION_LIST_BINDINGS
|
||||
|
||||
def __init__(self, config):
|
||||
'''
|
||||
Given a configuration dict, populate the repositories in this widget.
|
||||
'''
|
||||
self.config = config
|
||||
self.repositories = config['repositories']
|
||||
|
||||
super().__init__(
|
||||
*(
|
||||
textual.widgets.option_list.Option(label, id=index)
|
||||
for index, repository in enumerate(self.repositories)
|
||||
for label in (repository.get('label', repository.get('path')),)
|
||||
),
|
||||
classes='panel',
|
||||
)
|
||||
self.border_title = '📦 repositories'
|
||||
@@ -1,29 +0,0 @@
|
||||
import logging
|
||||
|
||||
|
||||
def run_browse(
|
||||
diff_arguments,
|
||||
global_arguments,
|
||||
configs,
|
||||
):
|
||||
'''
|
||||
Run the "browse" action for the given borgmatic configurations. This launches a console UI.
|
||||
|
||||
Raise ValueError if the Textual library (a prerequisite for this action) can't be imported.
|
||||
'''
|
||||
if not configs:
|
||||
return
|
||||
|
||||
logging.getLogger('asyncio').setLevel(logging.WARNING)
|
||||
|
||||
try:
|
||||
import textual # noqa: F401, PLC0415
|
||||
except ImportError: # pragma: no cover
|
||||
raise ValueError(
|
||||
'Unable to import the Textual library for the browse action; try installing "borgmatic[browse]"'
|
||||
)
|
||||
|
||||
import borgmatic.actions.browse.app # noqa: PLC0415
|
||||
|
||||
app = borgmatic.actions.browse.app.Browse_app(configs)
|
||||
app.run()
|
||||
@@ -1,192 +0,0 @@
|
||||
import logging
|
||||
import os
|
||||
|
||||
import textual
|
||||
import textual.signal
|
||||
|
||||
import borgmatic.actions.browse.archive
|
||||
|
||||
logger = logging.getLogger('__name__')
|
||||
|
||||
|
||||
LOADING_DONE = object()
|
||||
|
||||
|
||||
class Archive_loaded(textual.signal.Signal):
|
||||
'''
|
||||
A signal that publishes when each subsequent archive is loaded from a repository, intended for
|
||||
consumption in widgets that display archives as they are loaded. This signal also publishes
|
||||
when loading is complete.
|
||||
|
||||
Each subscribed callback call includes the archive as an archive name string. Given the lack of
|
||||
other identifying information (configuration file, repository), there should be a separate
|
||||
Archive_loaded instance per repository.
|
||||
'''
|
||||
|
||||
|
||||
@textual.work(thread=True)
|
||||
def add_repository_archives(browse_app, archive_loaded, config, repository):
|
||||
'''
|
||||
Given a running Browse_app instance, an Archive_loaded instance, a configuration dict, and a
|
||||
repository dict, load a list of the archives from the repository and add them as options in the
|
||||
archives list. Reverse the order so the most recent archive is first.
|
||||
|
||||
This function runs in a separate thread from the main UI. When loading is complete, publish a
|
||||
loading done signal.
|
||||
'''
|
||||
archives_data = borgmatic.actions.browse.archive.get_repository_archives(config, repository)
|
||||
|
||||
# Reverse the archives, so the common case of accessing the latest archive is easy because it's
|
||||
# at the top.
|
||||
for archive in reversed(archives_data['archives']):
|
||||
archive_loaded.publish(archive['archive'])
|
||||
|
||||
archive_loaded.publish(LOADING_DONE)
|
||||
|
||||
|
||||
def record_path(archive_path, hierarchy, path_components):
|
||||
'''
|
||||
Given an Archive_path instance, a dict capturing a filesystem hierarchy of paths, and a tuple of
|
||||
path components for the archive path, set the archive path into the hierarchy data structure.
|
||||
|
||||
For instance, if given an archive path and path components representing "foo/bar/baz.txt",
|
||||
produce a hierarchy that looks like:
|
||||
|
||||
{'foo': {'bar': {'baz.txt': Archive_path('-', 'foo/bar/baz.txt', '')}}}
|
||||
|
||||
Note that the hierarchy is modified in place, so any existing paths there are retained.
|
||||
'''
|
||||
if len(path_components) == 1:
|
||||
hierarchy[path_components[0]] = {} if archive_path.path_type == 'd' else archive_path
|
||||
return
|
||||
|
||||
record_path(archive_path, hierarchy.setdefault(path_components[0], {}), path_components[1:])
|
||||
|
||||
|
||||
def get_paths(hierarchy, path_components, full_path_components=None):
|
||||
'''
|
||||
Given a dict capturing a filesystem hierarchy of paths (or a subset thereof), a tuple of path
|
||||
components for a directory path relative to the hierarchy root, and an optional tuple of
|
||||
*absolute* path components for the same path (if different), return a generator of the
|
||||
contained file and directory Archive_path instances from the hierarchy.
|
||||
|
||||
For instance, given the following hierarchy:
|
||||
|
||||
{'foo': {'bar': {'baz.txt': Archive_path('-', 'foo/bar/baz.txt', ''), 'quux': {}}}}
|
||||
|
||||
... and path components of ('foo', 'bar'), return a generator with the following:
|
||||
|
||||
* Archive_path('-', 'foo/bar/baz.txt', '')
|
||||
* Archive_path('d', 'foo/bar/quux', '')
|
||||
|
||||
The given absolute path components are use to construct directory paths like that last archive
|
||||
path.
|
||||
'''
|
||||
if full_path_components is None:
|
||||
full_path_components = path_components
|
||||
|
||||
if len(path_components) == 1:
|
||||
try:
|
||||
return (
|
||||
archive_path
|
||||
if isinstance(archive_path, borgmatic.actions.browse.archive.Archive_path)
|
||||
else borgmatic.actions.browse.archive.Archive_path(
|
||||
'd', os.path.join(*full_path_components, component), ''
|
||||
)
|
||||
for component, archive_path in hierarchy[path_components[0]].items()
|
||||
)
|
||||
except KeyError:
|
||||
raise ValueError(f'Unknown file or directory: {path_components[0]}')
|
||||
|
||||
try:
|
||||
return get_paths(hierarchy[path_components[0]], path_components[1:], full_path_components)
|
||||
except KeyError:
|
||||
raise ValueError(f'Unknown directory: {path_components[0]}')
|
||||
|
||||
|
||||
class Archive_path_loaded(textual.signal.Signal):
|
||||
'''
|
||||
A signal that publishes when each subsequent path is loaded from an archive, intended for
|
||||
consumption in widgets that display paths as they are loaded. This signal also tracks the
|
||||
complete filesystem hierarchy seen thus far, so new widgets that get created after loading has
|
||||
started can "catch up" with existing known paths. Lastly, this signal publishes and tracks when
|
||||
loading is complete.
|
||||
|
||||
Each subscrided callback call includes the loaded path as an Archive_path instance. There is
|
||||
intended to be a separate Archive_path_loaded instance per archive, but that instance should be
|
||||
shared among several different widgets for the same archive for performance reasons.
|
||||
'''
|
||||
|
||||
def __init__(self, owner, name):
|
||||
self.path_hierarchy = {}
|
||||
self.complete = False
|
||||
|
||||
super().__init__(owner, name)
|
||||
|
||||
def publish(self, archive_path):
|
||||
'''
|
||||
Publish the given archive path to subscribers and record its path locally. But if the
|
||||
archive path is actually LOADING_DONE, then record loading as complete.
|
||||
'''
|
||||
super().publish(archive_path)
|
||||
|
||||
if archive_path is LOADING_DONE:
|
||||
self.complete = True
|
||||
else:
|
||||
record_path(
|
||||
archive_path, self.path_hierarchy, archive_path.file_path.split(os.path.sep)
|
||||
)
|
||||
|
||||
|
||||
@textual.work(thread=True)
|
||||
def load_archive_paths(browse_app, path_loaded, config, repository, archive_name):
|
||||
'''
|
||||
Given a running Browse_app instance, an Archive_path_loaded instance, a configuration dict, a
|
||||
repository dict, and an archive name, load the paths in this archive and publish each one via
|
||||
the Archive_path_loaded signal, so interested widgets can subscribe. Also send a "loading done"
|
||||
signal when loading completes.
|
||||
|
||||
This function runs in a separate thread from the main UI. When loading is complete, publish a
|
||||
loading done signal.
|
||||
'''
|
||||
for archive_path in borgmatic.actions.browse.archive.get_archive_paths(
|
||||
config, repository, archive_name
|
||||
):
|
||||
path_loaded.publish(archive_path)
|
||||
|
||||
path_loaded.publish(LOADING_DONE)
|
||||
|
||||
|
||||
class File_preview_loaded(textual.signal.Signal):
|
||||
'''
|
||||
A signal that publishes when file contents are loaded from an archive, intended for consumption
|
||||
in widgets that display loaded files. This signal also publishes when loading is complete.
|
||||
|
||||
Each published callback includes a the file's contents as a string. Given the lack of other
|
||||
identifying information (configuration file, repository, archive), there should be a separate
|
||||
Archive_loaded instance per previewed file.
|
||||
'''
|
||||
|
||||
|
||||
@textual.work(thread=True)
|
||||
def load_file_preview(
|
||||
browse_app,
|
||||
file_preview_loaded,
|
||||
config,
|
||||
repository,
|
||||
archive_name,
|
||||
file_path,
|
||||
):
|
||||
'''
|
||||
Given a running Browse_app instance, a File_preview_loaded instance, a configuration dict, a
|
||||
repository dict, an archive name, and the path of a file in that archive, load the contents of
|
||||
the file and write it into the given file preview widget.
|
||||
|
||||
This function runs in a separate thread from the main UI. When loading is complete, publish a
|
||||
loading done signal.
|
||||
'''
|
||||
file_contents = borgmatic.actions.browse.archive.get_archive_file_content(
|
||||
config, repository, archive_name, file_path
|
||||
)
|
||||
|
||||
file_preview_loaded.publish(file_contents)
|
||||
@@ -788,7 +788,7 @@ def run_check(
|
||||
'''
|
||||
logger.info('Running consistency checks')
|
||||
|
||||
repository_id = borgmatic.borg.check.get_repository_id(
|
||||
repository_id = borgmatic.borg.repo_info.get_repository_id(
|
||||
repository['path'],
|
||||
config,
|
||||
local_borg_version,
|
||||
@@ -844,7 +844,9 @@ def run_check(
|
||||
|
||||
if 'spot' in checks:
|
||||
logger.info('Running spot check')
|
||||
with borgmatic.config.paths.Runtime_directory(config) as borgmatic_runtime_directory:
|
||||
with borgmatic.config.paths.Runtime_directory(
|
||||
config, repository_id
|
||||
) as borgmatic_runtime_directory:
|
||||
spot_check(
|
||||
repository,
|
||||
config,
|
||||
|
||||
@@ -3,6 +3,7 @@ import logging
|
||||
import os
|
||||
|
||||
import borgmatic.borg.extract
|
||||
import borgmatic.borg.repo_info
|
||||
import borgmatic.borg.repo_list
|
||||
import borgmatic.config.paths
|
||||
|
||||
@@ -109,8 +110,18 @@ def run_bootstrap(bootstrap_arguments, global_arguments, local_borg_version):
|
||||
local_path=bootstrap_arguments.local_path,
|
||||
remote_path=bootstrap_arguments.remote_path,
|
||||
)
|
||||
repository_id = borgmatic.borg.repo_info.get_repository_id(
|
||||
bootstrap_arguments.repository,
|
||||
config,
|
||||
local_borg_version,
|
||||
global_arguments,
|
||||
local_path=bootstrap_arguments.local_path,
|
||||
remote_path=bootstrap_arguments.remote_path,
|
||||
)
|
||||
|
||||
with borgmatic.config.paths.Runtime_directory(config) as borgmatic_runtime_directory:
|
||||
with borgmatic.config.paths.Runtime_directory(
|
||||
config, repository_id
|
||||
) as borgmatic_runtime_directory:
|
||||
manifest_config_paths = load_config_paths_from_archive(
|
||||
bootstrap_arguments.repository,
|
||||
archive_name,
|
||||
|
||||
@@ -42,8 +42,18 @@ def run_create(
|
||||
|
||||
logger.info(f'Creating archive{dry_run_label}')
|
||||
working_directory = borgmatic.config.paths.get_working_directory(config)
|
||||
repository_id = borgmatic.borg.repo_info.get_repository_id(
|
||||
repository['path'],
|
||||
config,
|
||||
local_borg_version,
|
||||
global_arguments,
|
||||
local_path=local_path,
|
||||
remote_path=remote_path,
|
||||
)
|
||||
|
||||
with borgmatic.config.paths.Runtime_directory(config) as borgmatic_runtime_directory:
|
||||
with borgmatic.config.paths.Runtime_directory(
|
||||
config, repository_id
|
||||
) as borgmatic_runtime_directory:
|
||||
patterns = pattern.process_patterns(
|
||||
pattern.collect_patterns(config, working_directory),
|
||||
config,
|
||||
|
||||
@@ -536,8 +536,18 @@ def run_restore(
|
||||
'''
|
||||
logger.info(f'Restoring data sources from archive {restore_arguments.archive}')
|
||||
working_directory = borgmatic.config.paths.get_working_directory(config)
|
||||
repository_id = borgmatic.borg.repo_info.get_repository_id(
|
||||
repository['path'],
|
||||
config,
|
||||
local_borg_version,
|
||||
global_arguments,
|
||||
local_path=local_path,
|
||||
remote_path=remote_path,
|
||||
)
|
||||
|
||||
with borgmatic.config.paths.Runtime_directory(config) as borgmatic_runtime_directory:
|
||||
with borgmatic.config.paths.Runtime_directory(
|
||||
config, repository_id
|
||||
) as borgmatic_runtime_directory:
|
||||
patterns = borgmatic.actions.pattern.process_patterns(
|
||||
borgmatic.actions.pattern.collect_patterns(config, working_directory),
|
||||
config,
|
||||
|
||||
+1
-33
@@ -1,10 +1,8 @@
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import shlex
|
||||
|
||||
import borgmatic.config.paths
|
||||
from borgmatic.borg import environment, feature, flags, repo_info
|
||||
from borgmatic.borg import environment, feature, flags
|
||||
from borgmatic.execute import DO_NOT_CAPTURE, execute_command
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -82,36 +80,6 @@ def make_check_name_flags(checks, archive_filter_flags):
|
||||
)
|
||||
|
||||
|
||||
def get_repository_id(
|
||||
repository_path,
|
||||
config,
|
||||
local_borg_version,
|
||||
global_arguments,
|
||||
local_path,
|
||||
remote_path,
|
||||
):
|
||||
'''
|
||||
Given a local or remote repository path, a configuration dict, the local Borg version, global
|
||||
arguments, and local/remote commands to run, return the corresponding Borg repository ID.
|
||||
|
||||
Raise ValueError if the Borg repository ID cannot be determined.
|
||||
'''
|
||||
try:
|
||||
return json.loads(
|
||||
repo_info.display_repository_info(
|
||||
repository_path,
|
||||
config,
|
||||
local_borg_version,
|
||||
argparse.Namespace(json=True),
|
||||
global_arguments,
|
||||
local_path,
|
||||
remote_path,
|
||||
),
|
||||
)['repository']['id']
|
||||
except (json.JSONDecodeError, KeyError):
|
||||
raise ValueError(f'Cannot determine Borg repository ID for {repository_path}')
|
||||
|
||||
|
||||
def check_archives(
|
||||
repository_path,
|
||||
config,
|
||||
|
||||
@@ -374,9 +374,7 @@ def create_archive(
|
||||
|
||||
if json:
|
||||
output_log_level = None
|
||||
elif config.get('list_details') or (
|
||||
(config.get('statistics') or config.get('quick_statistics')) and not dry_run
|
||||
):
|
||||
elif config.get('list_details') or (config.get('statistics') and not dry_run):
|
||||
output_log_level = logging.ANSWER
|
||||
else:
|
||||
output_log_level = logging.INFO
|
||||
@@ -388,11 +386,6 @@ def create_archive(
|
||||
create_flags += (
|
||||
(('--info',) if logger.getEffectiveLevel() == logging.INFO and not json else ())
|
||||
+ (('--stats',) if config.get('statistics') and not json and not dry_run else ())
|
||||
+ (
|
||||
('--quick-stats',)
|
||||
if config.get('quick_statistics') and not json and not dry_run
|
||||
else ()
|
||||
)
|
||||
+ (('--debug', '--show-rc') if logger.isEnabledFor(logging.DEBUG) and not json else ())
|
||||
+ (('--progress',) if config.get('progress') else ())
|
||||
+ (('--json',) if json else ())
|
||||
|
||||
@@ -115,10 +115,10 @@ def capture_archive_listing(
|
||||
Given a local or remote repository path, an archive name, a configuration dict, the local Borg
|
||||
version, global arguments as an argparse.Namespace, the archive paths (or Borg patterns) in
|
||||
which to list files, the Borg path format indicating keys to include in the output, and local
|
||||
and remote Borg paths, capture the output of listing that archive and return it as a generator
|
||||
of dicts, one per path.
|
||||
and remote Borg paths, capture the output of listing that archive and return it as a sequence of
|
||||
dicts, one per path.
|
||||
'''
|
||||
return (
|
||||
return tuple(
|
||||
json.loads(entry)
|
||||
for entry in execute_command_and_capture_output(
|
||||
make_list_command(
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import argparse
|
||||
import json
|
||||
import logging
|
||||
import shlex
|
||||
|
||||
@@ -81,3 +83,33 @@ def display_repository_info(
|
||||
)
|
||||
|
||||
return None
|
||||
|
||||
|
||||
def get_repository_id(
|
||||
repository_path,
|
||||
config,
|
||||
local_borg_version,
|
||||
global_arguments,
|
||||
local_path,
|
||||
remote_path,
|
||||
):
|
||||
'''
|
||||
Given a local or remote repository path, a configuration dict, the local Borg version, global
|
||||
arguments, and local/remote commands to run, return the corresponding Borg repository ID.
|
||||
|
||||
Raise ValueError if the Borg repository ID cannot be determined.
|
||||
'''
|
||||
try:
|
||||
return json.loads(
|
||||
display_repository_info(
|
||||
repository_path,
|
||||
config,
|
||||
local_borg_version,
|
||||
argparse.Namespace(json=True),
|
||||
global_arguments,
|
||||
local_path,
|
||||
remote_path,
|
||||
),
|
||||
)['repository']['id']
|
||||
except (json.JSONDecodeError, KeyError):
|
||||
raise ValueError(f'Cannot determine Borg repository ID for {repository_path}')
|
||||
|
||||
@@ -31,10 +31,9 @@ ACTION_ALIASES = {
|
||||
'transfer': [],
|
||||
'break-lock': [],
|
||||
'key': [],
|
||||
'borg': [],
|
||||
'recreate': [],
|
||||
'diff': [],
|
||||
'browse': [],
|
||||
'borg': [],
|
||||
}
|
||||
|
||||
|
||||
@@ -325,7 +324,7 @@ def make_argument_description(schema, flag_name):
|
||||
' To specify a different list element, replace the "[0]" with another array index ("[1]", "[2]", etc.).',
|
||||
)
|
||||
|
||||
if example and schema_type in ('array', 'object'):
|
||||
if example and schema_type in ('array', 'object'): # noqa: PLR6201
|
||||
example_buffer = io.StringIO()
|
||||
yaml = ruamel.yaml.YAML(typ='safe')
|
||||
yaml.default_flow_style = True
|
||||
@@ -897,13 +896,6 @@ def make_parsers(schema, unparsed_arguments): # noqa: PLR0915
|
||||
action='store_true',
|
||||
help='Display statistics of archive',
|
||||
)
|
||||
create_group.add_argument(
|
||||
'--quick-stats',
|
||||
dest='quick_statistics',
|
||||
default=None,
|
||||
action='store_true',
|
||||
help='Display statistics of archive, skipping repository-wide "All archives" and chunk index statistics [Borg 1.4.5+ only]',
|
||||
)
|
||||
create_group.add_argument(
|
||||
'--list',
|
||||
'--files',
|
||||
@@ -2005,9 +1997,8 @@ def make_parsers(schema, unparsed_arguments): # noqa: PLR0915
|
||||
diff_parser = action_parsers.add_parser(
|
||||
'diff',
|
||||
aliases=ACTION_ALIASES['diff'],
|
||||
help='Find differences (file contents, user/group/mode) between archives',
|
||||
description='Find differences (file contents, user/group/mode) between archives',
|
||||
add_help=False,
|
||||
help='This command finds differences (file contents, user/group/mode) between archives',
|
||||
description='This command finds differences (file contents, user/group/mode) between archives',
|
||||
)
|
||||
diff_group = diff_parser.add_argument_group('diff arguments')
|
||||
diff_group.add_argument(
|
||||
@@ -2044,18 +2035,6 @@ def make_parsers(schema, unparsed_arguments): # noqa: PLR0915
|
||||
action='store_true',
|
||||
help='Run the diff according to borgmatic configured patterns (ie do not diff entire archives)',
|
||||
)
|
||||
diff_group.add_argument('-h', '--help', action='help', help='Show this help message and exit')
|
||||
|
||||
browse_parser = action_parsers.add_parser(
|
||||
'browse',
|
||||
aliases=ACTION_ALIASES['browse'],
|
||||
help='Browse repositories, archives, and files in a console UI',
|
||||
description='Browse repositories, archives, and files in a console UI',
|
||||
add_help=False,
|
||||
)
|
||||
browse_group = browse_parser.add_argument_group('browse arguments')
|
||||
browse_group.add_argument('-h', '--help', action='help', help='Show this help message and exit')
|
||||
|
||||
borg_parser = action_parsers.add_parser(
|
||||
'borg',
|
||||
aliases=ACTION_ALIASES['borg'],
|
||||
@@ -2128,7 +2107,7 @@ def parse_arguments(schema, *unparsed_arguments):
|
||||
)
|
||||
|
||||
if (
|
||||
('list' in arguments and 'repo-info' in arguments and arguments['list'].json)
|
||||
('list' in arguments and 'repo-info' in arguments and arguments['list'].json) # noqa: PLR0916
|
||||
or ('list' in arguments and 'info' in arguments and arguments['list'].json)
|
||||
or ('repo-info' in arguments and 'info' in arguments and arguments['repo-info'].json)
|
||||
):
|
||||
@@ -2146,7 +2125,7 @@ def parse_arguments(schema, *unparsed_arguments):
|
||||
'With the repo-list action, only one of --prefix or --match-archives flags can be used.',
|
||||
)
|
||||
|
||||
if 'info' in arguments and (
|
||||
if 'info' in arguments and ( # noqa: PLR0916
|
||||
(arguments['info'].archive and arguments['info'].prefix)
|
||||
or (arguments['info'].archive and arguments['info'].match_archives)
|
||||
or (arguments['info'].prefix and arguments['info'].match_archives)
|
||||
|
||||
@@ -12,7 +12,6 @@ import ruamel.yaml
|
||||
|
||||
import borgmatic.actions.borg
|
||||
import borgmatic.actions.break_lock
|
||||
import borgmatic.actions.browse.run
|
||||
import borgmatic.actions.change_passphrase
|
||||
import borgmatic.actions.check
|
||||
import borgmatic.actions.compact
|
||||
@@ -212,7 +211,7 @@ def run_configuration(config_filename, config, config_paths, arguments): # noqa
|
||||
f"Skipping {'/'.join(skip_actions)} action{'s' if len(skip_actions) > 1 else ''} due to configured skip_actions",
|
||||
)
|
||||
|
||||
try:
|
||||
try: # noqa: PLR1702
|
||||
with (
|
||||
Monitoring_hooks(config_filename, config, arguments, global_arguments),
|
||||
borgmatic.hooks.command.Before_after_hooks(
|
||||
@@ -826,8 +825,8 @@ def collect_highlander_action_summary_logs(configs, arguments, configuration_par
|
||||
try:
|
||||
if 'bootstrap' in arguments:
|
||||
try:
|
||||
# No configuration file is needed for bootstrap.
|
||||
local_borg_version = borg_version.local_borg_version(
|
||||
# No configuration file is needed for bootstrap.
|
||||
{},
|
||||
arguments['bootstrap'].local_path,
|
||||
)
|
||||
@@ -898,13 +897,6 @@ def collect_highlander_action_summary_logs(configs, arguments, configuration_par
|
||||
|
||||
return
|
||||
|
||||
if 'browse' in arguments:
|
||||
borgmatic.actions.browse.run.run_browse(
|
||||
arguments['browse'],
|
||||
arguments['global'],
|
||||
configs,
|
||||
)
|
||||
|
||||
except (
|
||||
CalledProcessError,
|
||||
ValueError,
|
||||
|
||||
+39
-20
@@ -1,6 +1,7 @@
|
||||
import contextlib
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
from enum import Enum
|
||||
|
||||
@@ -84,6 +85,25 @@ def replace_temporary_subdirectory_with_glob(
|
||||
)
|
||||
|
||||
|
||||
class Fixed_name_temporary_directory:
|
||||
'''
|
||||
A class whose instances can stand-in for tempfile.TemporaryDirectory's, except the temporary
|
||||
filename path is fixed rather than randomly generated.
|
||||
'''
|
||||
|
||||
def __init__(self, path):
|
||||
'''
|
||||
Given a temporary directory path, save it off for later.
|
||||
'''
|
||||
self.name = path
|
||||
|
||||
def cleanup(self):
|
||||
'''
|
||||
Remove the temporary directory path.
|
||||
'''
|
||||
shutil.rmtree(self.name, ignore_errors=True)
|
||||
|
||||
|
||||
class Runtime_directory:
|
||||
'''
|
||||
A Python context manager for creating and cleaning up the borgmatic runtime directory used for
|
||||
@@ -98,16 +118,17 @@ class Runtime_directory:
|
||||
automatically gets cleaned up as necessary.
|
||||
'''
|
||||
|
||||
def __init__(self, config):
|
||||
def __init__(self, config, repository_id):
|
||||
'''
|
||||
Given a configuration dict determine the borgmatic runtime directory, creating a secure,
|
||||
temporary directory within it if necessary. Defaults to $XDG_RUNTIME_DIR/./borgmatic or
|
||||
$RUNTIME_DIRECTORY/./borgmatic or $TMPDIR/borgmatic-[random]/./borgmatic or
|
||||
$TEMP/borgmatic-[random]/./borgmatic or /tmp/borgmatic-[random]/./borgmatic where "[random]"
|
||||
is a randomly generated string intended to avoid path collisions.
|
||||
|
||||
If XDG_RUNTIME_DIR or RUNTIME_DIRECTORY is set and already ends in "/borgmatic", then don't
|
||||
tack on a second "/borgmatic" path component.
|
||||
Given a configuration dict and the Borg ID for a repository, determine the borgmatic runtime
|
||||
directory, creating a secure, temporary directory within it if necessary. Defaults to
|
||||
$XDG_RUNTIME_DIR/borgmatic-[repository_id]/./borgmatic or
|
||||
$RUNTIME_DIRECTORY/borgmatic-[repository_id]/./borgmatic or
|
||||
$TMPDIR/borgmatic-[random]/./borgmatic or $TEMP/borgmatic-[random]/./borgmatic or
|
||||
/tmp/borgmatic-[random]/./borgmatic where "[random]" is a randomly generated string and
|
||||
"[repository_id]" is the Borg repository ID being operated on. Both strings are intended to
|
||||
avoid path collisions, and the random string helps avoid predictable temporary path attacks
|
||||
in shared temporary directories.
|
||||
|
||||
The "/./" is taking advantage of a Borg feature such that the part of the path before the "/./"
|
||||
does not get stored in the file path within an archive. That way, the path of the runtime
|
||||
@@ -125,7 +146,8 @@ class Runtime_directory:
|
||||
if not runtime_directory.startswith(os.path.sep):
|
||||
raise ValueError('The runtime directory must be an absolute path')
|
||||
|
||||
self.temporary_directory = None
|
||||
runtime_directory = os.path.join(runtime_directory, f'borgmatic-{repository_id}')
|
||||
self.temporary_directory = Fixed_name_temporary_directory(runtime_directory)
|
||||
else:
|
||||
base_directory = (
|
||||
os.environ.get('TMPDIR') or os.environ.get('TEMP') or '/tmp' # noqa: S108
|
||||
@@ -141,11 +163,9 @@ class Runtime_directory:
|
||||
)
|
||||
runtime_directory = self.temporary_directory.name
|
||||
|
||||
(base_path, final_directory) = os.path.split(runtime_directory.rstrip(os.path.sep))
|
||||
|
||||
self.runtime_path = expand_user_in_path(
|
||||
os.path.join(
|
||||
base_path if final_directory == 'borgmatic' else runtime_directory,
|
||||
runtime_directory,
|
||||
'.', # Borg 1.4+ "slashdot" hack.
|
||||
'borgmatic',
|
||||
),
|
||||
@@ -162,14 +182,13 @@ class Runtime_directory:
|
||||
|
||||
def __exit__(self, exception_type, exception, traceback):
|
||||
'''
|
||||
Delete any temporary directory that was created as part of initialization.
|
||||
Delete the temporary directory that was created as part of initialization.
|
||||
'''
|
||||
if self.temporary_directory:
|
||||
# The cleanup() call errors if, for instance, there's still a
|
||||
# mounted filesystem within the temporary directory. There's
|
||||
# nothing we can do about that here, so swallow the error.
|
||||
with contextlib.suppress(OSError):
|
||||
self.temporary_directory.cleanup()
|
||||
# The cleanup() call errors if, for instance, there's still a
|
||||
# mounted filesystem within the temporary directory. There's
|
||||
# nothing we can do about that here, so swallow the error.
|
||||
with contextlib.suppress(OSError):
|
||||
self.temporary_directory.cleanup()
|
||||
|
||||
|
||||
def make_runtime_directory_glob(borgmatic_runtime_directory):
|
||||
|
||||
@@ -1091,15 +1091,6 @@ properties:
|
||||
Corresponds to the "--stats" flag on those actions. Defaults to
|
||||
false.
|
||||
example: true
|
||||
quick_statistics:
|
||||
type: boolean
|
||||
description: |
|
||||
Display statistics for an archive when running supported actions,
|
||||
skipping the repository-wide "All archives" and chunk index
|
||||
statistics to save some time. Corresponds to the "--quick-stats"
|
||||
flag on those actions. Defaults to false. (This option is supported
|
||||
for Borg 1.4.5+ only.)
|
||||
example: true
|
||||
list_details:
|
||||
type: boolean
|
||||
description: |
|
||||
@@ -1140,9 +1131,8 @@ properties:
|
||||
- info
|
||||
- break-lock
|
||||
- key
|
||||
- diff
|
||||
- browse
|
||||
- borg
|
||||
- diff
|
||||
description: |
|
||||
List of one or more actions to skip running for this configuration
|
||||
file, even if specified on the command-line (explicitly or
|
||||
@@ -1358,9 +1348,8 @@ properties:
|
||||
- info
|
||||
- break-lock
|
||||
- key
|
||||
- diff
|
||||
- browse
|
||||
- borg
|
||||
- diff
|
||||
description: |
|
||||
List of actions for which the commands will be
|
||||
run. Defaults to running for all actions.
|
||||
@@ -1425,9 +1414,8 @@ properties:
|
||||
- info
|
||||
- break-lock
|
||||
- key
|
||||
- diff
|
||||
- browse
|
||||
- borg
|
||||
- diff
|
||||
description: |
|
||||
Only trigger the hook when borgmatic is run with
|
||||
particular actions listed here. Defaults to
|
||||
@@ -2837,9 +2825,7 @@ properties:
|
||||
properties:
|
||||
url:
|
||||
type: string
|
||||
description: |
|
||||
URL of this Apprise service. Supports the
|
||||
"{credential ...}" syntax.
|
||||
description: URL of this Apprise service.
|
||||
example: "gotify://hostname/token"
|
||||
label:
|
||||
type: string
|
||||
|
||||
+7
-31
@@ -372,21 +372,13 @@ def log_buffer_lines(
|
||||
yield log_record.getMessage()
|
||||
|
||||
|
||||
def raise_for_process_errors(
|
||||
buffer_readers,
|
||||
process_metadatas,
|
||||
output_log_level,
|
||||
borg_local_path,
|
||||
borg_exit_codes,
|
||||
capture_stderr=False,
|
||||
):
|
||||
def raise_for_process_errors(buffer_readers, process_metadatas, borg_local_path, borg_exit_codes):
|
||||
'''
|
||||
Given a dict from buffer object to Buffer_reader, a dict from subprocess.Popen() instance to
|
||||
Process_metadata instance, a requested output log level for stdout, Borg's local path, a
|
||||
sequence of exit code configuration dicts, and whether to capture stderr, check the given
|
||||
processes for error or warning exit codes. If found, vent or kill any running processes and
|
||||
drain any remaining buffer lines. In the case of an error exit code, raise. In the case of
|
||||
warning, return Exit_status.WARNING. Otherwise, return None.
|
||||
Process_metadata instance, Borg's local path, a sequence of exit code configuration dicts, check
|
||||
the given processes for error or warning exit codes. If found, vent or kill any running
|
||||
processes. In the case of an error exit code, raise. In the case of warning, return
|
||||
Exit_status.WARNING. Otherwise, return None.
|
||||
'''
|
||||
result_status = None
|
||||
|
||||
@@ -412,13 +404,6 @@ def raise_for_process_errors(
|
||||
result_status = Exit_status.WARNING
|
||||
continue
|
||||
|
||||
# Drain and log remaining buffer lines, so no output gets lost. But swallow captured output,
|
||||
# since we're raising below instead of yielding captured lines.
|
||||
tuple(
|
||||
log_remaining_buffer_lines(
|
||||
buffer_readers, process_metadatas, output_log_level, borg_local_path, capture_stderr
|
||||
)
|
||||
)
|
||||
last_lines = process_metadatas[process].last_lines
|
||||
|
||||
# If an error occurs, include its output in the raised exception so that we don't
|
||||
@@ -444,9 +429,6 @@ def log_remaining_buffer_lines(
|
||||
whether to capture stderr, drain and log any remaining output lines from the buffers until
|
||||
they're empty. Additionally, for any log records with a log level the same as the output log
|
||||
level, yield those log messages for capture.
|
||||
|
||||
The main difference between this function and log_buffer_lines() is that this one doesn't just
|
||||
do one "turn of the crank" of logging buffer output; it completely drains any remaining output.
|
||||
'''
|
||||
for output_buffer, reader in buffer_readers.items():
|
||||
if not reader.process:
|
||||
@@ -464,7 +446,6 @@ def log_remaining_buffer_lines(
|
||||
borg_local_path=borg_local_path,
|
||||
command=reader.process.args,
|
||||
),
|
||||
last_lines=process_metadatas[reader.process].last_lines,
|
||||
)
|
||||
|
||||
if (
|
||||
@@ -513,7 +494,7 @@ def log_outputs(
|
||||
for buffer in output_buffers_for_process(process, exclude_stdouts)
|
||||
}
|
||||
|
||||
# Log output lines for each process until they all exit or one errors.
|
||||
# Log output lines for each process until they all exit.
|
||||
while True:
|
||||
yield from log_buffer_lines(
|
||||
buffer_readers, process_metadatas, output_log_level, borg_local_path, capture_stderr
|
||||
@@ -521,12 +502,7 @@ def log_outputs(
|
||||
|
||||
if (
|
||||
raise_for_process_errors(
|
||||
buffer_readers,
|
||||
process_metadatas,
|
||||
output_log_level,
|
||||
borg_local_path,
|
||||
borg_exit_codes,
|
||||
capture_stderr,
|
||||
buffer_readers, process_metadatas, borg_local_path, borg_exit_codes
|
||||
)
|
||||
== Exit_status.WARNING
|
||||
):
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import logging
|
||||
import operator
|
||||
|
||||
import borgmatic.hooks.credential.parse
|
||||
import borgmatic.hooks.monitoring.logs
|
||||
import borgmatic.hooks.monitoring.monitor
|
||||
|
||||
@@ -45,9 +44,7 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
|
||||
import apprise # noqa: PLC0415
|
||||
from apprise import NotifyFormat, NotifyType # noqa: PLC0415
|
||||
except ImportError: # pragma: no cover
|
||||
logger.warning(
|
||||
'Unable to import Apprise in its monitoring hook; try installing "borgmatic[Apprise]"'
|
||||
)
|
||||
logger.warning('Unable to import Apprise in monitoring hook')
|
||||
return
|
||||
|
||||
state_to_notify_type = {
|
||||
@@ -79,12 +76,7 @@ def ping_monitor(hook_config, config, config_filename, state, monitoring_log_lev
|
||||
logger.info(f'Pinging Apprise services: {labels_string}{dry_run_string}')
|
||||
|
||||
apprise_object = apprise.Apprise()
|
||||
apprise_object.add(
|
||||
[
|
||||
borgmatic.hooks.credential.parse.resolve_credential(service['url'], config)
|
||||
for service in hook_config.get('services')
|
||||
]
|
||||
)
|
||||
apprise_object.add(list(map(operator.itemgetter('url'), hook_config.get('services'))))
|
||||
|
||||
if dry_run:
|
||||
return
|
||||
|
||||
+1
-1
@@ -169,7 +169,7 @@ class Json_formatter(logging.Formatter):
|
||||
def __init__(self, fmt='{message}', *args, style='{', **kwargs):
|
||||
super().__init__(*args, fmt=fmt, style=style, **kwargs)
|
||||
|
||||
def format(self, record):
|
||||
def format(self, record): # noqa: PLR6301
|
||||
return log_record_to_json(record)
|
||||
|
||||
|
||||
|
||||
+1
-1
@@ -5,7 +5,7 @@ RUN apk add --no-cache py3-pip py3-ruamel.yaml py3-ruamel.yaml.clib
|
||||
RUN pip install --break-system-packages --no-cache /app && borgmatic config generate && borgmatic config generate --destination /etc/borgmatic --split && chmod +r /etc/borgmatic/*.yaml
|
||||
RUN mkdir /command-line \
|
||||
&& borgmatic --help > /command-line/global.txt \
|
||||
&& for action in repo-create transfer create prune compact check delete extract config "config bootstrap" "config generate" "config validate" "config show" export-tar mount umount repo-delete restore repo-list list repo-info info break-lock "key export" "key import" "key change-passphrase" recreate diff browse borg; do \
|
||||
&& for action in repo-create transfer create prune compact check delete extract config "config bootstrap" "config generate" "config validate" "config show" export-tar mount umount repo-delete restore repo-list list repo-info info break-lock "key export" "key import" "key change-passphrase" recreate diff borg; do \
|
||||
borgmatic $action --help > /command-line/${action/ /-}.txt; done
|
||||
RUN /app/docs/fetch-contributors >> /contributors.html
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
Here's the command-line help for this action in the [most recent version of
|
||||
borgmatic](https://projects.torsion.org/borgmatic-collective/borgmatic/releases).
|
||||
If you're using an older version, some of these flags may not work (or the action
|
||||
may be missing entirely). You should instead run the action with `--help` to see
|
||||
the flags and actions specific to your borgmatic version.
|
||||
If you're using an older version, some of these flags may not work, and you
|
||||
should instead run the action with `--help` to see the flags specific to your
|
||||
borgmatic version.
|
||||
|
||||
@@ -31,7 +31,7 @@ changes work:
|
||||
```bash
|
||||
cd borgmatic
|
||||
uv tool update-shell
|
||||
uv tool install --editable .[dev]
|
||||
uv tool install --editable .
|
||||
```
|
||||
|
||||
Or to work on the [Apprise
|
||||
@@ -39,14 +39,7 @@ hook](https://torsion.org/borgmatic/reference/configuration/monitoring/apprise/)
|
||||
change that last line to:
|
||||
|
||||
```bash
|
||||
uv tool install --editable .[dev,Apprise]
|
||||
```
|
||||
|
||||
Or to work on the [browse
|
||||
action](https://torsion.org/borgmatic/reference/command-line/actions/browse/):
|
||||
|
||||
```bash
|
||||
uv tool install --editable .[dev,browse]
|
||||
uv tool install --editable .[Apprise]
|
||||
```
|
||||
|
||||
To get oriented with the borgmatic source code, have a look at the [source
|
||||
|
||||
@@ -135,52 +135,3 @@ is, patterns are _not_ taken into consideration. If you require this, supply the
|
||||
|
||||
See the [Borg](https://borgbackup.readthedocs.io/en/stable/usage/diff.html)
|
||||
documentation for information on output format, what is compared, and more.
|
||||
|
||||
|
||||
## Browsing backups
|
||||
|
||||
<span class="minilink minilink-addedin">New in version 2.1.6</span> <span
|
||||
class="minilink minilink-addedin">Experimental feature</span> borgmatic has an
|
||||
experimental console UI for browsing your repositories, archives, and files.
|
||||
Here's what it looks like:
|
||||
|
||||
<img src="https://torsion.org/borgmatic/static/browse.png" alt="borgmatic browse screenshot" style="width: 100%">
|
||||
|
||||
This feature is not intended to be a general-purpose Borg UI with every
|
||||
borgmatic feature, but rather it's for use cases like quickly looking at the
|
||||
contents of your backups when you're feeling too lazy to type out a full
|
||||
borgmatic command-line.
|
||||
|
||||
Depending on how you installed borgmatic, it may not have come with the
|
||||
necessary Python libraries to support the browse action. (borgmatic's
|
||||
[stand-alone
|
||||
binary](https://projects.torsion.org/borgmatic-collective/borgmatic/releases)
|
||||
does not currently include them.) If you originally [installed borgmatic with
|
||||
uv](https://torsion.org/borgmatic/how-to/install-borgmatic/), run the following
|
||||
to install the libraries needed for the browse action:
|
||||
|
||||
```bash
|
||||
sudo uv tool install borgmatic[browse]
|
||||
```
|
||||
|
||||
Omit `sudo` if borgmatic is installed as a non-root user.
|
||||
|
||||
Once the libraries are installed, run the following to access the browse action:
|
||||
|
||||
```bash
|
||||
borgmatic browse
|
||||
```
|
||||
|
||||
This launches a console UI where you can select a borgmatic configuration file
|
||||
(if there's more than one), select a Borg repository, select an archive in that
|
||||
repository, and even browse the backed up files in that archive.
|
||||
|
||||
Use the keyboard or the mouse to navigate the UI. The footer at the bottom of
|
||||
the screen shows some of the available keys. Logs show up directly in the UI at
|
||||
the [selected
|
||||
verbosity](https://torsion.org/borgmatic/reference/command-line/logging/),
|
||||
although logs are hidden by default.
|
||||
|
||||
Please [provide
|
||||
feedback](https://torsion.org/borgmatic/#support-and-contributing) if you find
|
||||
this feature useful—or even if you don't, but would like it to become useful.
|
||||
|
||||
@@ -98,7 +98,7 @@ installing borgmatic:
|
||||
|
||||
#### Etc.
|
||||
|
||||
* [stand-alone Linux binary](https://projects.torsion.org/borgmatic-collective/borgmatic/releases) (This is a beta feature! The minimal binary omits [Apprise support](https://torsion.org/borgmatic/reference/configuration/monitoring/apprise/).)
|
||||
* [stand-alone Linux binary](https://projects.torsion.org/borgmatic-collective/borgmatic/releases) (This is a beta feature!)
|
||||
* [Ansible role](https://github.com/borgbase/ansible-role-borgbackup)
|
||||
* [pipx](https://pipx.pypa.io/stable/)
|
||||
|
||||
|
||||
@@ -58,19 +58,25 @@ choice](https://torsion.org/borgmatic/how-to/set-up-backups/#autopilot), each
|
||||
entry using borgmatic's `--config` flag instead of relying on
|
||||
`/etc/borgmatic.d`.
|
||||
|
||||
<a id="limitations"></a>
|
||||
|
||||
## Limitations
|
||||
## Parallelism
|
||||
|
||||
borgmatic does not currently support its own parallelism—being run multiple
|
||||
times on the same machine simultaneously. In particular, many of the [data
|
||||
source
|
||||
hooks](https://torsion.org/borgmatic/reference/configuration/data-sources/) rely
|
||||
on global borgmatic runtime files which can't be shared across processes, and
|
||||
therefore multiple borgmatic instances on the same machine would interfere with
|
||||
each other.
|
||||
<span class="minilink minilink-addedin">New in version 2.1.6</span> borgmatic
|
||||
supports multiple borgmatic instances run on the same machine in parallel—as
|
||||
long as they're operating on different Borg repositories.
|
||||
|
||||
A single borgmatic instance also doesn't currently support running multiple Borg
|
||||
instances in parallel on the same machine.
|
||||
However, note that a single borgmatic instance doesn't currently support running
|
||||
multiple Borg instances in parallel on the same machine.
|
||||
|
||||
|
||||
<span class="minilink minilink-addedin">Prior to version 2.1.6</span> borgmatic
|
||||
did not support parallel borgmatic runs on the same machine simultaneously. In
|
||||
particular, many of the [data source
|
||||
hooks](https://torsion.org/borgmatic/reference/configuration/data-sources/)
|
||||
relied on global borgmatic runtime files which couldn't be shared across
|
||||
processes, and therefore multiple borgmatic instances on the same machine
|
||||
interfered with each other.
|
||||
|
||||
|
||||
<a id="archive-naming"></a>
|
||||
|
||||
@@ -1,17 +0,0 @@
|
||||
---
|
||||
title: browse
|
||||
eleventyNavigation:
|
||||
key: browse
|
||||
parent: 🎬 Actions
|
||||
---
|
||||
|
||||
<span class="minilink minilink-addedin">Experimental feature</span> {% include snippet/command-line/sample.md %}
|
||||
|
||||
```
|
||||
{% include borgmatic/command-line/browse.txt %}
|
||||
```
|
||||
|
||||
|
||||
## Related documentation
|
||||
|
||||
* [Inspect your backups](https://torsion.org/borgmatic/how-to/inspect-your-backups/)
|
||||
@@ -24,14 +24,9 @@ databases](https://torsion.org/borgmatic/how-to/backup-your-databases/#all-datab
|
||||
borgmatic excludes most data coming from [MariaDB system
|
||||
databases](https://mariadb.com/docs/server/reference/system-tables),
|
||||
because much of it is populated on MariaDB startup and thus not restorable (or
|
||||
just unnecessary to backup).
|
||||
|
||||
The system data that borgmatic does include in these dumps are: users, roles,
|
||||
grants, user-defined functions, and remote servers—all from the `mysql` system
|
||||
database. This omits all other data from the `mysql` database, which includes
|
||||
index and table statistics, time zones, and installed server plugins. It also
|
||||
excludes the separate `information_schema`, `performance_schema`, and `sys`
|
||||
system databases. This is not currently configurable.
|
||||
just unnecessary to backup). The system data that borgmatic does include in
|
||||
these dumps are: users, roles, grants, user-defined functions, and remote
|
||||
servers.
|
||||
|
||||
Within a Borg archive, you can find this data stored in a dump named `mysql`—the
|
||||
name of the system table this data comes from. And if you'd like to dump this
|
||||
|
||||
@@ -5,9 +5,9 @@ eleventyNavigation:
|
||||
parent: 🚨 Monitoring
|
||||
---
|
||||
<span class="minilink minilink-addedin">New in version 1.8.4</span>
|
||||
[Apprise](https://appriseit.com/) is a local notification library
|
||||
[Apprise](https://github.com/caronc/apprise/wiki) is a local notification library
|
||||
that "allows you to send a notification to almost all of the most popular
|
||||
[notification services](https://appriseit.com/services/) available to
|
||||
[notification services](https://github.com/caronc/apprise/wiki) available to
|
||||
us today such as: Telegram, Discord, Slack, Amazon SNS, Gotify, etc."
|
||||
|
||||
Depending on how you installed borgmatic, it may not have come with Apprise.
|
||||
@@ -22,7 +22,7 @@ sudo uv tool install borgmatic[Apprise]
|
||||
Omit `sudo` if borgmatic is installed as a non-root user.
|
||||
|
||||
Once Apprise is installed, configure borgmatic to notify one or more [Apprise
|
||||
services](https://appriseit.com/services/). For example:
|
||||
services](https://github.com/caronc/apprise/wiki). For example:
|
||||
|
||||
```yaml
|
||||
apprise:
|
||||
|
||||
@@ -29,11 +29,18 @@ probes the following values:
|
||||
You can see the runtime directory path that borgmatic selects by running with
|
||||
`--verbosity 2` and looking for `Using runtime directory` in the output.
|
||||
|
||||
Regardless of the runtime directory selected, borgmatic stores its files
|
||||
within a `borgmatic` subdirectory of the runtime directory. Additionally, in
|
||||
the case of `TMPDIR`, `TEMP`, and the hard-coded `/tmp`, borgmatic creates a
|
||||
randomly named subdirectory in an effort to reduce path collisions in shared
|
||||
system temporary directories.
|
||||
Regardless of the runtime directory selected, borgmatic stores its files within
|
||||
a `borgmatic` subdirectory of the runtime directory. Additionally, in the case
|
||||
of `TMPDIR`, `TEMP`, and the hard-coded `/tmp`, borgmatic creates a randomly
|
||||
named subdirectory in an effort to reduce path collisions and predictable
|
||||
temporary path attacks in shared temporary directories.
|
||||
|
||||
<span class="minilink minilink-addedin">New in version 2.1.6</span> When
|
||||
constructing the runtime directory, borgmatic now creates a subdirectory named
|
||||
after the Borg ID of the current repository. This means that borgmatic supports
|
||||
multiple borgmatic instances run [in
|
||||
parallel](https://torsion.org/borgmatic/how-to/make-per-application-backups/#parallelism)—as
|
||||
long as they're operating on different Borg repositories.
|
||||
|
||||
<span class="minilink minilink-addedin">Prior to version 1.9.0</span>
|
||||
borgmatic created temporary streaming database dumps within the `~/.borgmatic`
|
||||
|
||||
Vendored
BIN
Binary file not shown.
|
Before Width: | Height: | Size: 32 KiB |
+4
-7
@@ -1,18 +1,17 @@
|
||||
[project]
|
||||
name = "borgmatic"
|
||||
version = "2.1.6"
|
||||
version = "2.1.6.dev0"
|
||||
authors = [
|
||||
{ name="Dan Helfman", email="witten@torsion.org" },
|
||||
]
|
||||
description = "Simple, configuration-driven backup software for servers and workstations"
|
||||
license = "GPL-3.0-or-later"
|
||||
license-files = ["LICENSE"]
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.9"
|
||||
classifiers=[
|
||||
"Development Status :: 5 - Production/Stable",
|
||||
"Environment :: Console",
|
||||
"Intended Audience :: System Administrators",
|
||||
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
|
||||
"Programming Language :: Python",
|
||||
"Topic :: Security :: Cryptography",
|
||||
"Topic :: System :: Archiving :: Backup",
|
||||
@@ -31,8 +30,6 @@ validate-borgmatic-config = "borgmatic.commands.validate_config:main"
|
||||
|
||||
[project.optional-dependencies]
|
||||
Apprise = ["apprise"]
|
||||
browse = ["textual", "binaryornot"]
|
||||
browse-dev = ["textual-dev"]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://torsion.org/borgmatic"
|
||||
@@ -47,7 +44,7 @@ namespaces = false
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = "tests"
|
||||
addopts = "--cov-report term-missing:skip-covered --cov=borgmatic --no-cov-on-fail --cov-fail-under=100 --ignore=tests/end-to-end --timeout=120 --asyncio-mode=auto"
|
||||
addopts = "--cov-report term-missing:skip-covered --cov=borgmatic --no-cov-on-fail --cov-fail-under=100 --ignore=tests/end-to-end --timeout=120"
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 100
|
||||
@@ -57,7 +54,7 @@ exclude = ["*.*/*"]
|
||||
quote-style = "preserve"
|
||||
|
||||
[tool.ruff.lint]
|
||||
preview = false
|
||||
preview = true
|
||||
extend-select = [
|
||||
"A", # flake8-builtins: builtin shadowing
|
||||
"B", # flake8-bugbear: bugs and design problems
|
||||
|
||||
+3
-12
@@ -43,19 +43,15 @@ twine upload -r pypi --username __token__ "$wheel_path"
|
||||
scripts/export-docs-from-image
|
||||
docs_path=dist/borgmatic-docs.tar.gz
|
||||
|
||||
# Build stand-alone binaries.
|
||||
# Build stand-alone binary.
|
||||
uv venv --python 3.13 --clear binary
|
||||
source binary/bin/activate
|
||||
uv pip install -r binary_requirements.txt nuitka[onefile]
|
||||
nuitka --mode=onefile --enable-plugin=upx --include-package-data=borgmatic --include-data-dir=borgmatic.egg-info=borgmatic.egg-info --include-package=borgmatic.hooks --include-package=apprise --no-deployment-flag=self-execution borgmatic/commands/borgmatic.py
|
||||
rm -fr borgmatic.build borgmatic.dist
|
||||
deactivate
|
||||
rm -fr binary borgmatic.build borgmatic.dist
|
||||
standalone_binary_path="dist/borgmatic-${version}-binary-linux-glibc-x86_64"
|
||||
mv borgmatic.bin "$standalone_binary_path"
|
||||
nuitka --mode=onefile --enable-plugin=upx --include-package-data=borgmatic --include-data-dir=borgmatic.egg-info=borgmatic.egg-info --include-package=borgmatic.hooks --no-deployment-flag=self-execution borgmatic/commands/borgmatic.py
|
||||
rm -fr binary borgmatic.build borgmatic.dist
|
||||
deactivate
|
||||
standalone_minimal_binary_path="dist/borgmatic-${version}-minimal-binary-linux-glibc-x86_64"
|
||||
mv borgmatic.bin "$standalone_minimal_binary_path"
|
||||
|
||||
# Set release changelogs on projects.torsion.org and GitHub.
|
||||
release_changelog="$(cat NEWS | sed '/^$/q' | grep -v '^\S')"
|
||||
@@ -87,11 +83,6 @@ curl --silent --request POST \
|
||||
--header "Authorization: token $projects_token" \
|
||||
--header "Accept: application/json" \
|
||||
--form attachment=@"$standalone_binary_path"
|
||||
curl --silent --request POST \
|
||||
"https://projects.torsion.org/api/v1/repos/borgmatic-collective/borgmatic/releases/$release_id/assets?name=$(basename $standalone_minimal_binary_path)" \
|
||||
--header "Authorization: token $projects_token" \
|
||||
--header "Accept: application/json" \
|
||||
--form attachment=@"$standalone_minimal_binary_path"
|
||||
|
||||
github-release create --token="$github_token" --owner=witten --repo=borgmatic --tag="$version" --target_commit="main" \
|
||||
--name="borgmatic $version" --body="$release_changelog"
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
apprise
|
||||
attrs
|
||||
binaryornot
|
||||
certifi
|
||||
charset-normalizer
|
||||
click>=8.1.8
|
||||
@@ -17,16 +16,13 @@ packaging
|
||||
pluggy
|
||||
pygments
|
||||
pytest
|
||||
pytest-asyncio
|
||||
pytest-cov
|
||||
pytest-timeout
|
||||
pyyaml>5.0.0
|
||||
referencing
|
||||
requests
|
||||
requests-oauthlib
|
||||
rich
|
||||
rpds-py
|
||||
ruamel-yaml>0.15.0
|
||||
textual
|
||||
typing-extensions
|
||||
urllib3
|
||||
|
||||
+8
-18
@@ -2,39 +2,29 @@
|
||||
# uv pip compile --annotation-style line test_requirements.in -o test_requirements.txt
|
||||
apprise==1.10.0 # via -r test_requirements.in
|
||||
attrs==26.1.0 # via jsonschema, referencing, -r test_requirements.in
|
||||
binaryornot==0.6.0 # via -r test_requirements.in
|
||||
certifi==2026.5.20 # via apprise, requests, -r test_requirements.in
|
||||
certifi==2026.4.22 # via apprise, requests, -r test_requirements.in
|
||||
charset-normalizer==3.4.7 # via requests, -r test_requirements.in
|
||||
click>=8.1.8
|
||||
codespell==2.4.2 # via -r test_requirements.in
|
||||
coverage==7.14.0 # via pytest-cov, -r test_requirements.in
|
||||
coverage==7.13.5 # via pytest-cov, -r test_requirements.in
|
||||
flexmock==0.13.0 # via -r test_requirements.in
|
||||
idna==3.16 # via requests, -r test_requirements.in
|
||||
idna==3.13 # via requests, -r test_requirements.in
|
||||
iniconfig==2.3.0 # via pytest, -r test_requirements.in
|
||||
jsonschema==4.26.0 # via -r test_requirements.in
|
||||
jsonschema-specifications==2025.9.1 # via jsonschema, -r test_requirements.in
|
||||
linkify-it-py==2.1.0 # via markdown-it-py
|
||||
markdown==3.10.2 # via apprise, -r test_requirements.in
|
||||
markdown-it-py==4.2.0 # via mdit-py-plugins, rich, textual
|
||||
mdit-py-plugins==0.6.1 # via textual
|
||||
mdurl==0.1.2 # via markdown-it-py
|
||||
oauthlib==3.3.1 # via requests-oauthlib, -r test_requirements.in
|
||||
packaging==26.2 # via pytest, -r test_requirements.in
|
||||
platformdirs==4.9.6 # via textual
|
||||
pluggy==1.6.0 # via pytest, pytest-cov, -r test_requirements.in
|
||||
pygments==2.20.0 # via pytest, rich, textual, -r test_requirements.in
|
||||
pytest==9.0.3 # via pytest-asyncio, pytest-cov, pytest-timeout, -r test_requirements.in
|
||||
pytest-asyncio==1.3.0 # via -r test_requirements.in
|
||||
pygments==2.20.0 # via pytest, -r test_requirements.in
|
||||
pytest==9.0.3 # via pytest-cov, pytest-timeout, -r test_requirements.in
|
||||
pytest-cov==7.1.0 # via -r test_requirements.in
|
||||
pytest-timeout==2.4.0 # via -r test_requirements.in
|
||||
pyyaml>5.0.0
|
||||
referencing==0.37.0 # via jsonschema, jsonschema-specifications, -r test_requirements.in
|
||||
requests==2.34.2 # via apprise, requests-oauthlib, -r test_requirements.in
|
||||
requests==2.33.1 # via apprise, requests-oauthlib, -r test_requirements.in
|
||||
requests-oauthlib==2.0.0 # via apprise, -r test_requirements.in
|
||||
rich==15.0.0 # via textual, -r test_requirements.in
|
||||
rpds-py==0.30.0 # via jsonschema, referencing, -r test_requirements.in
|
||||
ruamel-yaml>0.15.0
|
||||
textual==8.2.7 # via -r test_requirements.in
|
||||
typing-extensions==4.15.0 # via textual, -r test_requirements.in
|
||||
uc-micro-py==2.0.0 # via linkify-it-py
|
||||
urllib3==2.7.0 # via requests, -r test_requirements.in
|
||||
typing-extensions==4.15.0 # via -r test_requirements.in
|
||||
urllib3==2.6.3 # via requests, -r test_requirements.in
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
from flexmock import flexmock
|
||||
|
||||
import borgmatic.actions.browse.app
|
||||
import borgmatic.actions.browse.configuration_files_list
|
||||
import borgmatic.actions.browse.logs
|
||||
import borgmatic.actions.browse.repositories_list
|
||||
|
||||
|
||||
async def test_browse_app_with_multiple_configs_uses_configuration_files_list():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
'test2.yaml': {'repositories': [{'path': 'test2.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
|
||||
async with app.run_test():
|
||||
app.query_one(selector='Header')
|
||||
|
||||
carousel = app.query_one(selector='Carousel')
|
||||
assert len(carousel.panels) == 1
|
||||
assert isinstance(
|
||||
carousel.panels[0],
|
||||
borgmatic.actions.browse.configuration_files_list.Configuration_files_list,
|
||||
)
|
||||
assert carousel.panels[0].configs == app.configs
|
||||
|
||||
app.query_one(selector='Logs')
|
||||
app.query_one(selector='Footer')
|
||||
|
||||
|
||||
async def test_browse_app_with_one_config_uses_repositories_list():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
|
||||
async with app.run_test():
|
||||
app.query_one(selector='Header')
|
||||
|
||||
carousel = app.query_one(selector='Carousel')
|
||||
assert len(carousel.panels) == 1
|
||||
assert isinstance(
|
||||
carousel.panels[0], borgmatic.actions.browse.repositories_list.Repositories_list
|
||||
)
|
||||
assert carousel.panels[0].config == app.configs['test1.yaml']
|
||||
|
||||
app.query_one(selector='Logs')
|
||||
app.query_one(selector='Footer')
|
||||
|
||||
|
||||
async def test_browse_app_key_toggles_logs_panel():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
logs_panel = app.query_one('#logs')
|
||||
|
||||
await pilot.press('v')
|
||||
await pilot.pause()
|
||||
assert logs_panel.styles.display == 'block'
|
||||
@@ -1,86 +0,0 @@
|
||||
import textual.app
|
||||
import textual.widgets.option_list
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.actions.browse import archives_list as module
|
||||
|
||||
|
||||
async def test_archives_list_on_mount_does_not_raise():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(module.borgmatic.actions.browse.workers).should_receive('add_repository_archives')
|
||||
archives_list = module.Archives_list(config=flexmock(), repository=flexmock())
|
||||
flexmock(archives_list.archive_loaded).should_receive('subscribe')
|
||||
|
||||
async with textual.app.App().run_test():
|
||||
archives_list.on_mount()
|
||||
|
||||
|
||||
def test_archives_list_on_archive_loaded_with_loading_done_removes_loading_indicator():
|
||||
loading_timer = flexmock()
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive(
|
||||
'add_inline_loading_indicator'
|
||||
).and_return(loading_timer)
|
||||
archives_list = module.Archives_list(config=flexmock(), repository=flexmock())
|
||||
flexmock(loading_timer).should_receive('stop')
|
||||
flexmock(archives_list).should_receive('remove_option').with_args('loading-indicator').once()
|
||||
flexmock(archives_list).should_receive('add_options').never()
|
||||
|
||||
archives_list.on_archive_loaded(module.borgmatic.actions.browse.workers.LOADING_DONE)
|
||||
|
||||
|
||||
def test_archives_list_on_archive_loaded_adds_archive_name():
|
||||
loading_timer = flexmock()
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive(
|
||||
'add_inline_loading_indicator'
|
||||
).and_return(loading_timer)
|
||||
archives_list = module.Archives_list(config=flexmock(), repository=flexmock())
|
||||
flexmock(loading_timer).should_receive('stop').never()
|
||||
loading_indicator = flexmock()
|
||||
flexmock(archives_list).should_receive('get_option').and_return(loading_indicator)
|
||||
flexmock(archives_list).should_receive('remove_option').with_args('loading-indicator').once()
|
||||
flexmock(archives_list).should_receive('add_options').once()
|
||||
|
||||
archives_list.on_archive_loaded('archive')
|
||||
|
||||
|
||||
def test_archives_list_on_option_list_option_highlighted_with_highlighted_none_marks_it_unchanged():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
|
||||
archives_list = module.Archives_list(config=flexmock(), repository=flexmock())
|
||||
archives_list.highlighted = None
|
||||
archives_list.on_option_list_option_highlighted(event=flexmock())
|
||||
|
||||
assert archives_list.highlighted_option_changed is False
|
||||
|
||||
|
||||
def test_archives_list_on_option_list_option_highlighted_with_highlighted_zero_marks_it_unchanged():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
|
||||
archives_list = module.Archives_list(config=flexmock(), repository=flexmock())
|
||||
archives_list.highlighted = 0
|
||||
archives_list.on_option_list_option_highlighted(event=flexmock())
|
||||
|
||||
assert archives_list.highlighted_option_changed is False
|
||||
|
||||
|
||||
def test_archives_list_on_option_list_option_highlighted_with_existing_option_and_highlighted_zero_marks_it_unchanged():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
|
||||
archives_list = module.Archives_list(config=flexmock(), repository=flexmock())
|
||||
archives_list.add_option(textual.widgets.option_list.Option('zero', id='zero'))
|
||||
archives_list.highlighted = 0
|
||||
archives_list.on_option_list_option_highlighted(event=flexmock())
|
||||
|
||||
assert archives_list.highlighted_option_changed is False
|
||||
|
||||
|
||||
def test_archives_list_on_option_list_option_highlighted_with_highlighted_non_zero_marks_it_changed():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
|
||||
archives_list = module.Archives_list(config=flexmock(), repository=flexmock())
|
||||
archives_list.add_option(textual.widgets.option_list.Option('zero', id='zero'))
|
||||
archives_list.add_option(textual.widgets.option_list.Option('one', id='one'))
|
||||
archives_list.highlighted = 1
|
||||
archives_list.on_option_list_option_highlighted(event=flexmock())
|
||||
|
||||
assert archives_list.highlighted_option_changed is True
|
||||
@@ -1,522 +0,0 @@
|
||||
import pytest
|
||||
import textual.widgets.option_list
|
||||
from flexmock import flexmock
|
||||
|
||||
import borgmatic.actions.browse.app
|
||||
import borgmatic.actions.browse.archive
|
||||
import borgmatic.actions.browse.carousel
|
||||
import borgmatic.actions.browse.loading
|
||||
import borgmatic.actions.browse.logs
|
||||
import borgmatic.actions.browse.workers
|
||||
from borgmatic.actions.browse import carousel as module
|
||||
|
||||
|
||||
def test_make_next_panel_with_configuration_files_list_returns_repositories_list():
|
||||
configs = {'test.yaml': {'repositories': [{'path': 'test.borg'}]}}
|
||||
|
||||
repositories_list = module.make_next_panel(
|
||||
focused_panel=borgmatic.actions.browse.configuration_files_list.Configuration_files_list(
|
||||
configs
|
||||
),
|
||||
option_id='test.yaml',
|
||||
)
|
||||
|
||||
assert isinstance(
|
||||
repositories_list, borgmatic.actions.browse.repositories_list.Repositories_list
|
||||
)
|
||||
assert repositories_list.config == configs['test.yaml']
|
||||
|
||||
|
||||
def test_make_next_panel_with_repositories_list_returns_archives_list():
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('add_repository_archives')
|
||||
flexmock(borgmatic.actions.browse.archives_list.Archives_list).should_receive('app').and_return(
|
||||
flexmock()
|
||||
)
|
||||
|
||||
archives_list = module.make_next_panel(
|
||||
focused_panel=borgmatic.actions.browse.repositories_list.Repositories_list(config),
|
||||
option_id=0,
|
||||
)
|
||||
|
||||
assert isinstance(archives_list, borgmatic.actions.browse.archives_list.Archives_list)
|
||||
assert archives_list.config == config
|
||||
assert archives_list.repository == config['repositories'][0]
|
||||
|
||||
|
||||
def test_make_next_panel_with_archives_list_returns_directory_list():
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('add_repository_archives')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('load_archive_paths')
|
||||
flexmock(borgmatic.actions.browse.archives_list.Archives_list).should_receive('app').and_return(
|
||||
flexmock()
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
|
||||
directory_list = module.make_next_panel(
|
||||
focused_panel=borgmatic.actions.browse.archives_list.Archives_list(
|
||||
config, config['repositories'][0]
|
||||
),
|
||||
option_id='archive',
|
||||
)
|
||||
|
||||
assert isinstance(directory_list, borgmatic.actions.browse.directory_list.Directory_list)
|
||||
assert directory_list.config == config
|
||||
assert directory_list.repository == config['repositories'][0]
|
||||
|
||||
|
||||
def test_make_next_panel_with_root_directory_list_and_selected_directory_option_returns_new_directory_list():
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('load_archive_paths')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('Archive_path_loaded').replace_with(
|
||||
flexmock(
|
||||
path_hierarchy={
|
||||
'etc': {},
|
||||
},
|
||||
complete=False,
|
||||
),
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
focused_panel = borgmatic.actions.browse.directory_list.Directory_list(
|
||||
config, config['repositories'][0], 'archive'
|
||||
)
|
||||
flexmock(focused_panel).should_receive('get_option').and_return(flexmock(prompt='📁 etc'))
|
||||
|
||||
directory_list = module.make_next_panel(focused_panel=focused_panel, option_id='etc')
|
||||
|
||||
assert isinstance(directory_list, borgmatic.actions.browse.directory_list.Directory_list)
|
||||
assert directory_list.config == config
|
||||
assert directory_list.repository == config['repositories'][0]
|
||||
assert directory_list.archive_name == 'archive'
|
||||
assert directory_list.path_components == ('etc',)
|
||||
|
||||
|
||||
def test_make_next_panel_with_non_root_directory_list_and_selected_directory_option_returns_new_directory_list():
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('load_archive_paths')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('Archive_path_loaded').replace_with(
|
||||
flexmock(
|
||||
path_hierarchy={
|
||||
'etc': {
|
||||
'borgmatic': {},
|
||||
},
|
||||
},
|
||||
complete=False,
|
||||
),
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
focused_panel = borgmatic.actions.browse.directory_list.Directory_list(
|
||||
config,
|
||||
config['repositories'][0],
|
||||
'archive',
|
||||
path_components=('etc',),
|
||||
)
|
||||
flexmock(focused_panel).should_receive('get_option').and_return(flexmock(prompt='📁 borgmatic'))
|
||||
|
||||
directory_list = module.make_next_panel(focused_panel=focused_panel, option_id='borgmatic')
|
||||
|
||||
assert isinstance(directory_list, borgmatic.actions.browse.directory_list.Directory_list)
|
||||
assert directory_list.config == config
|
||||
assert directory_list.repository == config['repositories'][0]
|
||||
assert directory_list.archive_name == 'archive'
|
||||
assert directory_list.path_components == ('etc', 'borgmatic')
|
||||
|
||||
|
||||
def test_make_next_panel_with_root_directory_list_and_selected_file_option_returns_new_file_preview():
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('load_archive_paths')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('load_file_preview')
|
||||
flexmock(borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
flexmock(borgmatic.actions.browse.file_preview.File_preview).should_receive('app').and_return(
|
||||
flexmock()
|
||||
)
|
||||
focused_panel = borgmatic.actions.browse.directory_list.Directory_list(
|
||||
config, config['repositories'][0], 'archive'
|
||||
)
|
||||
flexmock(focused_panel).should_receive('get_option').and_return(
|
||||
flexmock(prompt='📄 config.yaml')
|
||||
)
|
||||
|
||||
directory_list = module.make_next_panel(focused_panel=focused_panel, option_id='config.yaml')
|
||||
|
||||
assert isinstance(directory_list, borgmatic.actions.browse.file_preview.File_preview)
|
||||
assert directory_list.config == config
|
||||
assert directory_list.repository == config['repositories'][0]
|
||||
assert directory_list.archive_name == 'archive'
|
||||
assert directory_list.file_path == 'config.yaml'
|
||||
|
||||
|
||||
def test_make_next_panel_with_non_root_directory_list_and_selected_file_option_returns_new_file_preview():
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('load_archive_paths')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('load_file_preview')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('Archive_path_loaded').replace_with(
|
||||
flexmock(
|
||||
path_hierarchy={
|
||||
'etc': {
|
||||
'borgmatic': {
|
||||
'config.yaml': borgmatic.actions.browse.archive.Archive_path(
|
||||
'-', 'config.yaml', ''
|
||||
),
|
||||
},
|
||||
},
|
||||
},
|
||||
complete=False,
|
||||
),
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
flexmock(borgmatic.actions.browse.file_preview.File_preview).should_receive('app').and_return(
|
||||
flexmock()
|
||||
)
|
||||
focused_panel = borgmatic.actions.browse.directory_list.Directory_list(
|
||||
config,
|
||||
config['repositories'][0],
|
||||
'archive',
|
||||
path_components=('etc', 'borgmatic'),
|
||||
)
|
||||
flexmock(focused_panel).should_receive('get_option').and_return(
|
||||
flexmock(prompt='📄 config.yaml')
|
||||
)
|
||||
|
||||
directory_list = module.make_next_panel(focused_panel=focused_panel, option_id='config.yaml')
|
||||
|
||||
assert isinstance(directory_list, borgmatic.actions.browse.file_preview.File_preview)
|
||||
assert directory_list.config == config
|
||||
assert directory_list.repository == config['repositories'][0]
|
||||
assert directory_list.archive_name == 'archive'
|
||||
assert directory_list.file_path == 'etc/borgmatic/config.yaml'
|
||||
|
||||
|
||||
def test_make_next_panel_with_unsupported_focused_panel_returns_none():
|
||||
assert module.make_next_panel(focused_panel=flexmock(), option_id='hmmm') is None
|
||||
|
||||
|
||||
@pytest.mark.parametrize('icon', ('🔗', '🚰', '🐙'))
|
||||
def test_make_next_panel_with_directory_list_and_unsupported_selected_option_returns_none(icon):
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('load_archive_paths')
|
||||
flexmock(borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
focused_panel = borgmatic.actions.browse.directory_list.Directory_list(
|
||||
config, config['repositories'][0], 'archive'
|
||||
)
|
||||
flexmock(focused_panel).should_receive('get_option').and_return(
|
||||
flexmock(prompt=f'{icon} config.yaml')
|
||||
)
|
||||
|
||||
assert module.make_next_panel(focused_panel=focused_panel, option_id='config.yaml') is None
|
||||
|
||||
|
||||
async def test_carousel_previous_action_with_multiple_configs_does_not_raise():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
'test2.yaml': {'repositories': [{'path': 'test2.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press('left')
|
||||
|
||||
|
||||
async def test_carousel_previous_action_with_one_config_does_not_raise():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press('left')
|
||||
|
||||
|
||||
async def test_carousel_next_action_with_multiple_configs_advances_panel():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
'test2.yaml': {'repositories': [{'path': 'test2.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press('enter')
|
||||
|
||||
carousel = app.query_one(selector='Carousel')
|
||||
assert len(carousel.panels) == 2
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[0],
|
||||
borgmatic.actions.browse.configuration_files_list.Configuration_files_list,
|
||||
)
|
||||
assert carousel.panels[0].styles.display == 'none'
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[1], borgmatic.actions.browse.repositories_list.Repositories_list
|
||||
)
|
||||
assert carousel.panels[1].styles.display == 'block'
|
||||
assert carousel.panels[1].highlighted == 0
|
||||
assert app.focused == carousel.panels[1]
|
||||
|
||||
|
||||
async def test_carousel_next_action_with_one_config_advances_panel():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('add_repository_archives')
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press('enter')
|
||||
|
||||
carousel = app.query_one(selector='Carousel')
|
||||
assert len(carousel.panels) == 2
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[0], borgmatic.actions.browse.repositories_list.Repositories_list
|
||||
)
|
||||
assert carousel.panels[0].styles.display == 'none'
|
||||
|
||||
assert isinstance(carousel.panels[1], borgmatic.actions.browse.archives_list.Archives_list)
|
||||
assert carousel.panels[1].styles.display == 'block'
|
||||
assert carousel.panels[1].highlighted == 0
|
||||
assert app.focused == carousel.panels[1]
|
||||
|
||||
|
||||
async def test_carousel_next_action_with_no_next_panel_does_not_advance():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
flexmock(borgmatic.actions.browse.workers).should_receive('add_repository_archives')
|
||||
flexmock(module).should_receive('make_next_panel')
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press('enter')
|
||||
|
||||
carousel = app.query_one(selector='Carousel')
|
||||
assert len(carousel.panels) == 1
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[0], borgmatic.actions.browse.repositories_list.Repositories_list
|
||||
)
|
||||
assert carousel.panels[0].styles.display == 'block'
|
||||
assert app.focused == carousel.panels[0]
|
||||
|
||||
|
||||
async def test_carousel_next_action_and_previous_action_returns_to_original_panel():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
'test2.yaml': {'repositories': [{'path': 'test2.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press('enter')
|
||||
await pilot.press('left')
|
||||
|
||||
carousel = app.query_one(selector='Carousel')
|
||||
assert len(carousel.panels) == 2
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[0],
|
||||
borgmatic.actions.browse.configuration_files_list.Configuration_files_list,
|
||||
)
|
||||
assert carousel.panels[0].styles.display == 'block'
|
||||
assert carousel.panels[0].highlighted == 0
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[1], borgmatic.actions.browse.repositories_list.Repositories_list
|
||||
)
|
||||
assert carousel.panels[1].styles.display == 'none'
|
||||
assert app.focused == carousel.panels[0]
|
||||
|
||||
|
||||
async def test_carousel_next_action_and_previous_action_and_next_action_reuses_next_panel():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
'test2.yaml': {'repositories': [{'path': 'test2.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
flexmock(borgmatic.actions.browse.carousel).should_call('make_next_panel').once()
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press('enter')
|
||||
await pilot.press('left')
|
||||
await pilot.press('enter')
|
||||
|
||||
carousel = app.query_one(selector='Carousel')
|
||||
assert len(carousel.panels) == 2
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[0],
|
||||
borgmatic.actions.browse.configuration_files_list.Configuration_files_list,
|
||||
)
|
||||
assert carousel.panels[0].styles.display == 'none'
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[1], borgmatic.actions.browse.repositories_list.Repositories_list
|
||||
)
|
||||
assert carousel.panels[1].styles.display == 'block'
|
||||
assert carousel.panels[1].highlighted == 0
|
||||
assert app.focused == carousel.panels[1]
|
||||
|
||||
|
||||
async def test_carousel_next_action_with_multiple_configs_and_no_next_panel_does_not_advance():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
'test2.yaml': {'repositories': [{'path': 'test2.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
flexmock(module).should_receive('make_next_panel').and_return(None)
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press('enter')
|
||||
|
||||
carousel = app.query_one(selector='Carousel')
|
||||
assert len(carousel.panels) == 1
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[0],
|
||||
borgmatic.actions.browse.configuration_files_list.Configuration_files_list,
|
||||
)
|
||||
assert carousel.panels[0].styles.display == 'block'
|
||||
assert carousel.panels[0].highlighted == 0
|
||||
assert app.focused == carousel.panels[0]
|
||||
|
||||
|
||||
async def test_carousel_next_action_and_previous_action_and_down_truncates_next_panel():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
'test2.yaml': {'repositories': [{'path': 'test2.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press('enter')
|
||||
await pilot.press('left')
|
||||
await pilot.press('down')
|
||||
|
||||
carousel = app.query_one(selector='Carousel')
|
||||
assert len(carousel.panels) == 1
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[0],
|
||||
borgmatic.actions.browse.configuration_files_list.Configuration_files_list,
|
||||
)
|
||||
assert carousel.panels[0].styles.display == 'block'
|
||||
assert carousel.panels[0].highlighted == 1
|
||||
assert app.focused == carousel.panels[0]
|
||||
|
||||
|
||||
async def test_carousel_down_does_not_raise():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
'test2.yaml': {'repositories': [{'path': 'test2.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press('down')
|
||||
|
||||
carousel = app.query_one(selector='Carousel')
|
||||
assert len(carousel.panels) == 1
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[0],
|
||||
borgmatic.actions.browse.configuration_files_list.Configuration_files_list,
|
||||
)
|
||||
assert carousel.panels[0].styles.display == 'block'
|
||||
assert carousel.panels[0].highlighted == 1
|
||||
assert app.focused == carousel.panels[0]
|
||||
|
||||
|
||||
async def test_carousel_up_does_not_raise():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
'test2.yaml': {'repositories': [{'path': 'test2.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press('down')
|
||||
|
||||
carousel = app.query_one(selector='Carousel')
|
||||
assert len(carousel.panels) == 1
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[0],
|
||||
borgmatic.actions.browse.configuration_files_list.Configuration_files_list,
|
||||
)
|
||||
assert carousel.panels[0].styles.display == 'block'
|
||||
assert carousel.panels[0].highlighted == 1
|
||||
assert app.focused == carousel.panels[0]
|
||||
|
||||
|
||||
async def test_carousel_next_action_and_select_dot_dot_returns_to_original_panel():
|
||||
app = borgmatic.actions.browse.app.Browse_app(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
'test2.yaml': {'repositories': [{'path': 'test2.borg'}]},
|
||||
}
|
||||
)
|
||||
flexmock(borgmatic.actions.browse.logs).should_receive('log_to_widget')
|
||||
|
||||
async with app.run_test() as pilot:
|
||||
await pilot.press('enter')
|
||||
|
||||
carousel = app.query_one(selector='Carousel')
|
||||
carousel.panels[1].options[0] = textual.widgets.option_list.Option('..', id='..')
|
||||
|
||||
await pilot.press('enter')
|
||||
|
||||
assert len(carousel.panels) == 2
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[0],
|
||||
borgmatic.actions.browse.configuration_files_list.Configuration_files_list,
|
||||
)
|
||||
assert carousel.panels[0].styles.display == 'block'
|
||||
assert carousel.panels[0].highlighted == 0
|
||||
|
||||
assert isinstance(
|
||||
carousel.panels[1], borgmatic.actions.browse.repositories_list.Repositories_list
|
||||
)
|
||||
assert carousel.panels[1].styles.display == 'none'
|
||||
assert app.focused == carousel.panels[0]
|
||||
@@ -1,34 +0,0 @@
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.actions.browse import configuration_files_list as module
|
||||
|
||||
|
||||
def test_configuration_files_list_adds_config_paths_as_options():
|
||||
flexmock(module.os.path).should_receive('expanduser').and_return('/home/user')
|
||||
|
||||
configuration_files_list = module.Configuration_files_list(
|
||||
configs={
|
||||
'test1.yaml': {'repositories': [{'path': 'test1.borg'}]},
|
||||
'test2.yaml': {'repositories': [{'path': 'test2.borg'}]},
|
||||
}
|
||||
)
|
||||
|
||||
assert len(configuration_files_list.options) == 2
|
||||
assert configuration_files_list.options[0].prompt == 'test1.yaml'
|
||||
assert configuration_files_list.options[0].id == 'test1.yaml'
|
||||
assert configuration_files_list.options[1].prompt == 'test2.yaml'
|
||||
assert configuration_files_list.options[1].id == 'test2.yaml'
|
||||
|
||||
|
||||
def test_configuration_files_list_collapses_home_directory_in_config_path_option():
|
||||
flexmock(module.os.path).should_receive('expanduser').and_return('/home/user')
|
||||
|
||||
configuration_files_list = module.Configuration_files_list(
|
||||
configs={
|
||||
'/home/user/test.yaml': {'repositories': [{'path': '/home/user/test.borg'}]},
|
||||
}
|
||||
)
|
||||
|
||||
assert len(configuration_files_list.options) == 1
|
||||
assert configuration_files_list.options[0].prompt == '~/test.yaml'
|
||||
assert configuration_files_list.options[0].id == '/home/user/test.yaml'
|
||||
@@ -1,287 +0,0 @@
|
||||
import textual.widgets
|
||||
import textual.widgets.option_list
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.actions.browse import directory_list as module
|
||||
|
||||
|
||||
def test_add_archive_paths_with_only_duplicate_paths_bails():
|
||||
directory_list = textual.widgets.OptionList()
|
||||
directory_list.path_components = ('etc',)
|
||||
directory_list.add_option(textual.widgets.option_list.Option('foo', id='foo'))
|
||||
directory_list.add_option(textual.widgets.option_list.Option('bar', id='bar'))
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(directory_list).should_receive('set_options').never()
|
||||
|
||||
module.add_archive_paths(
|
||||
directory_list=directory_list,
|
||||
config=config,
|
||||
repository=config['repositories'][0],
|
||||
archive_name='archive',
|
||||
archive_paths=(
|
||||
flexmock(path_type='-', file_path='etc/foo/one.txt', link_target=''),
|
||||
flexmock(path_type='-', file_path='etc/foo/two.txt', link_target=''),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def test_add_archive_paths_adds_ands_sorts_and_filters_and_deduplicates():
|
||||
directory_list = textual.widgets.OptionList()
|
||||
directory_list.path_components = ('etc',)
|
||||
directory_list.add_option(textual.widgets.option_list.Option('📄 foo', id='foo'))
|
||||
directory_list.add_option(textual.widgets.option_list.Option('📄 bar', id='bar'))
|
||||
directory_list.highlighted = 1
|
||||
directory_list.highlighted_option_changed = True
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
|
||||
module.add_archive_paths(
|
||||
directory_list=directory_list,
|
||||
config=config,
|
||||
repository=config['repositories'][0],
|
||||
archive_name='archive',
|
||||
archive_paths=(
|
||||
flexmock(path_type='d', file_path='etc/quux', link_target=''),
|
||||
flexmock(path_type='-', file_path='etc/foo', link_target=''),
|
||||
flexmock(path_type='-', file_path='etc/baz', link_target=''),
|
||||
flexmock(path_type='d', file_path='root/nope', link_target=''),
|
||||
flexmock(path_type='d', file_path='etc/other', link_target=''),
|
||||
),
|
||||
)
|
||||
|
||||
assert len(directory_list.options) == 5
|
||||
assert directory_list.options[0].prompt == '📁 other'
|
||||
assert directory_list.options[0].id == 'other'
|
||||
assert directory_list.options[1].prompt == '📁 quux'
|
||||
assert directory_list.options[1].id == 'quux'
|
||||
assert directory_list.options[2].prompt == '📄 bar'
|
||||
assert directory_list.options[2].id == 'bar'
|
||||
assert directory_list.options[3].prompt == '📄 baz'
|
||||
assert directory_list.options[3].id == 'baz'
|
||||
assert directory_list.options[4].prompt == '📄 foo'
|
||||
assert directory_list.options[4].id == 'foo'
|
||||
assert directory_list.highlighted == 2
|
||||
|
||||
|
||||
def test_add_archive_paths_highlights_first_option_if_highlight_has_not_changed():
|
||||
directory_list = textual.widgets.OptionList()
|
||||
directory_list.path_components = ('etc',)
|
||||
directory_list.add_option(textual.widgets.option_list.Option('📄 foo', id='foo'))
|
||||
directory_list.add_option(textual.widgets.option_list.Option('📄 bar', id='bar'))
|
||||
directory_list.highlighted = None
|
||||
directory_list.highlighted_option_changed = False
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
|
||||
module.add_archive_paths(
|
||||
directory_list=directory_list,
|
||||
config=config,
|
||||
repository=config['repositories'][0],
|
||||
archive_name='archive',
|
||||
archive_paths=(flexmock(path_type='-', file_path='etc/baz', link_target=''),),
|
||||
)
|
||||
|
||||
assert len(directory_list.options) == 3
|
||||
assert directory_list.options[0].prompt == '📄 bar'
|
||||
assert directory_list.options[0].id == 'bar'
|
||||
assert directory_list.options[1].prompt == '📄 baz'
|
||||
assert directory_list.options[1].id == 'baz'
|
||||
assert directory_list.options[2].prompt == '📄 foo'
|
||||
assert directory_list.options[2].id == 'foo'
|
||||
assert directory_list.highlighted == 0
|
||||
|
||||
|
||||
def test_add_archive_paths_retains_loading_indicator_at_bottom():
|
||||
directory_list = textual.widgets.OptionList()
|
||||
directory_list.path_components = ('etc',)
|
||||
directory_list.add_option(textual.widgets.option_list.Option('📄 foo', id='foo'))
|
||||
directory_list.add_option(textual.widgets.option_list.Option('📄 bar', id='bar'))
|
||||
directory_list.add_option(
|
||||
textual.widgets.option_list.Option('loading!!!', id='loading-indicator')
|
||||
)
|
||||
directory_list.highlighted = 0
|
||||
directory_list.highlighted_option_changed = True
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
|
||||
module.add_archive_paths(
|
||||
directory_list=directory_list,
|
||||
config=config,
|
||||
repository=config['repositories'][0],
|
||||
archive_name='archive',
|
||||
archive_paths=(flexmock(path_type='-', file_path='etc/baz', link_target=''),),
|
||||
)
|
||||
|
||||
assert len(directory_list.options) == 4
|
||||
assert directory_list.options[0].prompt == '📄 bar'
|
||||
assert directory_list.options[0].id == 'bar'
|
||||
assert directory_list.options[1].prompt == '📄 baz'
|
||||
assert directory_list.options[1].id == 'baz'
|
||||
assert directory_list.options[2].prompt == '📄 foo'
|
||||
assert directory_list.options[2].id == 'foo'
|
||||
assert directory_list.options[3].prompt == 'loading!!!'
|
||||
assert directory_list.options[3].id == 'loading-indicator'
|
||||
assert directory_list.highlighted == 2
|
||||
|
||||
|
||||
def test_directory_list_with_root_directory_adds_loading_indicator():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive(
|
||||
'add_inline_loading_indicator'
|
||||
).once()
|
||||
|
||||
directory_list = module.Directory_list(
|
||||
config=flexmock(), repository=flexmock(), archive_name='archive'
|
||||
)
|
||||
assert directory_list.border_title == '📁 archive'
|
||||
assert len(directory_list.options) == 0
|
||||
assert not directory_list.path_loaded.complete
|
||||
|
||||
|
||||
def test_directory_list_with_already_complete_loading_skips_loading_indicator():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive(
|
||||
'add_inline_loading_indicator'
|
||||
).never()
|
||||
flexmock(module.borgmatic.actions.browse.workers).should_receive('load_archive_paths').never()
|
||||
flexmock(module.borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
|
||||
directory_list = module.Directory_list(
|
||||
config=flexmock(),
|
||||
repository=flexmock(),
|
||||
archive_name='archive',
|
||||
path_loaded=flexmock(complete=True),
|
||||
path_components=('etc',),
|
||||
)
|
||||
assert directory_list.border_title == '📁 etc'
|
||||
assert len(directory_list.options) == 1
|
||||
assert directory_list.options[0].prompt == '📁 ..'
|
||||
assert directory_list.options[0].id == '..'
|
||||
|
||||
|
||||
def test_directory_list_on_mount_with_root_directory_loads_archive_paths():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(module.borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
flexmock(module.borgmatic.actions.browse.workers).should_receive('load_archive_paths').once()
|
||||
flexmock(module).should_receive('add_archive_paths').never()
|
||||
directory_list = module.Directory_list(
|
||||
config=flexmock(), repository=flexmock(), archive_name='archive'
|
||||
)
|
||||
flexmock(directory_list.path_loaded).should_receive('subscribe')
|
||||
|
||||
directory_list.on_mount()
|
||||
|
||||
|
||||
def test_directory_list_on_mount_with_non_root_directory_adds_archive_paths():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(module.borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
flexmock(module.borgmatic.actions.browse.workers).should_receive('load_archive_paths').never()
|
||||
flexmock(module).should_receive('add_archive_paths').once()
|
||||
directory_list = module.Directory_list(
|
||||
config=flexmock(),
|
||||
repository=flexmock(),
|
||||
archive_name='archive',
|
||||
path_loaded=flexmock(complete=False, path_hierarchy={'etc': {}}),
|
||||
path_components=('etc',),
|
||||
)
|
||||
flexmock(directory_list.path_loaded).should_receive('subscribe')
|
||||
|
||||
directory_list.on_mount()
|
||||
|
||||
|
||||
def test_on_archive_path_loaded_with_loading_done_signal_removes_loading_indicator():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(module.borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
flexmock(module).should_receive('add_archive_paths').never()
|
||||
directory_list = module.Directory_list(
|
||||
config=flexmock(),
|
||||
repository=flexmock(),
|
||||
archive_name='archive',
|
||||
path_loaded=flexmock(complete=False, path_hierarchy={'etc': {}}),
|
||||
path_components=('etc',),
|
||||
)
|
||||
directory_list.timer = flexmock(stop=lambda: None)
|
||||
flexmock(directory_list).should_receive('remove_option').once()
|
||||
|
||||
directory_list.on_archive_path_loaded(data=module.borgmatic.actions.browse.workers.LOADING_DONE)
|
||||
|
||||
|
||||
def test_on_archive_path_loaded_with_path_loaded_signal_adds_archive_path():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(module.borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
flexmock(module).should_receive('add_archive_paths').once()
|
||||
directory_list = module.Directory_list(
|
||||
config=flexmock(),
|
||||
repository=flexmock(),
|
||||
archive_name='archive',
|
||||
path_loaded=flexmock(complete=False, path_hierarchy={'etc': {}}),
|
||||
path_components=('etc',),
|
||||
)
|
||||
flexmock(directory_list).should_receive('remove_option').never()
|
||||
|
||||
directory_list.on_archive_path_loaded(data=flexmock())
|
||||
|
||||
|
||||
def test_directory_list_on_option_list_option_highlighted_with_highlighted_none_marks_it_unchanged():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(module.borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
directory_list = module.Directory_list(
|
||||
config=flexmock(),
|
||||
repository=flexmock(),
|
||||
archive_name='archive',
|
||||
path_loaded=flexmock(complete=False, path_hierarchy={'etc': {}}),
|
||||
path_components=('etc',),
|
||||
)
|
||||
directory_list.highlighted = None
|
||||
|
||||
directory_list.on_option_list_option_highlighted(event=flexmock())
|
||||
|
||||
assert directory_list.highlighted_option_changed is False
|
||||
|
||||
|
||||
def test_directory_list_on_option_list_option_highlighted_with_highlighted_zero_marks_it_unchanged():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(module.borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
directory_list = module.Directory_list(
|
||||
config=flexmock(),
|
||||
repository=flexmock(),
|
||||
archive_name='archive',
|
||||
path_loaded=flexmock(complete=False, path_hierarchy={'etc': {}}),
|
||||
path_components=('etc',),
|
||||
)
|
||||
directory_list.add_option(textual.widgets.option_list.Option('zero', id='zero'))
|
||||
directory_list.highlighted = 0
|
||||
|
||||
directory_list.on_option_list_option_highlighted(event=flexmock())
|
||||
|
||||
assert directory_list.highlighted_option_changed is False
|
||||
|
||||
|
||||
def test_directory_list_on_option_list_option_highlighted_with_highlighted_non_zero_marks_it_changed():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(module.borgmatic.actions.browse.directory_list.Directory_list).should_receive(
|
||||
'app'
|
||||
).and_return(flexmock())
|
||||
directory_list = module.Directory_list(
|
||||
config=flexmock(),
|
||||
repository=flexmock(),
|
||||
archive_name='archive',
|
||||
path_loaded=flexmock(complete=False, path_hierarchy={'etc': {}}),
|
||||
path_components=('etc',),
|
||||
)
|
||||
directory_list.add_option(textual.widgets.option_list.Option('zero', id='zero'))
|
||||
directory_list.add_option(textual.widgets.option_list.Option('one', id='one'))
|
||||
directory_list.highlighted = 1
|
||||
|
||||
directory_list.on_option_list_option_highlighted(event=flexmock())
|
||||
|
||||
assert directory_list.highlighted_option_changed is True
|
||||
@@ -1,53 +0,0 @@
|
||||
import textual.widgets.option_list
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.actions.browse import file_preview as module
|
||||
|
||||
|
||||
def test_file_preview_does_not_raise():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
|
||||
module.File_preview(
|
||||
config=flexmock(), repository=flexmock(), archive_name='archive', file_path='foo/bar.txt'
|
||||
)
|
||||
|
||||
|
||||
async def test_file_preview_on_mount_does_not_raise():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive('add_inline_loading_indicator')
|
||||
flexmock(module.borgmatic.actions.browse.workers).should_receive('load_file_preview')
|
||||
file_preview = module.File_preview(
|
||||
config=flexmock(), repository=flexmock(), archive_name='archive', file_path='foo.txt'
|
||||
)
|
||||
flexmock(file_preview.file_preview_loaded).should_receive('subscribe')
|
||||
|
||||
async with textual.app.App().run_test():
|
||||
file_preview.on_mount()
|
||||
|
||||
|
||||
def test_file_preview_on_file_preview_loaded_with_none_file_contents_displays_error():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive(
|
||||
'add_inline_loading_indicator'
|
||||
).and_return(flexmock(stop=lambda: None))
|
||||
file_preview = module.File_preview(
|
||||
config=flexmock(), repository=flexmock(), archive_name='archive', file_path='foo.txt'
|
||||
)
|
||||
flexmock(file_preview).should_receive('write').with_args(
|
||||
'Cannot display a preview for this file'
|
||||
).once()
|
||||
|
||||
file_preview.on_file_preview_loaded(None)
|
||||
|
||||
|
||||
def test_file_preview_on_file_preview_loaded_with_file_contents_displays_contents():
|
||||
flexmock(module.borgmatic.actions.browse.loading).should_receive(
|
||||
'add_inline_loading_indicator'
|
||||
).and_return(flexmock(stop=lambda: None))
|
||||
file_preview = module.File_preview(
|
||||
config=flexmock(), repository=flexmock(), archive_name='archive', file_path='foo.txt'
|
||||
)
|
||||
flexmock(file_preview).should_receive('write').with_args(
|
||||
'Cannot display a preview for this file'
|
||||
).never()
|
||||
flexmock(file_preview).should_receive('write').once()
|
||||
|
||||
file_preview.on_file_preview_loaded('hi')
|
||||
@@ -1,97 +0,0 @@
|
||||
import pytest
|
||||
import textual.app
|
||||
import textual.widgets
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.actions.browse import loading as module
|
||||
|
||||
|
||||
def test_update_inline_loading_indicator_with_option_list_adds_a_dot():
|
||||
widget = textual.widgets.OptionList()
|
||||
widget.add_option(textual.widgets.option_list.Option('HOLD.', id='loading-indicator'))
|
||||
|
||||
module.update_inline_loading_indicator(widget)
|
||||
|
||||
assert len(widget.options) == 1
|
||||
assert widget.options[0].prompt == 'HOLD..'
|
||||
|
||||
|
||||
def test_update_inline_loading_indicator_with_option_list_wraps_dots_beyond_three():
|
||||
widget = textual.widgets.OptionList()
|
||||
widget.add_option(textual.widgets.option_list.Option('HOLD...', id='loading-indicator'))
|
||||
|
||||
module.update_inline_loading_indicator(widget)
|
||||
|
||||
assert len(widget.options) == 1
|
||||
assert widget.options[0].prompt == 'HOLD'
|
||||
|
||||
|
||||
def test_update_inline_loading_indicator_with_option_list_and_missing_indicator_does_not_raise():
|
||||
widget = textual.widgets.OptionList()
|
||||
|
||||
module.update_inline_loading_indicator(widget)
|
||||
|
||||
assert len(widget.options) == 0
|
||||
|
||||
|
||||
async def test_update_inline_loading_indicator_with_rich_log_adds_a_dot():
|
||||
async with textual.app.App().run_test():
|
||||
widget = textual.widgets.RichLog()
|
||||
widget._size_known = True
|
||||
widget.write('HOLD.')
|
||||
|
||||
module.update_inline_loading_indicator(widget)
|
||||
|
||||
assert str(widget.lines[0].text) == 'HOLD..'
|
||||
|
||||
|
||||
async def test_update_inline_loading_indicator_with_rich_log_wraps_dots_beyond_three():
|
||||
async with textual.app.App().run_test():
|
||||
widget = textual.widgets.RichLog()
|
||||
widget._size_known = True
|
||||
widget.write('HOLD...')
|
||||
|
||||
module.update_inline_loading_indicator(widget)
|
||||
|
||||
assert str(widget.lines[0].text) == 'HOLD'
|
||||
|
||||
|
||||
def test_update_inline_loading_indicator_with_rich_log_and_missing_indicator_does_not_raise():
|
||||
widget = textual.widgets.RichLog()
|
||||
|
||||
module.update_inline_loading_indicator(widget)
|
||||
|
||||
assert len(widget.lines) == 0
|
||||
|
||||
|
||||
def test_update_inline_loading_indicator_with_unsupported_widget_type_raises():
|
||||
with pytest.raises(ValueError):
|
||||
module.update_inline_loading_indicator(flexmock())
|
||||
|
||||
|
||||
def test_add_inline_loading_indicator_with_option_list_adds_loading_indicator_option():
|
||||
widget = textual.widgets.OptionList()
|
||||
flexmock(widget).should_receive('set_interval')
|
||||
|
||||
module.add_inline_loading_indicator(widget)
|
||||
|
||||
assert len(widget.options) == 1
|
||||
assert widget.options[0].prompt == module.LOADING_MESSAGE
|
||||
assert widget.options[0].id == 'loading-indicator'
|
||||
assert widget.highlighted is None
|
||||
|
||||
|
||||
async def test_add_inline_loading_indicator_with_rich_log_writes_loading_indicator_text():
|
||||
async with textual.app.App().run_test():
|
||||
widget = textual.widgets.RichLog()
|
||||
widget._size_known = True
|
||||
flexmock(widget).should_receive('set_interval')
|
||||
|
||||
module.add_inline_loading_indicator(widget)
|
||||
|
||||
assert str(widget.lines[0].text) == module.LOADING_MESSAGE
|
||||
|
||||
|
||||
def test_add_inline_loading_indicator_with_unsupported_widget_type_raises():
|
||||
with pytest.raises(ValueError):
|
||||
module.add_inline_loading_indicator(flexmock())
|
||||
@@ -1,37 +0,0 @@
|
||||
import contextlib
|
||||
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.actions.browse import logs as module
|
||||
|
||||
|
||||
def test_log_to_widget_adds_our_handler_and_removes_default_handler():
|
||||
default_handler = module.borgmatic.logger.Multi_stream_handler({})
|
||||
root_logger = module.logging.getLogger()
|
||||
root_logger.addHandler(default_handler)
|
||||
browse_log_handler = None
|
||||
|
||||
try:
|
||||
module.log_to_widget(flexmock())
|
||||
|
||||
with contextlib.suppress(StopIteration):
|
||||
browse_log_handler = next(
|
||||
handler
|
||||
for handler in root_logger.handlers
|
||||
if isinstance(handler, module.Browse_log_handler)
|
||||
)
|
||||
|
||||
assert browse_log_handler
|
||||
finally:
|
||||
if browse_log_handler:
|
||||
root_logger.removeHandler(browse_log_handler)
|
||||
|
||||
assert not any(
|
||||
handler
|
||||
for handler in root_logger.handlers
|
||||
if isinstance(handler, module.borgmatic.logger.Multi_stream_handler)
|
||||
)
|
||||
|
||||
|
||||
def test_logs_does_not_raise():
|
||||
module.Logs()
|
||||
@@ -1,12 +0,0 @@
|
||||
from borgmatic.actions.browse import repositories_list as module
|
||||
|
||||
|
||||
def test_repositories_list_populates_options():
|
||||
config = {'repositories': [{'path': 'test1.borg'}, {'path': 'test2.borg', 'label': 'two'}]}
|
||||
|
||||
repositories_list = module.Repositories_list(config=config)
|
||||
assert len(repositories_list.options) == 2
|
||||
assert repositories_list.options[0].prompt == 'test1.borg'
|
||||
assert repositories_list.options[0].id == 0
|
||||
assert repositories_list.options[1].prompt == 'two'
|
||||
assert repositories_list.options[1].id == 1
|
||||
@@ -1,19 +0,0 @@
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.actions.browse import workers as module
|
||||
|
||||
|
||||
def test_archive_path_loaded_publish_records_complete():
|
||||
signal = module.Archive_path_loaded(owner=flexmock(), name='Bob')
|
||||
signal.publish(module.LOADING_DONE)
|
||||
|
||||
assert signal.complete
|
||||
|
||||
|
||||
def test_archive_path_loaded_publish_records_published_path():
|
||||
archive_path = module.borgmatic.actions.browse.archive.Archive_path('-', 'foo/bar.txt', '')
|
||||
signal = module.Archive_path_loaded(owner=flexmock(), name='Bob')
|
||||
signal.publish(archive_path)
|
||||
|
||||
assert signal.path_hierarchy == {'foo': {'bar.txt': archive_path}}
|
||||
assert not signal.complete
|
||||
@@ -57,8 +57,6 @@ def test_make_rename_command_includes_log_debug():
|
||||
|
||||
|
||||
def test_make_rename_command_includes_dry_run():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_rename_command(
|
||||
dry_run=True,
|
||||
repository_name='repo',
|
||||
@@ -81,8 +79,6 @@ def test_make_rename_command_includes_dry_run():
|
||||
|
||||
|
||||
def test_make_rename_command_includes_remote_path():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_rename_command(
|
||||
dry_run=False,
|
||||
repository_name='repo',
|
||||
@@ -106,8 +102,6 @@ def test_make_rename_command_includes_remote_path():
|
||||
|
||||
|
||||
def test_make_rename_command_includes_umask():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_rename_command(
|
||||
dry_run=False,
|
||||
repository_name='repo',
|
||||
@@ -131,8 +125,6 @@ def test_make_rename_command_includes_umask():
|
||||
|
||||
|
||||
def test_make_rename_command_includes_log_json():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_rename_command(
|
||||
dry_run=False,
|
||||
repository_name='repo',
|
||||
@@ -148,8 +140,6 @@ def test_make_rename_command_includes_log_json():
|
||||
|
||||
|
||||
def test_make_rename_command_includes_lock_wait():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_rename_command(
|
||||
dry_run=False,
|
||||
repository_name='repo',
|
||||
@@ -173,8 +163,6 @@ def test_make_rename_command_includes_lock_wait():
|
||||
|
||||
|
||||
def test_make_rename_command_includes_extra_borg_options():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_rename_command(
|
||||
dry_run=False,
|
||||
repository_name='repo',
|
||||
|
||||
@@ -557,43 +557,6 @@ def test_log_outputs_with_unfinished_process_re_polls():
|
||||
)
|
||||
|
||||
|
||||
def test_log_outputs_includes_error_output_when_output_spans_multiple_chunks():
|
||||
flexmock(module.logger).should_receive('log')
|
||||
flexmock(module).should_receive('interpret_exit_code').and_return(module.Exit_status.ERROR)
|
||||
flexmock(module).should_receive('command_for_process').and_return('python')
|
||||
|
||||
process = subprocess.Popen(
|
||||
[
|
||||
sys.executable,
|
||||
'-c',
|
||||
(
|
||||
'import os, sys; '
|
||||
f'os.write(sys.stdout.fileno(), b"x" * {module.READ_CHUNK_SIZE + 10}); '
|
||||
'os.write(sys.stdout.fileno(), b"\\nERROR: critical failure"); '
|
||||
'os.close(1); '
|
||||
'os._exit(2)'
|
||||
),
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.STDOUT,
|
||||
)
|
||||
flexmock(module).should_receive('output_buffers_for_process').and_return((process.stdout,))
|
||||
|
||||
with pytest.raises(subprocess.CalledProcessError) as error:
|
||||
tuple(
|
||||
module.log_outputs(
|
||||
(process,),
|
||||
exclude_stdouts=(),
|
||||
output_log_level=logging.INFO,
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
)
|
||||
|
||||
assert error.value.output
|
||||
assert 'ERROR: critical failure' in error.value.output
|
||||
|
||||
|
||||
def test_read_lines_uses_system_locale_when_decoding_output():
|
||||
flexmock(module.locale).should_receive('getpreferredencoding').and_return('ISO-8859-1')
|
||||
process = subprocess.Popen(['echo', b'\xc4pple'], stdout=subprocess.PIPE)
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.actions.browse import archive as module
|
||||
|
||||
|
||||
def test_get_repository_archives_does_not_raise():
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(module.borgmatic.logger).should_receive('Log_prefix').and_return(flexmock())
|
||||
flexmock(module.borgmatic.borg.version).should_receive('local_borg_version').and_return('3.0')
|
||||
flexmock(module.borgmatic.borg.repo_list).should_receive('list_repository').and_return('{}')
|
||||
|
||||
assert module.get_repository_archives(config, config['repositories'][0]) == {}
|
||||
|
||||
|
||||
def test_get_archive_paths_returns_each_as_archive_path_with_metadata():
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(module.borgmatic.logger).should_receive('Log_prefix').and_return(flexmock())
|
||||
flexmock(module.borgmatic.borg.version).should_receive('local_borg_version').and_return('3.0')
|
||||
flexmock(module.borgmatic.borg.list).should_receive('capture_archive_listing').and_yield(
|
||||
{'path': 'foo.txt', 'type': '-', 'linktarget': ''},
|
||||
{'path': 'bar.txt', 'type': 'l', 'linktarget': 'foo.txt'},
|
||||
{'path': 'etc', 'type': 'd', 'linktarget': ''},
|
||||
)
|
||||
|
||||
assert tuple(module.get_archive_paths(config, config['repositories'][0], 'archive')) == (
|
||||
module.Archive_path('-', 'foo.txt', ''),
|
||||
module.Archive_path('l', 'bar.txt', 'foo.txt'),
|
||||
module.Archive_path('d', 'etc', ''),
|
||||
)
|
||||
|
||||
|
||||
def test_get_archive_file_content_with_binary_file_bails():
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(module.borgmatic.logger).should_receive('Log_prefix').and_return(flexmock())
|
||||
flexmock(module.borgmatic.borg.version).should_receive('local_borg_version').and_return('3.0')
|
||||
flexmock(module.borgmatic.borg.extract).should_receive('extract_archive').and_return(
|
||||
flexmock(stdout=flexmock(readlines=lambda hint: [b'foo\n', b'bar\n'])),
|
||||
)
|
||||
flexmock(module.binaryornot.helpers).should_receive('is_binary_string').and_return(True)
|
||||
|
||||
assert (
|
||||
module.get_archive_file_content(config, config['repositories'][0], 'archive', 'etc/foo.txt')
|
||||
is None
|
||||
)
|
||||
|
||||
|
||||
def test_get_archive_file_content_decodes_content():
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(module.borgmatic.logger).should_receive('Log_prefix').and_return(flexmock())
|
||||
flexmock(module.borgmatic.borg.version).should_receive('local_borg_version').and_return('3.0')
|
||||
flexmock(module.borgmatic.borg.extract).should_receive('extract_archive').and_return(
|
||||
flexmock(stdout=flexmock(readlines=lambda hint: [b'foo\n', b'bar\n'])),
|
||||
)
|
||||
flexmock(module.binaryornot.helpers).should_receive('is_binary_string').and_return(False)
|
||||
|
||||
assert (
|
||||
module.get_archive_file_content(config, config['repositories'][0], 'archive', 'etc/foo.txt')
|
||||
== 'foo\nbar\n'
|
||||
)
|
||||
|
||||
|
||||
def test_get_archive_file_content_with_large_file_truncates_content():
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(module.borgmatic.logger).should_receive('Log_prefix').and_return(flexmock())
|
||||
flexmock(module.borgmatic.borg.version).should_receive('local_borg_version').and_return('3.0')
|
||||
flexmock(module).READLINES_HINT_BYTES = 3
|
||||
flexmock(module.borgmatic.borg.extract).should_receive('extract_archive').and_return(
|
||||
flexmock(stdout=flexmock(readlines=lambda hint: [b'foo\n', b'bar\n'])),
|
||||
)
|
||||
flexmock(module.binaryornot.helpers).should_receive('is_binary_string').and_return(False)
|
||||
|
||||
assert (
|
||||
module.get_archive_file_content(config, config['repositories'][0], 'archive', 'etc/foo.txt')
|
||||
== f'foo\nbar\n\n{module.TRUNCATION_MESSAGE}'
|
||||
)
|
||||
|
||||
|
||||
def test_get_archive_file_content_with_unicode_decode_error_does_not_raise():
|
||||
config = {'repositories': [{'path': 'test.borg'}]}
|
||||
flexmock(module.borgmatic.logger).should_receive('Log_prefix').and_return(flexmock())
|
||||
flexmock(module.borgmatic.borg.version).should_receive('local_borg_version').and_return('3.0')
|
||||
flexmock(module.borgmatic.borg.extract).should_receive('extract_archive').and_return(
|
||||
flexmock(stdout=flexmock(readlines=lambda hint: [b'foo\n', b'\xc3\n'])),
|
||||
)
|
||||
flexmock(module.binaryornot.helpers).should_receive('is_binary_string').and_return(False)
|
||||
|
||||
assert (
|
||||
module.get_archive_file_content(config, config['repositories'][0], 'archive', 'etc/foo.txt')
|
||||
is None
|
||||
)
|
||||
@@ -1,94 +0,0 @@
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.actions.browse import directory_list as module
|
||||
|
||||
|
||||
def test_get_relative_archive_path_components_strips_off_current_directory():
|
||||
assert module.get_relative_archive_path_components(
|
||||
flexmock(file_path='foo/bar/baz/quux.txt'), ('foo', 'bar')
|
||||
) == ('baz', 'quux.txt')
|
||||
|
||||
|
||||
def test_get_relative_archive_path_components_with_root_current_directory_strips_off_nothing():
|
||||
assert module.get_relative_archive_path_components(
|
||||
flexmock(file_path='foo/bar/baz/quux.txt'), ()
|
||||
) == ('foo', 'bar', 'baz', 'quux.txt')
|
||||
|
||||
|
||||
def test_get_relative_archive_path_components_with_non_matching_paths_returns_none():
|
||||
assert (
|
||||
module.get_relative_archive_path_components(
|
||||
flexmock(file_path='foo/bar/baz/quux.txt'), ('etc',)
|
||||
)
|
||||
is None
|
||||
)
|
||||
|
||||
|
||||
def test_make_directory_list_option_with_file_path_makes_file_option():
|
||||
flexmock(module.textual.widgets.option_list).should_receive('Option').replace_with(flexmock)
|
||||
|
||||
option = module.make_directory_list_option(
|
||||
flexmock(path_type='-', file_path='foo/bar/baz.txt', link_target=''), ('baz.txt',)
|
||||
)
|
||||
|
||||
assert option.prompt == '📄 baz.txt'
|
||||
assert option.id == 'baz.txt'
|
||||
|
||||
|
||||
def test_make_directory_list_option_with_directory_path_makes_directory_option():
|
||||
flexmock(module.textual.widgets.option_list).should_receive('Option').replace_with(flexmock)
|
||||
|
||||
option = module.make_directory_list_option(
|
||||
flexmock(path_type='d', file_path='foo/bar/baz', link_target=''), ('baz',)
|
||||
)
|
||||
|
||||
assert option.prompt == '📁 baz'
|
||||
assert option.id == 'baz'
|
||||
|
||||
|
||||
def test_make_directory_list_option_with_contained_file_path_makes_directory_option():
|
||||
flexmock(module.textual.widgets.option_list).should_receive('Option').replace_with(flexmock)
|
||||
|
||||
option = module.make_directory_list_option(
|
||||
flexmock(path_type='d', file_path='foo/bar/baz.txt', link_target=''),
|
||||
(
|
||||
'bar',
|
||||
'baz.txt',
|
||||
),
|
||||
)
|
||||
|
||||
assert option.prompt == '📁 bar'
|
||||
assert option.id == 'bar'
|
||||
|
||||
|
||||
def test_make_directory_list_option_with_link_path_makes_link_option():
|
||||
flexmock(module.textual.widgets.option_list).should_receive('Option').replace_with(flexmock)
|
||||
|
||||
option = module.make_directory_list_option(
|
||||
flexmock(path_type='l', file_path='foo/bar/baz.txt', link_target='quux.txt'), ('baz.txt',)
|
||||
)
|
||||
|
||||
assert option.prompt == '🔗 baz.txt → quux.txt'
|
||||
assert option.id == 'baz.txt'
|
||||
|
||||
|
||||
def test_make_directory_list_option_with_pipe_path_makes_pipe_option():
|
||||
flexmock(module.textual.widgets.option_list).should_receive('Option').replace_with(flexmock)
|
||||
|
||||
option = module.make_directory_list_option(
|
||||
flexmock(path_type='p', file_path='foo/bar/baz.txt', link_target=''), ('baz.txt',)
|
||||
)
|
||||
|
||||
assert option.prompt == '🚰 baz.txt'
|
||||
assert option.id == 'baz.txt'
|
||||
|
||||
|
||||
def test_make_directory_list_option_with_unknown_path_makes_unknown_option():
|
||||
flexmock(module.textual.widgets.option_list).should_receive('Option').replace_with(flexmock)
|
||||
|
||||
option = module.make_directory_list_option(
|
||||
flexmock(path_type='wtf', file_path='foo/bar/baz.txt', link_target=''), ('baz.txt',)
|
||||
)
|
||||
|
||||
assert option.prompt == '❓ baz.txt'
|
||||
assert option.id == 'baz.txt'
|
||||
@@ -1,87 +0,0 @@
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.actions.browse import logs as module
|
||||
|
||||
|
||||
def test_rich_color_formatter_format_colors_log_record_based_on_level():
|
||||
formatted = module.Rich_color_formatter().format(
|
||||
module.logging.makeLogRecord(
|
||||
dict(
|
||||
levelno=module.logging.ERROR,
|
||||
levelname='ERROR',
|
||||
msg='oh no',
|
||||
)
|
||||
),
|
||||
)
|
||||
|
||||
assert formatted == '[bright_red]oh no[/bright_red]'
|
||||
|
||||
|
||||
def test_rich_color_formatter_format_includes_prefix():
|
||||
formatter = module.Rich_color_formatter()
|
||||
formatter.prefix = 'sup'
|
||||
formatted = formatter.format(
|
||||
module.logging.makeLogRecord(
|
||||
dict(
|
||||
levelno=module.logging.ERROR,
|
||||
levelname='ERROR',
|
||||
msg='oh no',
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
assert formatted == '[bright_red]sup: oh no[/bright_red]'
|
||||
|
||||
|
||||
def test_browse_log_handler_emit_from_worker_thread_calls_write_in_main_thread():
|
||||
flexmock(module.textual.worker).should_receive('get_current_worker')
|
||||
logs_widget = flexmock(write=lambda message: None, app=flexmock())
|
||||
flexmock(logs_widget.app).should_receive('call_from_thread').with_args(
|
||||
logs_widget.write, 'hi'
|
||||
).once()
|
||||
|
||||
module.Browse_log_handler(logs_widget).emit(
|
||||
module.logging.makeLogRecord(
|
||||
dict(
|
||||
levelno=module.logging.DEBUG,
|
||||
levelname='DEBUG',
|
||||
msg='hi',
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def test_browse_log_handler_emit_from_main_thread_calls_write_directly():
|
||||
flexmock(module.textual.worker).should_receive('get_current_worker').and_raise(RuntimeError)
|
||||
logs_widget = flexmock(write=lambda message: None, app=flexmock())
|
||||
flexmock(logs_widget.app).should_receive('call_from_thread').never()
|
||||
flexmock(logs_widget).should_receive('write').with_args('hi').once()
|
||||
|
||||
module.Browse_log_handler(logs_widget).emit(
|
||||
module.logging.makeLogRecord(
|
||||
dict(
|
||||
levelno=module.logging.DEBUG,
|
||||
levelname='DEBUG',
|
||||
msg='hi',
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def test_browse_log_handler_emit_from_main_thread_with_no_active_app_does_not_raise():
|
||||
flexmock(module.textual.worker).should_receive('get_current_worker').and_raise(RuntimeError)
|
||||
logs_widget = flexmock(write=lambda message: None, app=flexmock())
|
||||
flexmock(logs_widget.app).should_receive('call_from_thread').never()
|
||||
flexmock(logs_widget).should_receive('write').with_args('hi').and_raise(
|
||||
module.textual._context.NoActiveAppError
|
||||
)
|
||||
|
||||
module.Browse_log_handler(logs_widget).emit(
|
||||
module.logging.makeLogRecord(
|
||||
dict(
|
||||
levelno=module.logging.DEBUG,
|
||||
levelname='DEBUG',
|
||||
msg='hi',
|
||||
),
|
||||
),
|
||||
)
|
||||
@@ -1,29 +0,0 @@
|
||||
from flexmock import flexmock
|
||||
|
||||
import borgmatic.actions.browse.app
|
||||
from borgmatic.actions.browse import run as module
|
||||
|
||||
|
||||
def test_run_browse_without_configs_bails():
|
||||
app = flexmock()
|
||||
app.should_receive('run').never()
|
||||
|
||||
flexmock(borgmatic.actions.browse.app).should_receive('Browse_app').and_return(app)
|
||||
|
||||
module.run_browse(
|
||||
diff_arguments=flexmock(),
|
||||
global_arguments=flexmock(),
|
||||
configs=(),
|
||||
)
|
||||
|
||||
|
||||
def test_run_browse_with_configs_does_not_raise():
|
||||
flexmock(borgmatic.actions.browse.app).should_receive('Browse_app').and_return(
|
||||
flexmock(run=lambda: None)
|
||||
)
|
||||
|
||||
module.run_browse(
|
||||
diff_arguments=flexmock(),
|
||||
global_arguments=flexmock(),
|
||||
configs=(flexmock(), flexmock()),
|
||||
)
|
||||
@@ -1,126 +0,0 @@
|
||||
import pytest
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.actions.browse import workers as module
|
||||
|
||||
|
||||
def test_add_repository_archives_publishes_for_each_archive():
|
||||
flexmock(module.borgmatic.actions.browse.archive).should_receive(
|
||||
'get_repository_archives'
|
||||
).and_return({'archives': [{'archive': 'foo'}, {'archive': 'bar'}]})
|
||||
archive_loaded = flexmock()
|
||||
archive_loaded.should_receive('publish').with_args('bar').once() # Reversed order.
|
||||
archive_loaded.should_receive('publish').with_args('foo').once()
|
||||
archive_loaded.should_receive('publish').with_args(module.LOADING_DONE).once()
|
||||
|
||||
module.add_repository_archives.__wrapped__(
|
||||
browse_app=flexmock(),
|
||||
archive_loaded=archive_loaded,
|
||||
config=flexmock(),
|
||||
repository=flexmock(),
|
||||
)
|
||||
|
||||
|
||||
def test_record_path_sets_file_path_in_filesystem_hierarchy():
|
||||
archive_path = flexmock(path_type='-', file_path='foo/bar/baz.txt')
|
||||
quux_path = flexmock()
|
||||
hierarchy = {'foo': {'bar': {'quux.txt': quux_path}, 'empty': {}}}
|
||||
|
||||
module.record_path(
|
||||
archive_path=archive_path, hierarchy=hierarchy, path_components=('foo', 'bar', 'baz.txt')
|
||||
)
|
||||
|
||||
assert hierarchy == {
|
||||
'foo': {'bar': {'quux.txt': quux_path, 'baz.txt': archive_path}, 'empty': {}}
|
||||
}
|
||||
|
||||
|
||||
def test_record_path_sets_directory_path_in_filesystem_hierarchy():
|
||||
archive_path = flexmock(path_type='d', file_path='foo/bar/baz')
|
||||
quux_path = flexmock()
|
||||
hierarchy = {'foo': {'bar': {'quux.txt': quux_path}, 'empty': {}}}
|
||||
|
||||
module.record_path(
|
||||
archive_path=archive_path, hierarchy=hierarchy, path_components=('foo', 'bar', 'baz')
|
||||
)
|
||||
|
||||
assert hierarchy == {'foo': {'bar': {'quux.txt': quux_path, 'baz': {}}, 'empty': {}}}
|
||||
|
||||
|
||||
def test_get_paths_lists_directory_contents():
|
||||
baz_path = module.borgmatic.actions.browse.archive.Archive_path('-', 'foo/bar/baz.txt', '')
|
||||
hierarchy = {'foo': {'bar': {'baz.txt': baz_path, 'other': {}}}, 'nope': {}}
|
||||
|
||||
assert tuple(module.get_paths(hierarchy, ('foo', 'bar'))) == (
|
||||
baz_path,
|
||||
module.borgmatic.actions.browse.archive.Archive_path('d', 'foo/bar/other', ''),
|
||||
)
|
||||
|
||||
|
||||
def test_get_paths_with_full_path_components_lists_directory_contents():
|
||||
baz_path = module.borgmatic.actions.browse.archive.Archive_path('-', 'etc/foo/bar/baz.txt', '')
|
||||
hierarchy = {'foo': {'bar': {'baz.txt': baz_path, 'other': {}}}, 'nope': {}}
|
||||
|
||||
assert tuple(module.get_paths(hierarchy, ('foo', 'bar'), ('etc', 'foo', 'bar'))) == (
|
||||
baz_path,
|
||||
module.borgmatic.actions.browse.archive.Archive_path('d', 'etc/foo/bar/other', ''),
|
||||
)
|
||||
|
||||
|
||||
def test_get_paths_lists_empty_directory_contents():
|
||||
baz_path = module.borgmatic.actions.browse.archive.Archive_path('-', 'etc/foo/bar/baz.txt', '')
|
||||
hierarchy = {'foo': {'bar': {'baz.txt': baz_path, 'other': {}}}, 'nope': {}}
|
||||
|
||||
assert (
|
||||
tuple(module.get_paths(hierarchy, ('foo', 'bar', 'other'), ('etc', 'foo', 'bar', 'other')))
|
||||
== ()
|
||||
)
|
||||
|
||||
|
||||
def test_get_paths_with_unknown_file_raises():
|
||||
hierarchy = {'foo': {'other': {}}}
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
tuple(module.get_paths(hierarchy, ('foo', 'bar.txt')))
|
||||
|
||||
|
||||
def test_get_paths_with_unknown_directory_raises():
|
||||
hierarchy = {'foo': {'other': {}}}
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
tuple(module.get_paths(hierarchy, ('foo', 'bar', 'baz')))
|
||||
|
||||
|
||||
def test_load_archive_paths_publishes_for_each_archive_path():
|
||||
flexmock(module.borgmatic.actions.browse.archive).should_receive('get_archive_paths').and_yield(
|
||||
'foo.txt', 'bar.txt'
|
||||
)
|
||||
path_loaded = flexmock()
|
||||
path_loaded.should_receive('publish').with_args('foo.txt').once()
|
||||
path_loaded.should_receive('publish').with_args('bar.txt').once()
|
||||
path_loaded.should_receive('publish').with_args(module.LOADING_DONE).once()
|
||||
|
||||
module.load_archive_paths.__wrapped__(
|
||||
browse_app=flexmock(),
|
||||
path_loaded=path_loaded,
|
||||
config=flexmock(),
|
||||
repository=flexmock(),
|
||||
archive_name='archive',
|
||||
)
|
||||
|
||||
|
||||
def test_load_file_preview_publishes_file_contents():
|
||||
flexmock(module.borgmatic.actions.browse.archive).should_receive(
|
||||
'get_archive_file_content'
|
||||
).and_return('hi')
|
||||
file_preview_loaded = flexmock()
|
||||
file_preview_loaded.should_receive('publish').with_args('hi').once()
|
||||
|
||||
module.load_file_preview.__wrapped__(
|
||||
browse_app=flexmock(),
|
||||
file_preview_loaded=file_preview_loaded,
|
||||
config=flexmock(),
|
||||
repository=flexmock(),
|
||||
archive_name='archive',
|
||||
file_path='foo/bar/baz.txt',
|
||||
)
|
||||
@@ -171,6 +171,7 @@ def test_run_bootstrap_does_not_raise():
|
||||
flexmock(module.borgmatic.borg.repo_list).should_receive('resolve_archive_name').and_return(
|
||||
'archive',
|
||||
)
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('repo')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
|
||||
flexmock(),
|
||||
)
|
||||
@@ -222,6 +223,7 @@ def test_run_bootstrap_translates_ssh_command_argument_to_config():
|
||||
local_path='borg7',
|
||||
remote_path='borg8',
|
||||
).and_return('archive')
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('repo')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
|
||||
flexmock(),
|
||||
)
|
||||
|
||||
@@ -1838,7 +1838,7 @@ def test_spot_check_without_any_source_paths_errors():
|
||||
|
||||
def test_run_check_checks_archives_for_configured_repository():
|
||||
flexmock(module.logger).answer = lambda message: None
|
||||
flexmock(module.borgmatic.borg.check).should_receive('get_repository_id').and_return(flexmock())
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module).should_receive('upgrade_check_times')
|
||||
flexmock(module).should_receive('parse_checks')
|
||||
flexmock(module.borgmatic.borg.check).should_receive('make_archive_filter_flags').and_return(())
|
||||
@@ -1873,7 +1873,7 @@ def test_run_check_checks_archives_for_configured_repository():
|
||||
|
||||
def test_run_check_runs_configured_extract_check():
|
||||
flexmock(module.logger).answer = lambda message: None
|
||||
flexmock(module.borgmatic.borg.check).should_receive('get_repository_id').and_return(flexmock())
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module).should_receive('upgrade_check_times')
|
||||
flexmock(module).should_receive('parse_checks')
|
||||
flexmock(module.borgmatic.borg.check).should_receive('make_archive_filter_flags').and_return(())
|
||||
@@ -1906,7 +1906,7 @@ def test_run_check_runs_configured_extract_check():
|
||||
|
||||
def test_run_check_runs_configured_spot_check():
|
||||
flexmock(module.logger).answer = lambda message: None
|
||||
flexmock(module.borgmatic.borg.check).should_receive('get_repository_id').and_return(flexmock())
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module).should_receive('upgrade_check_times')
|
||||
flexmock(module).should_receive('parse_checks')
|
||||
flexmock(module.borgmatic.borg.check).should_receive('make_archive_filter_flags').and_return(())
|
||||
@@ -1942,7 +1942,7 @@ def test_run_check_runs_configured_spot_check():
|
||||
|
||||
def test_run_check_without_checks_runs_nothing_except_hooks():
|
||||
flexmock(module.logger).answer = lambda message: None
|
||||
flexmock(module.borgmatic.borg.check).should_receive('get_repository_id').and_return(flexmock())
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module).should_receive('upgrade_check_times')
|
||||
flexmock(module).should_receive('parse_checks')
|
||||
flexmock(module.borgmatic.borg.check).should_receive('make_archive_filter_flags').and_return(())
|
||||
|
||||
@@ -11,6 +11,7 @@ from borgmatic.actions import create as module
|
||||
|
||||
def test_run_create_executes_and_calls_hooks_for_configured_repository():
|
||||
flexmock(module.logger).answer = lambda message: None
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
|
||||
flexmock(),
|
||||
)
|
||||
@@ -49,6 +50,7 @@ def test_run_create_executes_and_calls_hooks_for_configured_repository():
|
||||
|
||||
def test_run_create_with_both_list_and_json_errors():
|
||||
flexmock(module.logger).answer = lambda message: None
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').never()
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').never()
|
||||
flexmock(module.borgmatic.borg.create).should_receive('create_archive').never()
|
||||
create_arguments = flexmock(
|
||||
@@ -80,6 +82,7 @@ def test_run_create_with_both_list_and_json_errors():
|
||||
|
||||
def test_run_create_with_both_list_and_progress_errors():
|
||||
flexmock(module.logger).answer = lambda message: None
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').never()
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').never()
|
||||
flexmock(module.borgmatic.borg.create).should_receive('create_archive').never()
|
||||
create_arguments = flexmock(
|
||||
@@ -111,6 +114,7 @@ def test_run_create_with_both_list_and_progress_errors():
|
||||
|
||||
def test_run_create_produces_json():
|
||||
flexmock(module.logger).answer = lambda message: None
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
|
||||
flexmock(),
|
||||
)
|
||||
@@ -156,6 +160,7 @@ def test_run_create_with_active_dumps_roundtrips_via_checkpoint_archive():
|
||||
mock_dump_process.should_receive('poll').and_return(None).and_return(0)
|
||||
|
||||
flexmock(module.logger).answer = lambda message: None
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
|
||||
flexmock(),
|
||||
)
|
||||
@@ -234,6 +239,7 @@ def test_run_create_with_active_dumps_json_updates_archive_info():
|
||||
}
|
||||
|
||||
flexmock(module.logger).answer = lambda message: None
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
|
||||
flexmock(),
|
||||
)
|
||||
@@ -316,6 +322,7 @@ def mock_dump_cleanup(config, borgmatic_runtime_directory, patterns, dry_run):
|
||||
|
||||
def test_run_create_with_active_dumps_removes_data_source_dumps_with_original_patterns():
|
||||
flexmock(module.logger).answer = lambda message: None
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
|
||||
flexmock(),
|
||||
)
|
||||
|
||||
@@ -1175,6 +1175,7 @@ def test_run_restore_restores_each_data_source():
|
||||
}
|
||||
|
||||
borgmatic_runtime_directory = flexmock()
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
|
||||
borgmatic_runtime_directory,
|
||||
)
|
||||
@@ -1249,6 +1250,7 @@ def test_run_restore_restores_data_source_by_falling_back_to_all_name():
|
||||
}
|
||||
|
||||
borgmatic_runtime_directory = flexmock()
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
|
||||
borgmatic_runtime_directory,
|
||||
)
|
||||
@@ -1311,6 +1313,7 @@ def test_run_restore_restores_data_source_configured_with_all_name():
|
||||
}
|
||||
|
||||
borgmatic_runtime_directory = flexmock()
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
|
||||
borgmatic_runtime_directory,
|
||||
)
|
||||
@@ -1395,6 +1398,7 @@ def test_run_restore_skips_missing_data_source():
|
||||
}
|
||||
|
||||
borgmatic_runtime_directory = flexmock()
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
|
||||
borgmatic_runtime_directory,
|
||||
)
|
||||
@@ -1479,6 +1483,7 @@ def test_run_restore_restores_data_sources_from_different_hooks():
|
||||
}
|
||||
|
||||
borgmatic_runtime_directory = flexmock()
|
||||
flexmock(module.borgmatic.borg.repo_info).should_receive('get_repository_id').and_return('id')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
|
||||
borgmatic_runtime_directory,
|
||||
)
|
||||
|
||||
@@ -22,7 +22,6 @@ def test_run_arbitrary_borg_calls_borg_with_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.run_arbitrary_borg(
|
||||
repository_path='repo',
|
||||
@@ -100,7 +99,6 @@ def test_run_arbitrary_borg_with_lock_wait_calls_borg_with_lock_wait_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.run_arbitrary_borg(
|
||||
repository_path='repo',
|
||||
@@ -125,7 +123,6 @@ def test_run_arbitrary_borg_with_archive_calls_borg_with_archive_flag():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.run_arbitrary_borg(
|
||||
repository_path='repo',
|
||||
@@ -151,7 +148,6 @@ def test_run_arbitrary_borg_with_local_path_calls_borg_via_local_path():
|
||||
borg_local_path='borg1',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.run_arbitrary_borg(
|
||||
repository_path='repo',
|
||||
@@ -178,7 +174,6 @@ def test_run_arbitrary_borg_with_exit_codes_calls_borg_using_them():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=borg_exit_codes,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.run_arbitrary_borg(
|
||||
repository_path='repo',
|
||||
@@ -205,7 +200,6 @@ def test_run_arbitrary_borg_with_remote_path_calls_borg_with_remote_path_flags()
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.run_arbitrary_borg(
|
||||
repository_path='repo',
|
||||
@@ -233,7 +227,6 @@ def test_run_arbitrary_borg_with_remote_path_injection_attack_gets_escaped():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.run_arbitrary_borg(
|
||||
repository_path='repo',
|
||||
@@ -259,7 +252,6 @@ def test_run_arbitrary_borg_passes_borg_specific_flags_to_borg():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.run_arbitrary_borg(
|
||||
repository_path='repo',
|
||||
@@ -284,7 +276,6 @@ def test_run_arbitrary_borg_omits_dash_dash_in_flags_passed_to_borg():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.run_arbitrary_borg(
|
||||
repository_path='repo',
|
||||
@@ -309,7 +300,6 @@ def test_run_arbitrary_borg_without_borg_specific_flags_does_not_raise():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.run_arbitrary_borg(
|
||||
repository_path='repo',
|
||||
@@ -386,7 +376,6 @@ def test_run_arbitrary_borg_calls_borg_with_working_directory():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.run_arbitrary_borg(
|
||||
repository_path='repo',
|
||||
|
||||
@@ -24,7 +24,6 @@ def insert_execute_command_mock(command, working_directory=None, borg_exit_codes
|
||||
def test_break_lock_calls_borg_with_required_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'break-lock', '--log-json', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.break_lock(
|
||||
repository_path='repo',
|
||||
@@ -37,7 +36,6 @@ def test_break_lock_calls_borg_with_required_flags():
|
||||
def test_break_lock_calls_borg_with_local_path():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg1', 'break-lock', '--log-json', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.break_lock(
|
||||
repository_path='repo',
|
||||
@@ -51,7 +49,6 @@ def test_break_lock_calls_borg_with_local_path():
|
||||
def test_break_lock_calls_borg_using_exit_codes():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg1', 'break-lock', '--log-json', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.break_lock(
|
||||
repository_path='repo',
|
||||
@@ -67,7 +64,6 @@ def test_break_lock_calls_borg_with_remote_path_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'break-lock', '--remote-path', 'borg1', '--log-json', 'repo')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.break_lock(
|
||||
repository_path='repo',
|
||||
@@ -81,7 +77,6 @@ def test_break_lock_calls_borg_with_remote_path_flags():
|
||||
def test_break_lock_calls_borg_with_umask_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'break-lock', '--umask', '0770', '--log-json', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.break_lock(
|
||||
repository_path='repo',
|
||||
@@ -94,7 +89,6 @@ def test_break_lock_calls_borg_with_umask_flags():
|
||||
def test_break_lock_calls_borg_with_lock_wait_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'break-lock', '--log-json', '--lock-wait', '5', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.break_lock(
|
||||
repository_path='repo',
|
||||
@@ -109,7 +103,6 @@ def test_break_lock_calls_borg_with_extra_borg_options():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'break-lock', '--log-json', '--extra', 'value with space', 'repo')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.break_lock(
|
||||
repository_path='repo',
|
||||
@@ -152,7 +145,6 @@ def test_break_lock_calls_borg_with_working_directory():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'break-lock', '--log-json', 'repo'), working_directory='/working/dir'
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.break_lock(
|
||||
repository_path='repo',
|
||||
|
||||
@@ -35,7 +35,6 @@ def insert_execute_command_mock(
|
||||
def test_change_passphrase_calls_borg_with_required_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'key', 'change-passphrase', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.change_passphrase(
|
||||
repository_path='repo',
|
||||
@@ -49,7 +48,6 @@ def test_change_passphrase_calls_borg_with_required_flags():
|
||||
def test_change_passphrase_calls_borg_with_local_path():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg1', 'key', 'change-passphrase', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.change_passphrase(
|
||||
repository_path='repo',
|
||||
@@ -70,7 +68,6 @@ def test_change_passphrase_calls_borg_using_exit_codes():
|
||||
config=config,
|
||||
borg_exit_codes=borg_exit_codes,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.change_passphrase(
|
||||
repository_path='repo',
|
||||
@@ -86,7 +83,6 @@ def test_change_passphrase_calls_borg_with_remote_path_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'key', 'change-passphrase', '--remote-path', 'borg1', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.change_passphrase(
|
||||
repository_path='repo',
|
||||
@@ -105,7 +101,6 @@ def test_change_passphrase_calls_borg_with_umask_flags():
|
||||
('borg', 'key', 'change-passphrase', '--umask', '0770', 'repo'),
|
||||
config=config,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.change_passphrase(
|
||||
repository_path='repo',
|
||||
@@ -123,7 +118,6 @@ def test_change_passphrase_calls_borg_with_lock_wait_flags():
|
||||
('borg', 'key', 'change-passphrase', '--lock-wait', '5', 'repo'),
|
||||
config=config,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.change_passphrase(
|
||||
repository_path='repo',
|
||||
@@ -141,7 +135,6 @@ def test_change_passphrase_calls_borg_with_extra_borg_options():
|
||||
('borg', 'key', 'change-passphrase', '--extra', 'value with space', 'repo'),
|
||||
config=config,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.change_passphrase(
|
||||
repository_path='repo',
|
||||
@@ -186,7 +179,6 @@ def test_change_passphrase_with_dry_run_skips_borg_call():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.execute).should_receive('execute_command').never()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.change_passphrase(
|
||||
repository_path='repo',
|
||||
@@ -203,7 +195,6 @@ def test_change_passphrase_calls_borg_without_passphrase():
|
||||
('borg', 'key', 'change-passphrase', 'repo'),
|
||||
config={'option': 'foo'},
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.change_passphrase(
|
||||
repository_path='repo',
|
||||
@@ -226,7 +217,6 @@ def test_change_passphrase_calls_borg_with_working_directory():
|
||||
config=config,
|
||||
working_directory='/working/dir',
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.change_passphrase(
|
||||
repository_path='repo',
|
||||
|
||||
@@ -272,54 +272,6 @@ def test_make_check_name_flags_with_extract_omits_extract_flag():
|
||||
assert flags == ()
|
||||
|
||||
|
||||
def test_get_repository_id_with_valid_json_does_not_raise():
|
||||
config = {}
|
||||
flexmock(module.repo_info).should_receive('display_repository_info').and_return(
|
||||
'{"repository": {"id": "repo"}}',
|
||||
)
|
||||
|
||||
assert module.get_repository_id(
|
||||
repository_path='repo',
|
||||
config=config,
|
||||
local_borg_version='1.2.3',
|
||||
global_arguments=flexmock(),
|
||||
local_path='borg',
|
||||
remote_path=None,
|
||||
)
|
||||
|
||||
|
||||
def test_get_repository_id_with_json_error_raises():
|
||||
config = {}
|
||||
flexmock(module.repo_info).should_receive('display_repository_info').and_return(
|
||||
'{"unexpected": {"id": "repo"}}',
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.get_repository_id(
|
||||
repository_path='repo',
|
||||
config=config,
|
||||
local_borg_version='1.2.3',
|
||||
global_arguments=flexmock(),
|
||||
local_path='borg',
|
||||
remote_path=None,
|
||||
)
|
||||
|
||||
|
||||
def test_get_repository_id_with_missing_json_keys_raises():
|
||||
config = {}
|
||||
flexmock(module.repo_info).should_receive('display_repository_info').and_return('{invalid JSON')
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.get_repository_id(
|
||||
repository_path='repo',
|
||||
config=config,
|
||||
local_borg_version='1.2.3',
|
||||
global_arguments=flexmock(),
|
||||
local_path='borg',
|
||||
remote_path=None,
|
||||
)
|
||||
|
||||
|
||||
def test_check_archives_with_progress_passes_through_to_borg():
|
||||
config = {'progress': True}
|
||||
flexmock(module).should_receive('make_check_name_flags').with_args(
|
||||
@@ -337,7 +289,6 @@ def test_check_archives_with_progress_passes_through_to_borg():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=[{'code': 1, 'treat_as': 'error'}],
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -374,7 +325,6 @@ def test_check_archives_with_log_json_and_progress_passes_through_both_to_borg()
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=[{'code': 1, 'treat_as': 'error'}],
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -411,7 +361,6 @@ def test_check_archives_with_repair_passes_through_to_borg():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=[{'code': 1, 'treat_as': 'error'}],
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -448,7 +397,6 @@ def test_check_archives_with_log_json_and_repair_passes_through_both_to_borg():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=[{'code': 1, 'treat_as': 'error'}],
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -485,7 +433,6 @@ def test_check_archives_with_max_duration_flag_passes_through_to_borg():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=[{'code': 1, 'treat_as': 'error'}],
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -522,7 +469,6 @@ def test_check_archives_with_max_duration_option_passes_through_to_borg():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=[{'code': 1, 'treat_as': 'error'}],
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -556,7 +502,6 @@ def test_check_archives_with_max_duration_option_and_archives_check_runs_reposit
|
||||
insert_execute_command_mock(
|
||||
('borg', 'check', '--max-duration', '33', '--repository-only', '--log-json', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -590,7 +535,6 @@ def test_check_archives_with_max_duration_flag_and_archives_check_runs_repositor
|
||||
insert_execute_command_mock(
|
||||
('borg', 'check', '--max-duration', '33', '--repository-only', '--log-json', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -627,7 +571,6 @@ def test_check_archives_with_max_duration_option_and_data_check_runs_repository_
|
||||
insert_execute_command_mock(
|
||||
('borg', 'check', '--max-duration', '33', '--repository-only', '--log-json', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -664,7 +607,6 @@ def test_check_archives_with_max_duration_flag_and_data_check_runs_repository_ch
|
||||
insert_execute_command_mock(
|
||||
('borg', 'check', '--max-duration', '33', '--repository-only', '--log-json', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -701,7 +643,6 @@ def test_check_archives_with_max_duration_flag_overrides_max_duration_option():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=[{'code': 1, 'treat_as': 'error'}],
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -735,7 +676,6 @@ def test_check_archives_calls_borg_with_parameters(checks):
|
||||
flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'check', '--log-json', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -763,7 +703,6 @@ def test_check_archives_with_data_check_implies_archives_check_calls_borg_with_p
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'check', '--log-json', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -790,8 +729,8 @@ def test_check_archives_with_log_info_passes_through_to_borg():
|
||||
(),
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'check', '--log-json', '--info', 'repo'))
|
||||
insert_logging_mock(logging.INFO)
|
||||
insert_execute_command_mock(('borg', 'check', '--log-json', '--info', 'repo'))
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -818,8 +757,8 @@ def test_check_archives_with_log_debug_passes_through_to_borg():
|
||||
(),
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'check', '--log-json', '--debug', '--show-rc', 'repo'))
|
||||
insert_logging_mock(logging.DEBUG)
|
||||
insert_execute_command_mock(('borg', 'check', '--log-json', '--debug', '--show-rc', 'repo'))
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -845,7 +784,6 @@ def test_check_archives_with_local_path_calls_borg_via_local_path():
|
||||
flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg1', 'check', '--log-json', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -875,7 +813,6 @@ def test_check_archives_with_exit_codes_calls_borg_using_them():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'check', '--log-json', 'repo'), borg_exit_codes=borg_exit_codes
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -901,7 +838,6 @@ def test_check_archives_with_remote_path_passes_through_to_borg():
|
||||
flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'check', '--remote-path', 'borg1', '--log-json', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -928,7 +864,6 @@ def test_check_archives_with_umask_passes_through_to_borg():
|
||||
flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'check', '--umask', '077', '--log-json', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -954,7 +889,6 @@ def test_check_archives_with_lock_wait_passes_through_to_borg():
|
||||
flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'check', '--log-json', '--lock-wait', '5', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -981,7 +915,6 @@ def test_check_archives_with_retention_prefix():
|
||||
flexmock(module).should_receive('make_check_name_flags').with_args(checks, ()).and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'check', '--log-json', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -1011,7 +944,6 @@ def test_check_archives_with_extra_borg_options_passes_through_to_borg():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'check', '--log-json', '--extra', '--options', 'value with space', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -1048,7 +980,6 @@ def test_check_archives_with_match_archives_passes_through_to_borg():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=[{'code': 1, 'treat_as': 'error'}],
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
@@ -1080,7 +1011,6 @@ def test_check_archives_calls_borg_with_working_directory():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'check', '--log-json', 'repo'), working_directory='/working/dir'
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.check_archives(
|
||||
repository_path='repo',
|
||||
|
||||
@@ -33,7 +33,6 @@ COMPACT_COMMAND = ('borg', 'compact')
|
||||
def test_compact_segments_calls_borg_with_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock((*COMPACT_COMMAND, '--log-json', 'repo'), logging.INFO)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
dry_run=False,
|
||||
@@ -84,7 +83,6 @@ def test_compact_segments_with_dry_run_skips_borg_call_when_feature_unavailable(
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').never()
|
||||
flexmock(module).should_receive('execute_command').never()
|
||||
flexmock(module.logger).should_receive('info').with_args('Skipping compact (dry run)').once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
repository_path='repo',
|
||||
@@ -104,7 +102,6 @@ def test_compact_segments_with_dry_run_executes_borg_call_when_feature_available
|
||||
flexmock(module.environment).should_receive('make_environment').once()
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').once()
|
||||
flexmock(module).should_receive('execute_command').once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
repository_path='repo',
|
||||
@@ -118,7 +115,6 @@ def test_compact_segments_with_dry_run_executes_borg_call_when_feature_available
|
||||
def test_compact_segments_with_local_path_calls_borg_via_local_path():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg1', *COMPACT_COMMAND[1:], '--log-json', 'repo'), logging.INFO)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
dry_run=False,
|
||||
@@ -138,7 +134,6 @@ def test_compact_segments_with_exit_codes_calls_borg_using_them():
|
||||
logging.INFO,
|
||||
borg_exit_codes=borg_exit_codes,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
dry_run=False,
|
||||
@@ -154,7 +149,6 @@ def test_compact_segments_with_remote_path_calls_borg_with_remote_path_flags():
|
||||
insert_execute_command_mock(
|
||||
(*COMPACT_COMMAND, '--remote-path', 'borg1', '--log-json', 'repo'), logging.INFO
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
dry_run=False,
|
||||
@@ -169,7 +163,6 @@ def test_compact_segments_with_remote_path_calls_borg_with_remote_path_flags():
|
||||
def test_compact_segments_with_progress_calls_borg_with_progress_flag():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock((*COMPACT_COMMAND, '--progress', 'repo'), logging.INFO)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
dry_run=False,
|
||||
@@ -185,7 +178,6 @@ def test_compact_segments_with_log_json_and_progress_calls_borg_with_both_flags(
|
||||
insert_execute_command_mock(
|
||||
(*COMPACT_COMMAND, '--log-json', '--progress', 'repo'), logging.INFO
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
dry_run=False,
|
||||
@@ -201,7 +193,6 @@ def test_compact_segments_with_cleanup_commits_calls_borg_with_cleanup_commits_f
|
||||
insert_execute_command_mock(
|
||||
(*COMPACT_COMMAND, '--log-json', '--cleanup-commits', 'repo'), logging.INFO
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
dry_run=False,
|
||||
@@ -218,7 +209,6 @@ def test_compact_segments_with_threshold_calls_borg_with_threshold_flag():
|
||||
insert_execute_command_mock(
|
||||
(*COMPACT_COMMAND, '--log-json', '--threshold', '20', 'repo'), logging.INFO
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
dry_run=False,
|
||||
@@ -235,7 +225,6 @@ def test_compact_segments_with_umask_calls_borg_with_umask_flags():
|
||||
insert_execute_command_mock(
|
||||
(*COMPACT_COMMAND, '--umask', '077', '--log-json', 'repo'), logging.INFO
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
dry_run=False,
|
||||
@@ -252,7 +241,6 @@ def test_compact_segments_with_lock_wait_calls_borg_with_lock_wait_flags():
|
||||
insert_execute_command_mock(
|
||||
(*COMPACT_COMMAND, '--log-json', '--lock-wait', '5', 'repo'), logging.INFO
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
dry_run=False,
|
||||
@@ -269,7 +257,6 @@ def test_compact_segments_with_extra_borg_options_calls_borg_with_extra_options(
|
||||
(*COMPACT_COMMAND, '--log-json', '--extra', '--options', 'value with space', 'repo'),
|
||||
logging.INFO,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
dry_run=False,
|
||||
@@ -287,7 +274,6 @@ def test_compact_segments_calls_borg_with_working_directory():
|
||||
logging.INFO,
|
||||
working_directory='/working/dir',
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.compact_segments(
|
||||
dry_run=False,
|
||||
|
||||
@@ -1265,7 +1265,6 @@ def test_create_archive_calls_borg_with_flags():
|
||||
working_directory=None,
|
||||
environment=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.create_archive(
|
||||
dry_run=False,
|
||||
@@ -1300,7 +1299,6 @@ def test_create_archive_calls_borg_with_environment():
|
||||
working_directory=None,
|
||||
environment=environment,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.create_archive(
|
||||
dry_run=False,
|
||||
@@ -1479,44 +1477,6 @@ def test_create_archive_with_stats_and_dry_run_calls_borg_without_stats():
|
||||
'source_directories': ['foo', 'bar'],
|
||||
'repositories': ['repo'],
|
||||
'exclude_patterns': None,
|
||||
'statistics': True,
|
||||
},
|
||||
patterns=[Pattern('foo'), Pattern('bar')],
|
||||
local_borg_version='1.2.3',
|
||||
global_arguments=flexmock(),
|
||||
borgmatic_runtime_directory='/borgmatic/run',
|
||||
)
|
||||
|
||||
|
||||
def test_create_archive_with_quick_stats_and_dry_run_calls_borg_without_quick_stats():
|
||||
# --dry-run and --quick-stats are mutually exclusive, see:
|
||||
# https://borgbackup.readthedocs.io/en/stable/usage/create.html#description
|
||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||
flexmock(module).should_receive('make_base_create_command').and_return(
|
||||
(('borg', 'create', '--dry-run'), REPO_ARCHIVE, flexmock()),
|
||||
)
|
||||
flexmock(module.environment).should_receive('make_environment')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module).should_receive('execute_command').with_args(
|
||||
('borg', 'create', '--dry-run', '--info', *REPO_ARCHIVE),
|
||||
output_log_level=logging.INFO,
|
||||
output_file=None,
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
working_directory=None,
|
||||
environment=None,
|
||||
)
|
||||
insert_logging_mock(logging.INFO)
|
||||
|
||||
module.create_archive(
|
||||
dry_run=True,
|
||||
repository_path='repo',
|
||||
config={
|
||||
'source_directories': ['foo', 'bar'],
|
||||
'repositories': ['repo'],
|
||||
'exclude_patterns': None,
|
||||
'quick_statistics': True,
|
||||
},
|
||||
patterns=[Pattern('foo'), Pattern('bar')],
|
||||
local_borg_version='1.2.3',
|
||||
@@ -1544,7 +1504,6 @@ def test_create_archive_with_working_directory_calls_borg_with_working_directory
|
||||
working_directory='/working/dir',
|
||||
environment=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.create_archive(
|
||||
dry_run=False,
|
||||
@@ -1580,7 +1539,6 @@ def test_create_archive_with_exit_codes_calls_borg_using_them():
|
||||
working_directory=None,
|
||||
environment=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.create_archive(
|
||||
dry_run=False,
|
||||
@@ -1615,7 +1573,6 @@ def test_create_archive_with_stats_calls_borg_with_stats_flag_and_answer_output_
|
||||
working_directory=None,
|
||||
environment=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.create_archive(
|
||||
dry_run=False,
|
||||
@@ -1654,7 +1611,6 @@ def test_create_archive_with_files_calls_borg_with_answer_output_log_level():
|
||||
working_directory=None,
|
||||
environment=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.create_archive(
|
||||
dry_run=False,
|
||||
@@ -1724,7 +1680,6 @@ def test_create_archive_with_progress_calls_borg_with_progress_flag():
|
||||
working_directory=None,
|
||||
environment=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.create_archive(
|
||||
dry_run=False,
|
||||
@@ -1776,7 +1731,6 @@ def test_create_archive_with_progress_and_stream_processes_calls_borg_with_progr
|
||||
working_directory=None,
|
||||
environment=None,
|
||||
).and_yield()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.create_archive(
|
||||
dry_run=False,
|
||||
@@ -1810,7 +1764,6 @@ def test_create_archive_with_json_calls_borg_with_json_flag():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).and_yield('[]')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
json_output = module.create_archive(
|
||||
dry_run=False,
|
||||
@@ -1845,7 +1798,6 @@ def test_create_archive_with_stats_and_json_calls_borg_without_stats_flag():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).and_yield('[]')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
json_output = module.create_archive(
|
||||
dry_run=False,
|
||||
@@ -1854,42 +1806,6 @@ def test_create_archive_with_stats_and_json_calls_borg_without_stats_flag():
|
||||
'source_directories': ['foo*'],
|
||||
'repositories': ['repo'],
|
||||
'exclude_patterns': None,
|
||||
'statistics': True,
|
||||
},
|
||||
patterns=[Pattern('foo'), Pattern('bar')],
|
||||
local_borg_version='1.2.3',
|
||||
global_arguments=flexmock(),
|
||||
borgmatic_runtime_directory='/borgmatic/run',
|
||||
json=True,
|
||||
)
|
||||
|
||||
assert json_output == '[]'
|
||||
|
||||
|
||||
def test_create_archive_with_quick_stats_and_json_calls_borg_without_quick_stats_flag():
|
||||
flexmock(module.borgmatic.logger).should_receive('add_custom_log_levels')
|
||||
flexmock(module.logging).ANSWER = module.borgmatic.logger.ANSWER
|
||||
flexmock(module).should_receive('make_base_create_command').and_return(
|
||||
(('borg', 'create'), REPO_ARCHIVE, flexmock()),
|
||||
)
|
||||
flexmock(module.environment).should_receive('make_environment')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module).should_receive('execute_command_and_capture_output').with_args(
|
||||
('borg', 'create', '--json', *REPO_ARCHIVE),
|
||||
working_directory=None,
|
||||
environment=None,
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).and_yield('[]')
|
||||
|
||||
json_output = module.create_archive(
|
||||
dry_run=False,
|
||||
repository_path='repo',
|
||||
config={
|
||||
'source_directories': ['foo*'],
|
||||
'repositories': ['repo'],
|
||||
'exclude_patterns': None,
|
||||
'quick_statistics': True,
|
||||
},
|
||||
patterns=[Pattern('foo'), Pattern('bar')],
|
||||
local_borg_version='1.2.3',
|
||||
@@ -1918,7 +1834,6 @@ def test_create_archive_with_comment_calls_borg_with_comment_flag():
|
||||
working_directory=None,
|
||||
environment=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.create_archive(
|
||||
dry_run=False,
|
||||
@@ -1956,7 +1871,6 @@ def test_create_archive_calls_borg_with_working_directory():
|
||||
working_directory='/working/dir',
|
||||
environment=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.create_archive(
|
||||
dry_run=False,
|
||||
|
||||
@@ -9,13 +9,13 @@ from ..test_verbosity import insert_logging_mock
|
||||
|
||||
|
||||
def test_make_delete_command_includes_log_info():
|
||||
insert_logging_mock(logging.INFO)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
|
||||
('repo',),
|
||||
)
|
||||
insert_logging_mock(logging.INFO)
|
||||
|
||||
command = module.make_delete_command(
|
||||
repository={'path': 'repo'},
|
||||
@@ -31,13 +31,13 @@ def test_make_delete_command_includes_log_info():
|
||||
|
||||
|
||||
def test_make_delete_command_includes_log_debug():
|
||||
insert_logging_mock(logging.DEBUG)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_match_archives_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
|
||||
('repo',),
|
||||
)
|
||||
insert_logging_mock(logging.DEBUG)
|
||||
|
||||
command = module.make_delete_command(
|
||||
repository={'path': 'repo'},
|
||||
@@ -63,7 +63,6 @@ def test_make_delete_command_includes_dry_run():
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
|
||||
('repo',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_delete_command(
|
||||
repository={'path': 'repo'},
|
||||
@@ -89,7 +88,6 @@ def test_make_delete_command_includes_remote_path():
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
|
||||
('repo',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_delete_command(
|
||||
repository={'path': 'repo'},
|
||||
@@ -113,7 +111,6 @@ def test_make_delete_command_includes_umask():
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
|
||||
('repo',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_delete_command(
|
||||
repository={'path': 'repo'},
|
||||
@@ -139,7 +136,6 @@ def test_make_delete_command_includes_lock_wait():
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
|
||||
('repo',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_delete_command(
|
||||
repository={'path': 'repo'},
|
||||
@@ -161,7 +157,6 @@ def test_make_delete_command_includes_extra_borg_options():
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
|
||||
('repo',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_delete_command(
|
||||
repository={'path': 'repo'},
|
||||
@@ -187,7 +182,6 @@ def test_make_delete_command_with_list_config_calls_borg_with_list_flag():
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
|
||||
('repo',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_delete_command(
|
||||
repository={'path': 'repo'},
|
||||
@@ -209,7 +203,6 @@ def test_make_delete_command_includes_force():
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
|
||||
('repo',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_delete_command(
|
||||
repository={'path': 'repo'},
|
||||
@@ -231,7 +224,6 @@ def test_make_delete_command_includes_force_twice():
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
|
||||
('repo',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_delete_command(
|
||||
repository={'path': 'repo'},
|
||||
@@ -255,7 +247,6 @@ def test_make_delete_command_includes_archive():
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
|
||||
('repo',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_delete_command(
|
||||
repository={'path': 'repo'},
|
||||
@@ -284,7 +275,6 @@ def test_make_delete_command_includes_match_archives():
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').and_return(
|
||||
('repo',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_delete_command(
|
||||
repository={'path': 'repo'},
|
||||
@@ -317,7 +307,6 @@ def test_delete_archives_with_archive_calls_borg_delete():
|
||||
)
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.execute).should_receive('execute_command').once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.delete_archives(
|
||||
repository={'path': 'repo'},
|
||||
@@ -338,7 +327,6 @@ def test_delete_archives_with_match_archives_calls_borg_delete():
|
||||
)
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.execute).should_receive('execute_command').once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.delete_archives(
|
||||
repository={'path': 'repo'},
|
||||
@@ -360,7 +348,6 @@ def test_delete_archives_with_archive_related_argument_calls_borg_delete(argumen
|
||||
)
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.execute).should_receive('execute_command').once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.delete_archives(
|
||||
repository={'path': 'repo'},
|
||||
@@ -380,7 +367,6 @@ def test_delete_archives_without_archive_related_argument_calls_borg_repo_delete
|
||||
flexmock(module.borgmatic.borg.environment).should_receive('make_environment').never()
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.execute).should_receive('execute_command').never()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.delete_archives(
|
||||
repository={'path': 'repo'},
|
||||
@@ -417,7 +403,6 @@ def test_delete_archives_calls_borg_delete_with_working_directory():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.delete_archives(
|
||||
repository={'path': 'repo'},
|
||||
|
||||
@@ -4,8 +4,6 @@ from flexmock import flexmock
|
||||
|
||||
from borgmatic.borg import diff as module
|
||||
|
||||
from ..test_verbosity import insert_logging_mock
|
||||
|
||||
LOGGING_ANSWER = flexmock()
|
||||
|
||||
|
||||
@@ -42,7 +40,6 @@ def test_diff_calls_borg_with_archives():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -97,7 +94,6 @@ def test_diff_with_local_path_calls_borg_with_it():
|
||||
borg_local_path='borg6',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -154,7 +150,6 @@ def test_diff_with_remote_path_calls_borg_with_it():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -211,7 +206,6 @@ def test_diff_with_lock_wait_calls_borg_with_it():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -268,7 +262,6 @@ def test_diff_with_log_level_info_calls_borg_with_info_flag():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -326,7 +319,6 @@ def test_diff_with_log_level_debug_calls_borg_with_debug_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -384,7 +376,6 @@ def test_diff_with_only_patterns_calls_borg_with_configured_pattern_paths():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -443,7 +434,6 @@ def test_diff_with_exclude_config_calls_borg_with_exclude_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -499,7 +489,6 @@ def test_diff_with_numeric_ids_calls_borg_with_numeric_ids_flag():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -560,7 +549,6 @@ def test_diff_with_numeric_ids_and_feature_not_available_calls_borg_with_numeric
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -616,7 +604,6 @@ def test_diff_with_same_chunker_params_calls_borg_with_it():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -673,7 +660,6 @@ def test_diff_with_sort_keys_calls_borg_with_formatted_sort_by_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -729,7 +715,6 @@ def test_diff_with_content_only_calls_borg_with_it():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -786,7 +771,6 @@ def test_diff_with_extra_borg_options_calls_borg_with_them():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
@@ -844,7 +828,6 @@ def test_diff_without_separate_repository_archive_feature_available_calls_borg_j
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.borgmatic.borg.diff.diff(
|
||||
repository='repo',
|
||||
|
||||
@@ -36,7 +36,6 @@ def test_export_key_calls_borg_with_required_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'export', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -51,7 +50,6 @@ def test_export_key_calls_borg_with_local_path():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg1', 'key', 'export', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -68,7 +66,6 @@ def test_export_key_calls_borg_using_exit_codes():
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
borg_exit_codes = flexmock()
|
||||
insert_execute_command_mock(('borg', 'key', 'export', 'repo'), borg_exit_codes=borg_exit_codes)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -83,7 +80,6 @@ def test_export_key_calls_borg_with_remote_path_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'export', '--remote-path', 'borg1', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -99,7 +95,6 @@ def test_export_key_calls_borg_with_umask_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'export', '--umask', '0770', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -114,7 +109,6 @@ def test_export_key_calls_borg_with_lock_wait_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'export', '--lock-wait', '5', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -129,7 +123,6 @@ def test_export_key_calls_borg_with_extra_borg_options():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'export', '--extra', 'value with space', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -174,7 +167,6 @@ def test_export_key_calls_borg_with_paper_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'export', '--paper', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -189,7 +181,6 @@ def test_export_key_calls_borg_with_paper_flag():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'export', '--paper', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -204,7 +195,6 @@ def test_export_key_calls_borg_with_qr_html_flag():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'export', '--qr-html', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -221,7 +211,6 @@ def test_export_key_calls_borg_with_path_argument():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'key', 'export', '--log-json', 'repo', 'dest'), output_file=None
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -251,7 +240,6 @@ def test_export_key_with_stdout_path_calls_borg_without_path_argument():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'export', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -280,7 +268,6 @@ def test_export_key_calls_borg_with_working_directory():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'export', 'repo'), working_directory='/working/dir')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
@@ -301,7 +288,6 @@ def test_export_key_calls_borg_with_path_argument_and_working_directory():
|
||||
output_file=None,
|
||||
working_directory='/working/dir',
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_key(
|
||||
repository_path='repo',
|
||||
|
||||
@@ -39,7 +39,6 @@ def test_export_tar_archive_calls_borg_with_path_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'export-tar', '--log-json', 'repo::archive', 'test.tar', 'path1', 'path2'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
@@ -63,7 +62,6 @@ def test_export_tar_archive_calls_borg_with_local_path_flags():
|
||||
('borg1', 'export-tar', '--log-json', 'repo::archive', 'test.tar'),
|
||||
borg_local_path='borg1',
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
@@ -89,7 +87,6 @@ def test_export_tar_archive_calls_borg_using_exit_codes():
|
||||
('borg', 'export-tar', '--log-json', 'repo::archive', 'test.tar'),
|
||||
borg_exit_codes=borg_exit_codes,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
@@ -112,7 +109,6 @@ def test_export_tar_archive_calls_borg_with_remote_path_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'export-tar', '--remote-path', 'borg1', '--log-json', 'repo::archive', 'test.tar'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
@@ -136,7 +132,6 @@ def test_export_tar_archive_calls_borg_with_umask_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'export-tar', '--umask', '0770', '--log-json', 'repo::archive', 'test.tar'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
@@ -159,7 +154,6 @@ def test_export_tar_archive_calls_borg_with_lock_wait_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'export-tar', '--log-json', '--lock-wait', '5', 'repo::archive', 'test.tar'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
@@ -190,7 +184,6 @@ def test_export_tar_archive_calls_borg_with_extra_borg_options():
|
||||
'test.tar',
|
||||
),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
@@ -279,7 +272,6 @@ def test_export_tar_archive_calls_borg_with_tar_filter_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'export-tar', '--log-json', '--tar-filter', 'bzip2', 'repo::archive', 'test.tar'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
@@ -304,7 +296,6 @@ def test_export_tar_archive_calls_borg_with_list_flag():
|
||||
('borg', 'export-tar', '--log-json', '--list', 'repo::archive', 'test.tar'),
|
||||
output_log_level=logging.ANSWER,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
@@ -335,7 +326,6 @@ def test_export_tar_archive_calls_borg_with_strip_components_flag():
|
||||
'test.tar',
|
||||
),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
@@ -359,7 +349,6 @@ def test_export_tar_archive_skips_abspath_for_remote_repository_flag():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'export-tar', '--log-json', 'server:repo::archive', 'test.tar')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
@@ -380,7 +369,6 @@ def test_export_tar_archive_calls_borg_with_stdout_destination_path():
|
||||
('repo::archive',),
|
||||
)
|
||||
insert_execute_command_mock(('borg', 'export-tar', 'repo::archive', '-'), capture=False)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
@@ -404,7 +392,6 @@ def test_export_tar_archive_calls_borg_with_working_directory():
|
||||
('borg', 'export-tar', '--log-json', 'repo::archive', 'test.tar'),
|
||||
working_directory='/working/dir',
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.export_tar_archive(
|
||||
dry_run=False,
|
||||
|
||||
@@ -25,7 +25,6 @@ def test_extract_last_archive_dry_run_calls_borg_with_last_archive():
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
('repo::archive',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_last_archive_dry_run(
|
||||
config={},
|
||||
@@ -39,7 +38,6 @@ def test_extract_last_archive_dry_run_calls_borg_with_last_archive():
|
||||
def test_extract_last_archive_dry_run_without_any_archives_should_not_raise():
|
||||
flexmock(module.repo_list).should_receive('resolve_archive_name').and_raise(ValueError)
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_last_archive_dry_run(
|
||||
config={},
|
||||
@@ -55,10 +53,10 @@ def test_extract_last_archive_dry_run_with_log_info_calls_borg_with_info_paramet
|
||||
insert_execute_command_mock(
|
||||
('borg', 'extract', '--dry-run', '--log-json', '--info', 'repo::archive')
|
||||
)
|
||||
insert_logging_mock(logging.INFO)
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
('repo::archive',),
|
||||
)
|
||||
insert_logging_mock(logging.INFO)
|
||||
|
||||
module.extract_last_archive_dry_run(
|
||||
config={},
|
||||
@@ -83,10 +81,10 @@ def test_extract_last_archive_dry_run_with_log_debug_calls_borg_with_debug_param
|
||||
'repo::archive',
|
||||
),
|
||||
)
|
||||
insert_logging_mock(logging.DEBUG)
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
('repo::archive',),
|
||||
)
|
||||
insert_logging_mock(logging.DEBUG)
|
||||
|
||||
module.extract_last_archive_dry_run(
|
||||
config={},
|
||||
@@ -111,7 +109,6 @@ def test_extract_last_archive_dry_run_calls_borg_with_progress_flag():
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
('repo::archive',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_last_archive_dry_run(
|
||||
config={'progress': True},
|
||||
@@ -128,7 +125,6 @@ def test_extract_last_archive_dry_run_calls_borg_via_local_path():
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
('repo::archive',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_last_archive_dry_run(
|
||||
config={},
|
||||
@@ -150,7 +146,6 @@ def test_extract_last_archive_dry_run_calls_borg_using_exit_codes():
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
('repo::archive',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_last_archive_dry_run(
|
||||
config={'borg_exit_codes': borg_exit_codes},
|
||||
@@ -169,7 +164,6 @@ def test_extract_last_archive_dry_run_calls_borg_with_remote_path_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
('repo::archive',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_last_archive_dry_run(
|
||||
config={},
|
||||
@@ -189,7 +183,6 @@ def test_extract_last_archive_dry_run_calls_borg_with_lock_wait_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
('repo::archive',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_last_archive_dry_run(
|
||||
config={},
|
||||
@@ -216,7 +209,6 @@ def test_extract_last_archive_dry_run_calls_borg_with_extra_borg_options():
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
('repo::archive',),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_last_archive_dry_run(
|
||||
config={'extra_borg_options': {'extract': '--extra "value with space"'}},
|
||||
@@ -239,7 +231,6 @@ def test_extract_archive_calls_borg_with_path_flags():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -263,7 +254,6 @@ def test_extract_archive_calls_borg_with_local_path():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -292,7 +282,6 @@ def test_extract_archive_calls_borg_with_exit_codes():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -318,7 +307,6 @@ def test_extract_archive_calls_borg_with_remote_path_flags():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -350,7 +338,6 @@ def test_extract_archive_calls_borg_with_numeric_ids_parameter(feature_available
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -376,7 +363,6 @@ def test_extract_archive_calls_borg_with_umask_flags():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -402,7 +388,6 @@ def test_extract_archive_calls_borg_with_lock_wait_flags():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -428,7 +413,6 @@ def test_extract_archive_calls_borg_with_extra_borg_options():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -444,6 +428,7 @@ def test_extract_archive_calls_borg_with_extra_borg_options():
|
||||
def test_extract_archive_with_log_info_calls_borg_with_info_parameter():
|
||||
flexmock(module.os.path).should_receive('abspath').and_return('repo')
|
||||
insert_execute_command_mock(('borg', 'extract', '--log-json', '--info', 'repo::archive'))
|
||||
insert_logging_mock(logging.INFO)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
@@ -452,7 +437,6 @@ def test_extract_archive_with_log_info_calls_borg_with_info_parameter():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.INFO)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -470,6 +454,7 @@ def test_extract_archive_with_log_debug_calls_borg_with_debug_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'extract', '--log-json', '--debug', '--list', '--show-rc', 'repo::archive'),
|
||||
)
|
||||
insert_logging_mock(logging.DEBUG)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
@@ -478,7 +463,6 @@ def test_extract_archive_with_log_debug_calls_borg_with_debug_flags():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.DEBUG)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -502,7 +486,6 @@ def test_extract_archive_calls_borg_with_dry_run_parameter():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=True,
|
||||
@@ -528,7 +511,6 @@ def test_extract_archive_calls_borg_with_destination_path():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -555,7 +537,6 @@ def test_extract_archive_calls_borg_with_strip_components():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -591,7 +572,6 @@ def test_extract_archive_calls_borg_with_strip_components_calculated_from_all():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -627,7 +607,6 @@ def test_extract_archive_calls_borg_with_strip_components_calculated_from_all_wi
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -652,7 +631,6 @@ def test_extract_archive_with_strip_components_all_and_no_paths_raises():
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
flexmock(module).should_receive('execute_command').never()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.extract_archive(
|
||||
@@ -687,7 +665,6 @@ def test_extract_archive_calls_borg_with_progress_flag():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -720,7 +697,6 @@ def test_extract_archive_with_log_json_and_progress_calls_borg_with_both_flags()
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -755,7 +731,6 @@ def test_extract_archive_calls_borg_with_extract_to_stdout_returns_process():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.extract_archive(
|
||||
@@ -794,7 +769,6 @@ def test_extract_archive_with_progress_and_extract_to_stdout_ignores_progress():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.extract_archive(
|
||||
@@ -830,7 +804,6 @@ def test_extract_archive_skips_abspath_for_remote_repository():
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).and_return('repo')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -856,7 +829,6 @@ def test_extract_archive_uses_configured_working_directory_in_repo_path_and_dest
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).with_args('repo', '/working/dir').and_return('/working/dir/repo').once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
@@ -880,7 +852,6 @@ def test_extract_archive_uses_configured_working_directory_in_repo_path_when_des
|
||||
flexmock(module.borgmatic.config.validate).should_receive(
|
||||
'normalize_repository_path',
|
||||
).with_args('repo', '/working/dir').and_return('/working/dir/repo').once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.extract_archive(
|
||||
dry_run=False,
|
||||
|
||||
@@ -32,7 +32,6 @@ def test_import_key_calls_borg_with_required_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'import', '--log-json', 'repo', '-'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.import_key(
|
||||
repository_path='repo',
|
||||
@@ -48,7 +47,6 @@ def test_import_key_calls_borg_with_local_path():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg1', 'key', 'import', '--log-json', 'repo', '-'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.import_key(
|
||||
repository_path='repo',
|
||||
@@ -68,7 +66,6 @@ def test_import_key_calls_borg_using_exit_codes():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'key', 'import', '--log-json', 'repo', '-'), borg_exit_codes=borg_exit_codes
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.import_key(
|
||||
repository_path='repo',
|
||||
@@ -86,7 +83,6 @@ def test_import_key_calls_borg_with_remote_path_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'key', 'import', '--remote-path', 'borg1', '--log-json', 'repo', '-')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.import_key(
|
||||
repository_path='repo',
|
||||
@@ -105,7 +101,6 @@ def test_import_key_calls_borg_with_umask_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'key', 'import', '--umask', '0770', '--log-json', 'repo', '-')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.import_key(
|
||||
repository_path='repo',
|
||||
@@ -123,7 +118,6 @@ def test_import_key_calls_borg_with_lock_wait_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'key', 'import', '--log-json', '--lock-wait', '5', 'repo', '-')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.import_key(
|
||||
repository_path='repo',
|
||||
@@ -141,7 +135,6 @@ def test_import_key_calls_borg_with_extra_borg_options():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'key', 'import', '--log-json', '--extra', 'value with space', 'repo', '-')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.import_key(
|
||||
repository_path='repo',
|
||||
@@ -191,7 +184,6 @@ def test_import_key_calls_borg_with_paper_flags():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'import', '--log-json', '--paper', 'repo', '-'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.import_key(
|
||||
repository_path='repo',
|
||||
@@ -209,7 +201,6 @@ def test_import_key_calls_borg_with_path_argument():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'key', 'import', '--log-json', 'repo', 'source'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.import_key(
|
||||
repository_path='repo',
|
||||
@@ -241,7 +232,6 @@ def test_import_key_with_stdin_path_calls_borg_without_path_argument():
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
flexmock(module.os.path).should_receive('exists').never()
|
||||
insert_execute_command_mock(('borg', 'key', 'import', '--log-json', 'repo', '-'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.import_key(
|
||||
repository_path='repo',
|
||||
@@ -274,7 +264,6 @@ def test_import_key_calls_borg_with_working_directory():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'key', 'import', '--log-json', 'repo', '-'), working_directory='/working/dir'
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.import_key(
|
||||
repository_path='repo',
|
||||
@@ -295,7 +284,6 @@ def test_import_key_calls_borg_with_path_argument_and_working_directory():
|
||||
('borg', 'key', 'import', '--log-json', 'repo', 'source'),
|
||||
working_directory='/working/dir',
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.import_key(
|
||||
repository_path='repo',
|
||||
|
||||
@@ -17,7 +17,6 @@ def test_make_info_command_constructs_borg_info_command():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -113,7 +112,6 @@ def test_make_info_command_with_log_debug_and_json_omits_borg_logging_flags():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -137,7 +135,6 @@ def test_make_info_command_with_json_passes_through_to_command():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -161,7 +158,6 @@ def test_make_info_command_with_archive_uses_match_archives_flags():
|
||||
).and_return(('--match-archives', 'archive'))
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -193,7 +189,6 @@ def test_make_info_command_with_local_path_passes_through_to_command():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -221,7 +216,6 @@ def test_make_info_command_with_remote_path_passes_through_to_command():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -247,7 +241,6 @@ def test_make_info_command_with_umask_passes_through_to_command():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -275,7 +268,6 @@ def test_make_info_command_with_lock_wait_passes_through_to_command():
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
config = {'lock_wait': 5}
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -300,7 +292,6 @@ def test_make_info_command_with_extra_borg_options_passes_through_to_command():
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
config = {'extra_borg_options': {'info': '--extra "value with space"'}}
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -336,7 +327,6 @@ def test_make_info_command_transforms_prefix_into_match_archives_flags():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -372,7 +362,6 @@ def test_make_info_command_prefers_prefix_over_archive_name_format():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -404,7 +393,6 @@ def test_make_info_command_transforms_archive_name_format_into_match_archives_fl
|
||||
).and_return(('--match-archives', 'sh:bar-*'))
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -437,7 +425,6 @@ def test_make_info_command_with_match_archives_option_passes_through_to_command(
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
flexmock(module.environment).should_receive('make_environment')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -473,7 +460,6 @@ def test_make_info_command_with_match_archives_flag_passes_through_to_command():
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
flexmock(module.environment).should_receive('make_environment')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -510,7 +496,6 @@ def test_make_info_command_passes_arguments_through_to_command(argument_name):
|
||||
)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('--repo', 'repo'))
|
||||
flexmock(module.environment).should_receive('make_environment')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
@@ -552,7 +537,6 @@ def test_make_info_command_with_date_based_matching_passes_through_to_command():
|
||||
older='1m',
|
||||
oldest='1w',
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_info_command(
|
||||
repository_path='repo',
|
||||
|
||||
@@ -78,7 +78,6 @@ def test_make_list_command_includes_json_but_not_debug():
|
||||
|
||||
|
||||
def test_make_list_command_includes_json():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--json',))
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
@@ -95,7 +94,6 @@ def test_make_list_command_includes_json():
|
||||
|
||||
|
||||
def test_make_list_command_includes_lock_wait():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('make_flags').and_return(()).and_return(()).and_return(
|
||||
('--lock-wait', '5'),
|
||||
).and_return(())
|
||||
@@ -114,7 +112,6 @@ def test_make_list_command_includes_lock_wait():
|
||||
|
||||
|
||||
def test_make_list_command_includes_format():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('make_flags').and_return(()).and_return(()).and_return(
|
||||
()
|
||||
).and_return(('--format', 'stuff'))
|
||||
@@ -133,7 +130,6 @@ def test_make_list_command_includes_format():
|
||||
|
||||
|
||||
def test_make_list_command_includes_extra_borg_options():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
@@ -150,7 +146,6 @@ def test_make_list_command_includes_extra_borg_options():
|
||||
|
||||
|
||||
def test_make_list_command_includes_archive():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
@@ -169,7 +164,6 @@ def test_make_list_command_includes_archive():
|
||||
|
||||
|
||||
def test_make_list_command_includes_archive_and_path():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_archive_flags').and_return(
|
||||
@@ -188,7 +182,6 @@ def test_make_list_command_includes_archive_and_path():
|
||||
|
||||
|
||||
def test_make_list_command_includes_local_path():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
@@ -206,7 +199,6 @@ def test_make_list_command_includes_local_path():
|
||||
|
||||
|
||||
def test_make_list_command_includes_remote_path():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags').with_args(
|
||||
'remote-path',
|
||||
@@ -231,7 +223,6 @@ def test_make_list_command_includes_remote_path():
|
||||
|
||||
|
||||
def test_make_list_command_includes_umask():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('make_flags').replace_with(
|
||||
lambda name, value: (f'--{name}', value) if value else (),
|
||||
)
|
||||
@@ -250,7 +241,6 @@ def test_make_list_command_includes_umask():
|
||||
|
||||
|
||||
def test_make_list_command_includes_short():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--short',))
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
@@ -281,7 +271,6 @@ def test_make_list_command_includes_short():
|
||||
),
|
||||
)
|
||||
def test_make_list_command_includes_additional_flags(argument_name):
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(
|
||||
(f"--{argument_name.replace('_', '-')}", 'value'),
|
||||
|
||||
@@ -25,7 +25,6 @@ def test_mount_archive_calls_borg_with_required_flags():
|
||||
flexmock(module.feature).should_receive('available').and_return(False)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_execute_command_mock(('borg', 'mount', '--log-json', 'repo', '/mnt'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False)
|
||||
module.mount_archive(
|
||||
@@ -49,7 +48,6 @@ def test_mount_archive_with_borg_features_calls_borg_with_repository_and_match_a
|
||||
insert_execute_command_mock(
|
||||
('borg', 'mount', '--log-json', '--repo', 'repo', '--match-archives', 'archive', '/mnt'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False)
|
||||
module.mount_archive(
|
||||
@@ -68,7 +66,6 @@ def test_mount_archive_without_archive_calls_borg_with_repository_flags_only():
|
||||
('repo::archive',),
|
||||
)
|
||||
insert_execute_command_mock(('borg', 'mount', '--log-json', 'repo::archive', '/mnt'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False)
|
||||
module.mount_archive(
|
||||
@@ -89,7 +86,6 @@ def test_mount_archive_calls_borg_with_path_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'mount', '--log-json', 'repo::archive', '/mnt', 'path1', 'path2')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(
|
||||
mount_point='/mnt',
|
||||
@@ -113,7 +109,6 @@ def test_mount_archive_calls_borg_with_local_path():
|
||||
('repo::archive',),
|
||||
)
|
||||
insert_execute_command_mock(('borg1', 'mount', '--log-json', 'repo::archive', '/mnt'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False)
|
||||
module.mount_archive(
|
||||
@@ -137,7 +132,6 @@ def test_mount_archive_calls_borg_using_exit_codes():
|
||||
('borg', 'mount', '--log-json', 'repo::archive', '/mnt'),
|
||||
borg_exit_codes=borg_exit_codes,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False)
|
||||
module.mount_archive(
|
||||
@@ -158,7 +152,6 @@ def test_mount_archive_calls_borg_with_remote_path_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'mount', '--remote-path', 'borg1', '--log-json', 'repo::archive', '/mnt'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False)
|
||||
module.mount_archive(
|
||||
@@ -180,7 +173,6 @@ def test_mount_archive_calls_borg_with_umask_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'mount', '--umask', '0770', '--log-json', 'repo::archive', '/mnt')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False)
|
||||
module.mount_archive(
|
||||
@@ -201,7 +193,6 @@ def test_mount_archive_calls_borg_with_lock_wait_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'mount', '--log-json', '--lock-wait', '5', 'repo::archive', '/mnt')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False)
|
||||
module.mount_archive(
|
||||
@@ -222,7 +213,6 @@ def test_mount_archive_calls_borg_with_extra_borg_options():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'mount', '--log-json', '--extra', 'value with space', 'repo::archive', '/mnt')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False)
|
||||
module.mount_archive(
|
||||
@@ -290,7 +280,6 @@ def test_mount_archive_calls_borg_with_foreground_parameter():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=True)
|
||||
module.mount_archive(
|
||||
@@ -311,7 +300,6 @@ def test_mount_archive_calls_borg_with_options_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'mount', '--log-json', '-o', 'super_mount', 'repo::archive', '/mnt')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(
|
||||
mount_point='/mnt',
|
||||
@@ -373,7 +361,6 @@ def test_mount_archive_with_date_based_matching_calls_borg_with_date_based_flags
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(
|
||||
mount_point='/mnt',
|
||||
@@ -401,7 +388,6 @@ def test_mount_archive_calls_borg_with_working_directory():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'mount', '--log-json', 'repo', '/mnt'), working_directory='/working/dir'
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
mount_arguments = flexmock(mount_point='/mnt', options=None, paths=None, foreground=False)
|
||||
module.mount_archive(
|
||||
|
||||
@@ -244,7 +244,6 @@ def test_prune_archives_calls_borg_with_flags():
|
||||
'1.2.3',
|
||||
).and_return(False)
|
||||
insert_execute_command_mock((*PRUNE_COMMAND, 'repo'), logging.INFO)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(statistics=False, list_details=False)
|
||||
module.prune_archives(
|
||||
@@ -313,7 +312,6 @@ def test_prune_archives_with_dry_run_calls_borg_with_dry_run_flag():
|
||||
'1.2.3',
|
||||
).and_return(False)
|
||||
insert_execute_command_mock((*PRUNE_COMMAND, '--dry-run', 'repo'), logging.INFO)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(statistics=False, list_details=False)
|
||||
module.prune_archives(
|
||||
@@ -336,7 +334,6 @@ def test_prune_archives_with_local_path_calls_borg_via_local_path():
|
||||
'1.2.3',
|
||||
).and_return(False)
|
||||
insert_execute_command_mock(('borg1', *PRUNE_COMMAND[1:], 'repo'), logging.INFO)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(statistics=False, list_details=False)
|
||||
module.prune_archives(
|
||||
@@ -365,7 +362,6 @@ def test_prune_archives_with_exit_codes_calls_borg_using_them():
|
||||
logging.INFO,
|
||||
borg_exit_codes=borg_exit_codes,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(statistics=False, list_details=False)
|
||||
module.prune_archives(
|
||||
@@ -388,7 +384,6 @@ def test_prune_archives_with_remote_path_calls_borg_with_remote_path_flags():
|
||||
'1.2.3',
|
||||
).and_return(False)
|
||||
insert_execute_command_mock((*PRUNE_COMMAND, '--remote-path', 'borg1', 'repo'), logging.INFO)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(statistics=False, list_details=False)
|
||||
module.prune_archives(
|
||||
@@ -412,7 +407,6 @@ def test_prune_archives_with_stats_config_calls_borg_with_stats_flag():
|
||||
'1.2.3',
|
||||
).and_return(False)
|
||||
insert_execute_command_mock((*PRUNE_COMMAND, '--stats', 'repo'), module.borgmatic.logger.ANSWER)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(statistics=None, list_details=False)
|
||||
module.prune_archives(
|
||||
@@ -435,7 +429,6 @@ def test_prune_archives_with_list_config_calls_borg_with_list_flag():
|
||||
'1.2.3',
|
||||
).and_return(False)
|
||||
insert_execute_command_mock((*PRUNE_COMMAND, '--list', 'repo'), module.borgmatic.logger.ANSWER)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(statistics=False, list_details=None)
|
||||
module.prune_archives(
|
||||
@@ -459,7 +452,6 @@ def test_prune_archives_with_umask_calls_borg_with_umask_flags():
|
||||
'1.2.3',
|
||||
).and_return(False)
|
||||
insert_execute_command_mock((*PRUNE_COMMAND, '--umask', '077', 'repo'), logging.INFO)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(statistics=False, list_details=False)
|
||||
module.prune_archives(
|
||||
@@ -483,7 +475,6 @@ def test_prune_archives_with_lock_wait_calls_borg_with_lock_wait_flags():
|
||||
'1.2.3',
|
||||
).and_return(False)
|
||||
insert_execute_command_mock((*PRUNE_COMMAND, '--lock-wait', '5', 'repo'), logging.INFO)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(statistics=False, list_details=False)
|
||||
module.prune_archives(
|
||||
@@ -509,7 +500,6 @@ def test_prune_archives_with_extra_borg_options_calls_borg_with_extra_options():
|
||||
(*PRUNE_COMMAND, '--extra', '--options', 'value with space', 'repo'),
|
||||
logging.INFO,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(statistics=False, list_details=False)
|
||||
module.prune_archives(
|
||||
@@ -579,7 +569,6 @@ def test_prune_archives_with_date_based_matching_calls_borg_with_date_based_flag
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(
|
||||
statistics=False,
|
||||
@@ -613,7 +602,6 @@ def test_prune_archives_calls_borg_with_working_directory():
|
||||
logging.INFO,
|
||||
working_directory='/working/dir',
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(statistics=False, list_details=False)
|
||||
module.prune_archives(
|
||||
@@ -636,7 +624,6 @@ def test_prune_archives_calls_borg_without_stats_when_feature_is_not_available()
|
||||
'2.0.0b10',
|
||||
).and_return(True)
|
||||
insert_execute_command_mock((*PRUNE_COMMAND, 'repo'), logging.ANSWER)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
prune_arguments = flexmock(statistics=True, list_details=False)
|
||||
module.prune_archives(
|
||||
|
||||
@@ -35,7 +35,6 @@ def test_recreate_calls_borg_with_required_flags():
|
||||
),
|
||||
)
|
||||
insert_execute_command_mock(('borg', 'recreate', '--log-json', '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -71,7 +70,6 @@ def test_recreate_with_dry_run_calls_borg_with_dry_run_flag():
|
||||
),
|
||||
)
|
||||
insert_execute_command_mock(('borg', 'recreate', '--log-json', '--dry-run', '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -109,7 +107,6 @@ def test_recreate_with_remote_path():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--remote-path', 'borg1', '--log-json', '--repo', 'repo')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -147,7 +144,6 @@ def test_recreate_with_lock_wait():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--log-json', '--lock-wait', '5', '--repo', 'repo')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -184,7 +180,6 @@ def test_recreate_with_extra_borg_options():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--log-json', '--extra', 'value with space', '--repo', 'repo')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -219,6 +214,7 @@ def test_recreate_with_log_info():
|
||||
),
|
||||
)
|
||||
insert_execute_command_mock(('borg', 'recreate', '--log-json', '--info', '--repo', 'repo'))
|
||||
|
||||
insert_logging_mock(logging.INFO)
|
||||
|
||||
module.recreate_archive(
|
||||
@@ -295,7 +291,6 @@ def test_recreate_with_list_config_calls_borg_with_list_flag():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--log-json', '--list', '--filter', 'AME+-', '--repo', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -333,7 +328,6 @@ def test_recreate_with_patterns_from_flag():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--log-json', '--patterns-from', 'patterns_file', '--repo', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -372,7 +366,6 @@ def test_recreate_with_exclude_flags():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--log-json', '--exclude', 'pattern', '--repo', 'repo')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -409,7 +402,6 @@ def test_recreate_with_target_flag():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--log-json', '--target', 'new-archive', '--repo', 'repo')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -454,7 +446,6 @@ def test_recreate_with_comment_flag():
|
||||
'repo',
|
||||
),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -491,7 +482,6 @@ def test_recreate_with_timestamp_flag():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--log-json', '--timestamp', '2023-10-01T12:00:00', '--repo', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -528,7 +518,6 @@ def test_recreate_with_compression_flag():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--log-json', '--compression', 'lz4', '--repo', 'repo')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -565,7 +554,6 @@ def test_recreate_with_chunker_params_flag():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--log-json', '--chunker-params', '19,23,21,4095', '--repo', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -602,7 +590,6 @@ def test_recreate_with_recompress_flag():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--log-json', '--recompress', 'always', '--repo', 'repo')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -637,7 +624,6 @@ def test_recreate_with_match_archives_star():
|
||||
),
|
||||
)
|
||||
insert_execute_command_mock(('borg', 'recreate', '--log-json', '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -672,7 +658,6 @@ def test_recreate_with_match_archives_regex():
|
||||
),
|
||||
)
|
||||
insert_execute_command_mock(('borg', 'recreate', '--log-json', '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -707,7 +692,6 @@ def test_recreate_with_match_archives_shell():
|
||||
),
|
||||
)
|
||||
insert_execute_command_mock(('borg', 'recreate', '--log-json', '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -744,7 +728,6 @@ def test_recreate_with_match_archives_and_feature_available_calls_borg_with_matc
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--log-json', '--repo', 'repo', '--match-archives', 'foo-*')
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -781,7 +764,6 @@ def test_recreate_with_archives_flag_and_feature_available_calls_borg_with_match
|
||||
insert_execute_command_mock(
|
||||
('borg', 'recreate', '--log-json', '--repo', 'repo', '--match-archives', 'archive'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -812,7 +794,6 @@ def test_recreate_with_match_archives_and_feature_not_available_calls_borg_witho
|
||||
)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_archive_flags').never()
|
||||
insert_execute_command_mock(('borg', 'recreate', '--log-json', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
@@ -843,7 +824,6 @@ def test_recreate_with_archives_flags_and_feature_not_available_calls_borg_with_
|
||||
).and_return(('repo::archive',))
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_repository_flags').never()
|
||||
insert_execute_command_mock(('borg', 'recreate', '--log-json', 'repo::archive'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.recreate_archive(
|
||||
repository='repo',
|
||||
|
||||
@@ -50,7 +50,6 @@ def insert_repo_create_command_mock(
|
||||
def test_create_repository_calls_borg_with_flags():
|
||||
insert_repo_info_command_not_found_mock()
|
||||
insert_repo_create_command_mock((*REPO_CREATE_COMMAND, '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -178,7 +177,6 @@ def test_create_repository_with_source_repository_calls_borg_with_other_repo_fla
|
||||
insert_repo_create_command_mock(
|
||||
(*REPO_CREATE_COMMAND, '--other-repo', 'other.borg', '--repo', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -201,7 +199,6 @@ def test_create_repository_with_source_repository_calls_borg_with_other_repo_fla
|
||||
def test_create_repository_with_copy_crypt_key_calls_borg_with_copy_crypt_key_flag():
|
||||
insert_repo_info_command_not_found_mock()
|
||||
insert_repo_create_command_mock((*REPO_CREATE_COMMAND, '--copy-crypt-key', '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -224,7 +221,6 @@ def test_create_repository_with_copy_crypt_key_calls_borg_with_copy_crypt_key_fl
|
||||
def test_create_repository_with_append_only_calls_borg_with_append_only_flag():
|
||||
insert_repo_info_command_not_found_mock()
|
||||
insert_repo_create_command_mock((*REPO_CREATE_COMMAND, '--append-only', '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -247,7 +243,6 @@ def test_create_repository_with_append_only_calls_borg_with_append_only_flag():
|
||||
def test_create_repository_with_append_only_config_calls_borg_with_append_only_flag():
|
||||
insert_repo_info_command_not_found_mock()
|
||||
insert_repo_create_command_mock((*REPO_CREATE_COMMAND, '--append-only', '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -272,7 +267,6 @@ def test_create_repository_with_storage_quota_calls_borg_with_storage_quota_flag
|
||||
insert_repo_create_command_mock(
|
||||
(*REPO_CREATE_COMMAND, '--storage-quota', '5G', '--repo', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -295,7 +289,6 @@ def test_create_repository_with_storage_quota_calls_borg_with_storage_quota_flag
|
||||
def test_create_repository_with_make_parent_dirs_calls_borg_with_make_parent_dirs_flag():
|
||||
insert_repo_info_command_not_found_mock()
|
||||
insert_repo_create_command_mock((*REPO_CREATE_COMMAND, '--make-parent-dirs', '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -362,7 +355,6 @@ def test_create_repository_with_log_debug_calls_borg_with_debug_flag():
|
||||
def test_create_repository_with_lock_wait_calls_borg_with_lock_wait_flag():
|
||||
insert_repo_info_command_not_found_mock()
|
||||
insert_repo_create_command_mock((*REPO_CREATE_COMMAND, '--lock-wait', '5', '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -384,7 +376,6 @@ def test_create_repository_with_lock_wait_calls_borg_with_lock_wait_flag():
|
||||
def test_create_repository_with_local_path_calls_borg_via_local_path():
|
||||
insert_repo_info_command_not_found_mock()
|
||||
insert_repo_create_command_mock(('borg1', *REPO_CREATE_COMMAND[1:], '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -411,7 +402,6 @@ def test_create_repository_with_exit_codes_calls_borg_using_them():
|
||||
('borg', *REPO_CREATE_COMMAND[1:], '--repo', 'repo'),
|
||||
borg_exit_codes=borg_exit_codes,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -435,7 +425,6 @@ def test_create_repository_with_remote_path_calls_borg_with_remote_path_flag():
|
||||
insert_repo_create_command_mock(
|
||||
(*REPO_CREATE_COMMAND, '--remote-path', 'borg1', '--repo', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -458,7 +447,6 @@ def test_create_repository_with_remote_path_calls_borg_with_remote_path_flag():
|
||||
def test_create_repository_with_umask_calls_borg_with_umask_flag():
|
||||
insert_repo_info_command_not_found_mock()
|
||||
insert_repo_create_command_mock((*REPO_CREATE_COMMAND, '--umask', '077', '--repo', 'repo'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -482,7 +470,6 @@ def test_create_repository_calls_borg_with_extra_borg_options():
|
||||
insert_repo_create_command_mock(
|
||||
(*REPO_CREATE_COMMAND, '--extra', '--options', 'value with space', '--repo', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -507,7 +494,6 @@ def test_create_repository_calls_borg_with_extra_borg_options_from_deprecated_in
|
||||
insert_repo_create_command_mock(
|
||||
(*REPO_CREATE_COMMAND, '--extra', '--options', 'value with space', '--repo', 'repo'),
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
@@ -532,7 +518,6 @@ def test_create_repository_calls_borg_with_working_directory():
|
||||
(*REPO_CREATE_COMMAND, '--repo', 'repo'),
|
||||
working_directory='/working/dir',
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(
|
||||
(
|
||||
|
||||
@@ -8,7 +8,6 @@ from ..test_verbosity import insert_logging_mock
|
||||
|
||||
|
||||
def test_make_repo_delete_command_with_feature_available_runs_borg_repo_delete():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
@@ -31,7 +30,6 @@ def test_make_repo_delete_command_with_feature_available_runs_borg_repo_delete()
|
||||
|
||||
|
||||
def test_make_repo_delete_command_without_feature_available_runs_borg_delete():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(False)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
@@ -100,7 +98,6 @@ def test_make_repo_delete_command_includes_log_debug():
|
||||
|
||||
|
||||
def test_make_repo_delete_command_includes_dry_run():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args(
|
||||
@@ -127,7 +124,6 @@ def test_make_repo_delete_command_includes_dry_run():
|
||||
|
||||
|
||||
def test_make_repo_delete_command_includes_remote_path():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args(
|
||||
@@ -154,7 +150,6 @@ def test_make_repo_delete_command_includes_remote_path():
|
||||
|
||||
|
||||
def test_make_repo_delete_command_includes_umask():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').replace_with(
|
||||
lambda name, value: (f'--{name}', value) if value else (),
|
||||
@@ -179,7 +174,6 @@ def test_make_repo_delete_command_includes_umask():
|
||||
|
||||
|
||||
def test_make_repo_delete_command_includes_lock_wait():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args(
|
||||
@@ -206,7 +200,6 @@ def test_make_repo_delete_command_includes_lock_wait():
|
||||
|
||||
|
||||
def test_make_repo_delete_command_without_feature_available_includes_delete_extra_borg_options():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(False)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
@@ -229,7 +222,6 @@ def test_make_repo_delete_command_without_feature_available_includes_delete_extr
|
||||
|
||||
|
||||
def test_make_repo_delete_command_with_feature_available_includes_delete_extra_borg_options():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
@@ -252,7 +244,6 @@ def test_make_repo_delete_command_with_feature_available_includes_delete_extra_b
|
||||
|
||||
|
||||
def test_make_repo_delete_command_includes_list():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').with_args(
|
||||
@@ -279,7 +270,6 @@ def test_make_repo_delete_command_includes_list():
|
||||
|
||||
|
||||
def test_make_repo_delete_command_includes_force():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
@@ -302,7 +292,6 @@ def test_make_repo_delete_command_includes_force():
|
||||
|
||||
|
||||
def test_make_repo_delete_command_includes_force_twice():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
@@ -325,7 +314,6 @@ def test_make_repo_delete_command_includes_force_twice():
|
||||
|
||||
|
||||
def test_make_repo_delete_command_with_output_file_omits_log_json():
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.borgmatic.borg.feature).should_receive('available').and_return(True)
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags').and_return(())
|
||||
flexmock(module.borgmatic.borg.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import logging
|
||||
|
||||
import pytest
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.borg import repo_info as module
|
||||
@@ -38,7 +39,6 @@ def test_display_repository_info_calls_borg_with_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.display_repository_info(
|
||||
repository_path='repo',
|
||||
@@ -75,7 +75,6 @@ def test_display_repository_info_without_borg_features_calls_borg_with_info_sub_
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.display_repository_info(
|
||||
repository_path='repo',
|
||||
@@ -118,7 +117,6 @@ def test_display_repository_info_with_log_info_calls_borg_with_info_flag():
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.INFO)
|
||||
|
||||
module.display_repository_info(
|
||||
repository_path='repo',
|
||||
config={},
|
||||
@@ -151,8 +149,8 @@ def test_display_repository_info_with_log_info_and_json_suppresses_most_borg_out
|
||||
borg_exit_codes=None,
|
||||
).and_yield('[]')
|
||||
flexmock(module.flags).should_receive('warn_for_aggressive_archive_flags').never()
|
||||
insert_logging_mock(logging.INFO)
|
||||
|
||||
insert_logging_mock(logging.INFO)
|
||||
json_output = module.display_repository_info(
|
||||
repository_path='repo',
|
||||
config={},
|
||||
@@ -229,8 +227,8 @@ def test_display_repository_info_with_log_debug_and_json_suppresses_most_borg_ou
|
||||
borg_exit_codes=None,
|
||||
).and_yield('[]')
|
||||
flexmock(module.flags).should_receive('warn_for_aggressive_archive_flags').never()
|
||||
insert_logging_mock(logging.DEBUG)
|
||||
|
||||
insert_logging_mock(logging.DEBUG)
|
||||
json_output = module.display_repository_info(
|
||||
repository_path='repo',
|
||||
config={},
|
||||
@@ -265,7 +263,6 @@ def test_display_repository_info_with_json_calls_borg_with_json_flag():
|
||||
borg_exit_codes=None,
|
||||
).and_yield('[]')
|
||||
flexmock(module.flags).should_receive('warn_for_aggressive_archive_flags').never()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
json_output = module.display_repository_info(
|
||||
repository_path='repo',
|
||||
@@ -309,7 +306,6 @@ def test_display_repository_info_with_local_path_calls_borg_via_local_path():
|
||||
borg_local_path='borg1',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.display_repository_info(
|
||||
repository_path='repo',
|
||||
@@ -353,7 +349,6 @@ def test_display_repository_info_with_exit_codes_calls_borg_using_them():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=borg_exit_codes,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.display_repository_info(
|
||||
repository_path='repo',
|
||||
@@ -395,7 +390,6 @@ def test_display_repository_info_with_remote_path_calls_borg_with_remote_path_fl
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.display_repository_info(
|
||||
repository_path='repo',
|
||||
@@ -438,7 +432,6 @@ def test_display_repository_info_with_umask_calls_borg_with_umask_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.display_repository_info(
|
||||
repository_path='repo',
|
||||
@@ -475,7 +468,6 @@ def test_display_repository_info_with_lock_wait_calls_borg_with_lock_wait_flags(
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.display_repository_info(
|
||||
repository_path='repo',
|
||||
@@ -518,7 +510,6 @@ def test_display_repository_info_without_feature_available_calls_borg_with_info_
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.display_repository_info(
|
||||
repository_path='repo',
|
||||
@@ -571,7 +562,6 @@ def test_display_repository_info_with_feature_available_calls_borg_with_repo_inf
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.display_repository_info(
|
||||
repository_path='repo',
|
||||
@@ -615,7 +605,6 @@ def test_display_repository_info_calls_borg_with_working_directory():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.display_repository_info(
|
||||
repository_path='repo',
|
||||
@@ -624,3 +613,51 @@ def test_display_repository_info_calls_borg_with_working_directory():
|
||||
repo_info_arguments=flexmock(json=False),
|
||||
global_arguments=flexmock(),
|
||||
)
|
||||
|
||||
|
||||
def test_get_repository_id_with_valid_json_does_not_raise():
|
||||
config = {}
|
||||
flexmock(module).should_receive('display_repository_info').and_return(
|
||||
'{"repository": {"id": "repo"}}',
|
||||
)
|
||||
|
||||
assert module.get_repository_id(
|
||||
repository_path='repo',
|
||||
config=config,
|
||||
local_borg_version='1.2.3',
|
||||
global_arguments=flexmock(),
|
||||
local_path='borg',
|
||||
remote_path=None,
|
||||
)
|
||||
|
||||
|
||||
def test_get_repository_id_with_json_error_raises():
|
||||
config = {}
|
||||
flexmock(module).should_receive('display_repository_info').and_return(
|
||||
'{"unexpected": {"id": "repo"}}',
|
||||
)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.get_repository_id(
|
||||
repository_path='repo',
|
||||
config=config,
|
||||
local_borg_version='1.2.3',
|
||||
global_arguments=flexmock(),
|
||||
local_path='borg',
|
||||
remote_path=None,
|
||||
)
|
||||
|
||||
|
||||
def test_get_repository_id_with_missing_json_keys_raises():
|
||||
config = {}
|
||||
flexmock(module).should_receive('display_repository_info').and_return('{invalid JSON')
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.get_repository_id(
|
||||
repository_path='repo',
|
||||
config=config,
|
||||
local_borg_version='1.2.3',
|
||||
global_arguments=flexmock(),
|
||||
local_path='borg',
|
||||
remote_path=None,
|
||||
)
|
||||
|
||||
@@ -126,7 +126,6 @@ def test_get_latest_archive_calls_borg_with_flags():
|
||||
environment=None,
|
||||
working_directory=None,
|
||||
).and_yield(json.dumps({'archives': [expected_archive]}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.get_latest_archive(
|
||||
@@ -219,7 +218,6 @@ def test_get_latest_archive_with_local_path_calls_borg_via_local_path():
|
||||
borg_local_path='borg1',
|
||||
borg_exit_codes=None,
|
||||
).and_yield(json.dumps({'archives': [expected_archive]}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.get_latest_archive(
|
||||
@@ -252,7 +250,6 @@ def test_get_latest_archive_with_exit_codes_calls_borg_using_them():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=borg_exit_codes,
|
||||
).and_yield(json.dumps({'archives': [expected_archive]}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.get_latest_archive(
|
||||
@@ -286,7 +283,6 @@ def test_get_latest_archive_with_remote_path_calls_borg_with_remote_path_flags()
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).and_yield(json.dumps({'archives': [expected_archive]}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.get_latest_archive(
|
||||
@@ -321,7 +317,6 @@ def test_get_latest_archive_with_umask_calls_borg_with_umask_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).and_yield(json.dumps({'archives': [expected_archive]}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.get_latest_archive(
|
||||
@@ -351,7 +346,6 @@ def test_get_latest_archive_without_archives_raises():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).and_yield(json.dumps({'archives': []}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.get_latest_archive(
|
||||
@@ -383,7 +377,6 @@ def test_get_latest_archive_with_lock_wait_calls_borg_with_lock_wait_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).and_yield(json.dumps({'archives': [expected_archive]}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.get_latest_archive(
|
||||
@@ -416,7 +409,6 @@ def test_get_latest_archive_with_match_archives_calls_borg_with_match_archives_f
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).and_yield(json.dumps({'archives': [expected_archive]}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.get_latest_archive(
|
||||
@@ -455,7 +447,6 @@ def test_get_latest_archive_calls_borg_with_list_extra_borg_options():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).and_yield(json.dumps({'archives': [expected_archive]}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.get_latest_archive(
|
||||
@@ -494,7 +485,6 @@ def test_get_latest_archive_with_feature_available_calls_borg_with_repo_list_ext
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).and_yield(json.dumps({'archives': [expected_archive]}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.get_latest_archive(
|
||||
@@ -528,7 +518,6 @@ def test_get_latest_archive_with_consider_checkpoints_calls_borg_with_consider_c
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).and_yield(json.dumps({'archives': [expected_archive]}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.get_latest_archive(
|
||||
@@ -563,7 +552,6 @@ def test_get_latest_archive_with_consider_checkpoints_and_feature_available_call
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
).and_yield(json.dumps({'archives': [expected_archive]}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.get_latest_archive(
|
||||
@@ -597,7 +585,6 @@ def test_get_latest_archive_calls_borg_with_working_directory():
|
||||
environment=None,
|
||||
working_directory='/working/dir',
|
||||
).and_yield(json.dumps({'archives': [expected_archive]}))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
assert (
|
||||
module.get_latest_archive(
|
||||
@@ -771,7 +758,6 @@ def test_make_repo_list_command_includes_lock_wait():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -801,7 +787,6 @@ def test_make_repo_list_command_includes_list_extra_borg_options():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -831,7 +816,6 @@ def test_make_repo_list_command_with_feature_available_includes_repo_list_extra_
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -861,7 +845,6 @@ def test_make_repo_list_command_includes_local_path():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -894,7 +877,6 @@ def test_make_repo_list_command_includes_remote_path():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -927,7 +909,6 @@ def test_make_repo_list_command_includes_umask():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -959,7 +940,6 @@ def test_make_repo_list_command_transforms_prefix_into_match_archives():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -982,7 +962,6 @@ def test_make_repo_list_command_prefers_prefix_over_archive_name_format():
|
||||
flexmock(module.flags).should_receive('make_match_archives_flags').never()
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -1007,7 +986,6 @@ def test_make_repo_list_command_transforms_archive_name_format_into_match_archiv
|
||||
).and_return(('--match-archives', 'sh:bar-*'))
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -1039,7 +1017,6 @@ def test_make_repo_list_command_includes_format_from_command_line():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -1070,7 +1047,6 @@ def test_make_repo_list_command_includes_short():
|
||||
).and_return(())
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(('--short',))
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -1115,7 +1091,6 @@ def test_make_repo_list_command_includes_additional_flags(argument_name):
|
||||
(f"--{argument_name.replace('_', '-')}", 'value'),
|
||||
)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -1159,7 +1134,6 @@ def test_make_repo_list_command_with_match_archives_calls_borg_with_match_archiv
|
||||
).and_return(('--match-archives', 'foo-*'))
|
||||
flexmock(module.flags).should_receive('make_flags_from_arguments').and_return(())
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -1187,7 +1161,6 @@ def test_list_repository_calls_borg_command():
|
||||
flexmock(module.environment).should_receive('make_environment')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module).should_receive('execute_command_and_capture_output').and_yield('').once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('warn_for_aggressive_archive_flags')
|
||||
|
||||
module.list_repository(
|
||||
@@ -1205,7 +1178,6 @@ def test_list_repository_with_json_calls_borg_json_command_only():
|
||||
flexmock(module.environment).should_receive('make_environment')
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module).should_receive('execute_command_and_capture_output').and_yield('{}')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('warn_for_aggressive_archive_flags').never()
|
||||
|
||||
assert (
|
||||
@@ -1232,7 +1204,6 @@ def test_make_repo_list_command_with_date_based_matching_calls_borg_with_date_ba
|
||||
('--newer', '1d', '--newest', '1y', '--older', '1m', '--oldest', '1w'),
|
||||
)
|
||||
flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
command = module.make_repo_list_command(
|
||||
repository_path='repo',
|
||||
@@ -1285,7 +1256,6 @@ def test_list_repository_calls_borg_with_working_directory():
|
||||
borg_local_path=object,
|
||||
borg_exit_codes=object,
|
||||
).and_yield('').once()
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.flags).should_receive('warn_for_aggressive_archive_flags')
|
||||
|
||||
module.list_repository(
|
||||
|
||||
@@ -26,7 +26,6 @@ def test_transfer_archives_calls_borg_with_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -64,7 +63,6 @@ def test_transfer_archives_with_dry_run_calls_borg_with_dry_run_flag():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=True,
|
||||
@@ -100,7 +98,6 @@ def test_transfer_archives_with_log_info_calls_borg_with_info_flag():
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.INFO)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
repository_path='repo',
|
||||
@@ -173,7 +170,6 @@ def test_transfer_archives_with_archive_calls_borg_with_match_archives_flag():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -212,7 +208,6 @@ def test_transfer_archives_with_match_archives_calls_borg_with_match_archives_fl
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -251,7 +246,6 @@ def test_transfer_archives_with_archive_name_format_calls_borg_with_match_archiv
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -286,7 +280,6 @@ def test_transfer_archives_with_local_path_calls_borg_via_local_path():
|
||||
borg_local_path='borg2',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -323,7 +316,6 @@ def test_transfer_archives_with_exit_codes_calls_borg_using_them():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=borg_exit_codes,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -362,7 +354,6 @@ def test_transfer_archives_with_remote_path_calls_borg_with_remote_path_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -400,7 +391,6 @@ def test_transfer_archives_with_umask_calls_borg_with_umask_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -439,7 +429,6 @@ def test_transfer_archives_with_lock_wait_calls_borg_with_lock_wait_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -475,7 +464,6 @@ def test_transfer_archives_calls_borg_with_extra_borg_options():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -513,7 +501,6 @@ def test_transfer_archives_with_progress_calls_borg_with_progress_flags():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -551,7 +538,6 @@ def test_transfer_archives_with_log_json_and_progress_calls_borg_with_both_flags
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -590,7 +576,6 @@ def test_transfer_archives_passes_through_arguments_to_borg(argument_name):
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -628,7 +613,6 @@ def test_transfer_archives_with_source_repository_calls_borg_with_other_repo_fla
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -678,7 +662,6 @@ def test_transfer_archives_with_date_based_matching_calls_borg_with_date_based_f
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
@@ -718,7 +701,6 @@ def test_transfer_archives_calls_borg_with_working_directory():
|
||||
borg_local_path='borg',
|
||||
borg_exit_codes=None,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.transfer_archives(
|
||||
dry_run=False,
|
||||
|
||||
@@ -26,7 +26,6 @@ def insert_execute_command_mock(
|
||||
|
||||
def test_unmount_archive_calls_borg_with_required_parameters():
|
||||
insert_execute_command_mock(('borg', 'umount', '--log-json', '/mnt'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.unmount_archive(config={}, mount_point='/mnt')
|
||||
|
||||
@@ -50,7 +49,6 @@ def test_unmount_archive_calls_borg_with_extra_borg_options():
|
||||
('borg', 'umount', '--log-json', '--extra', 'value with space', '/mnt'),
|
||||
borg_local_path='borg',
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.unmount_archive(
|
||||
config={'extra_borg_options': {'umount': '--extra "value with space"'}}, mount_point='/mnt'
|
||||
@@ -59,7 +57,6 @@ def test_unmount_archive_calls_borg_with_extra_borg_options():
|
||||
|
||||
def test_unmount_archive_calls_borg_with_local_path():
|
||||
insert_execute_command_mock(('borg1', 'umount', '--log-json', '/mnt'), borg_local_path='borg1')
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.unmount_archive(config={}, mount_point='/mnt', local_path='borg1')
|
||||
|
||||
@@ -69,7 +66,6 @@ def test_unmount_archive_calls_borg_with_exit_codes():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'umount', '--log-json', '/mnt'), borg_exit_codes=borg_exit_codes
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.unmount_archive(config={'borg_exit_codes': borg_exit_codes}, mount_point='/mnt')
|
||||
|
||||
@@ -78,6 +74,5 @@ def test_unmount_archive_calls_borg_with_working_directory():
|
||||
insert_execute_command_mock(
|
||||
('borg', 'umount', '--log-json', '/mnt'), working_directory='/working/dir'
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
|
||||
module.unmount_archive(config={'working_directory': '/working/dir'}, mount_point='/mnt')
|
||||
|
||||
@@ -32,7 +32,6 @@ def insert_execute_command_and_capture_output_mock(
|
||||
|
||||
def test_local_borg_version_calls_borg_with_required_parameters():
|
||||
insert_execute_command_and_capture_output_mock(('borg', '--version', '--log-json'))
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.environment).should_receive('make_environment')
|
||||
|
||||
assert module.local_borg_version({}) == VERSION
|
||||
@@ -60,7 +59,6 @@ def test_local_borg_version_with_local_borg_path_calls_borg_with_it():
|
||||
insert_execute_command_and_capture_output_mock(
|
||||
('borg1', '--version', '--log-json'), borg_local_path='borg1'
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.environment).should_receive('make_environment')
|
||||
|
||||
assert module.local_borg_version({}, 'borg1') == VERSION
|
||||
@@ -72,7 +70,6 @@ def test_local_borg_version_with_borg_exit_codes_calls_using_with_them():
|
||||
('borg', '--version', '--log-json'),
|
||||
borg_exit_codes=borg_exit_codes,
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.environment).should_receive('make_environment')
|
||||
|
||||
assert module.local_borg_version({'borg_exit_codes': borg_exit_codes}) == VERSION
|
||||
@@ -82,7 +79,6 @@ def test_local_borg_version_with_invalid_version_raises():
|
||||
insert_execute_command_and_capture_output_mock(
|
||||
('borg', '--version', '--log-json'), version_output='wtf'
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.environment).should_receive('make_environment')
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
@@ -94,7 +90,6 @@ def test_local_borg_version_calls_borg_with_working_directory():
|
||||
('borg', '--version', '--log-json'),
|
||||
working_directory='/working/dir',
|
||||
)
|
||||
insert_logging_mock(logging.WARNING)
|
||||
flexmock(module.environment).should_receive('make_environment')
|
||||
|
||||
assert module.local_borg_version({'working_directory': '/working/dir'}) == VERSION
|
||||
|
||||
@@ -2095,43 +2095,6 @@ def test_collect_highlander_action_summary_logs_error_on_run_show_failure():
|
||||
assert {log.levelno for log in logs} == {logging.CRITICAL}
|
||||
|
||||
|
||||
def test_collect_highlander_action_summary_logs_nothing_additional_for_success_with_browse():
|
||||
flexmock(module.borgmatic.actions.browse.run).should_receive('run_browse')
|
||||
arguments = {
|
||||
'browse': flexmock(),
|
||||
'global': flexmock(),
|
||||
}
|
||||
|
||||
logs = tuple(
|
||||
module.collect_highlander_action_summary_logs(
|
||||
{'test.yaml': {}},
|
||||
arguments=arguments,
|
||||
configuration_parse_errors=False,
|
||||
),
|
||||
)
|
||||
assert not logs
|
||||
|
||||
|
||||
def test_collect_highlander_action_summary_logs_error_on_run_browse_failure():
|
||||
flexmock(module.borgmatic.actions.browse.run).should_receive('run_browse').and_raise(
|
||||
ValueError,
|
||||
)
|
||||
arguments = {
|
||||
'browse': flexmock(),
|
||||
'global': flexmock(),
|
||||
}
|
||||
|
||||
logs = tuple(
|
||||
module.collect_highlander_action_summary_logs(
|
||||
{'test.yaml': {}},
|
||||
arguments=arguments,
|
||||
configuration_parse_errors=False,
|
||||
),
|
||||
)
|
||||
|
||||
assert {log.levelno for log in logs} == {logging.CRITICAL}
|
||||
|
||||
|
||||
def test_collect_configuration_run_summary_logs_info_for_success():
|
||||
flexmock(module.validate).should_receive('guard_configuration_contains_repository')
|
||||
flexmock(module.command).should_receive('filter_hooks').with_args(
|
||||
|
||||
+81
-107
@@ -62,65 +62,58 @@ def test_replace_temporary_subdirectory_with_glob_uses_custom_temporary_director
|
||||
)
|
||||
|
||||
|
||||
def test_fixed_name_temporary_directory_cleanup_does_not_raise():
|
||||
flexmock(module.shutil).should_receive('rmtree')
|
||||
|
||||
module.Fixed_name_temporary_directory('/path').cleanup()
|
||||
|
||||
|
||||
def test_runtime_directory_uses_config_option():
|
||||
flexmock(module).should_receive('Fixed_name_temporary_directory').and_return(
|
||||
flexmock(cleanup=lambda: None)
|
||||
)
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
config = {'user_runtime_directory': '/run', 'borgmatic_source_directory': '/nope'}
|
||||
|
||||
with module.Runtime_directory(config) as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/run/./borgmatic'
|
||||
|
||||
|
||||
def test_runtime_directory_uses_config_option_without_adding_duplicate_borgmatic_subdirectory():
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
config = {'user_runtime_directory': '/run/borgmatic', 'borgmatic_source_directory': '/nope'}
|
||||
|
||||
with module.Runtime_directory(config) as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/run/./borgmatic'
|
||||
with module.Runtime_directory(config, repository_id='id') as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/run/borgmatic-id/./borgmatic'
|
||||
|
||||
|
||||
def test_runtime_directory_with_relative_config_option_errors():
|
||||
flexmock(module.os).should_receive('makedirs').never()
|
||||
config = {'user_runtime_directory': 'run', 'borgmatic_source_directory': '/nope'}
|
||||
|
||||
with pytest.raises(ValueError), module.Runtime_directory(config):
|
||||
with pytest.raises(ValueError), module.Runtime_directory(config, repository_id='id'):
|
||||
pass
|
||||
|
||||
|
||||
def test_runtime_directory_falls_back_to_xdg_runtime_dir():
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(
|
||||
'/run',
|
||||
def test_runtime_directory_falls_back_to_xdg_runtime_dir(monkeypatch):
|
||||
flexmock(module).should_receive('Fixed_name_temporary_directory').and_return(
|
||||
flexmock(cleanup=lambda: None)
|
||||
)
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
monkeypatch.setenv('XDG_RUNTIME_DIR', '/run')
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
|
||||
with module.Runtime_directory({}) as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/run/./borgmatic'
|
||||
with module.Runtime_directory({}, repository_id='id') as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/run/borgmatic-id/./borgmatic'
|
||||
|
||||
|
||||
def test_runtime_directory_falls_back_to_xdg_runtime_dir_without_adding_duplicate_borgmatic_subdirectory():
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(
|
||||
'/run/borgmatic',
|
||||
)
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
|
||||
with module.Runtime_directory({}) as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/run/./borgmatic'
|
||||
|
||||
|
||||
def test_runtime_directory_with_relative_xdg_runtime_dir_errors():
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return('run')
|
||||
def test_runtime_directory_with_relative_xdg_runtime_dir_errors(monkeypatch):
|
||||
monkeypatch.setenv('XDG_RUNTIME_DIR', 'run')
|
||||
flexmock(module.os).should_receive('makedirs').never()
|
||||
|
||||
with pytest.raises(ValueError), module.Runtime_directory({}):
|
||||
with pytest.raises(ValueError), module.Runtime_directory({}, repository_id='id'):
|
||||
pass
|
||||
|
||||
|
||||
def test_runtime_directory_falls_back_to_runtime_directory():
|
||||
def test_runtime_directory_falls_back_to_runtime_directory(monkeypatch):
|
||||
flexmock(module).should_receive('Fixed_name_temporary_directory').and_return(
|
||||
flexmock(cleanup=lambda: None)
|
||||
)
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
|
||||
monkeypatch.delenv('XDG_RUNTIME_DIR', raising=False)
|
||||
flexmock(module).should_receive('resolve_systemd_directory').with_args(
|
||||
module.Systemd_directories.RUNTIME_DIRECTORY
|
||||
).and_return(
|
||||
@@ -128,26 +121,12 @@ def test_runtime_directory_falls_back_to_runtime_directory():
|
||||
)
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
|
||||
with module.Runtime_directory({}) as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/run/./borgmatic'
|
||||
with module.Runtime_directory({}, repository_id='id') as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/run/borgmatic-id/./borgmatic'
|
||||
|
||||
|
||||
def test_runtime_directory_falls_back_to_runtime_directory_without_adding_duplicate_borgmatic_subdirectory():
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
|
||||
flexmock(module).should_receive('resolve_systemd_directory').with_args(
|
||||
module.Systemd_directories.RUNTIME_DIRECTORY
|
||||
).and_return(
|
||||
'/run/borgmatic',
|
||||
)
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
|
||||
with module.Runtime_directory({}) as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/run/./borgmatic'
|
||||
|
||||
|
||||
def test_runtime_directory_with_relative_runtime_directory_errors():
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
|
||||
def test_runtime_directory_with_relative_runtime_directory_errors(monkeypatch):
|
||||
monkeypatch.delenv('XDG_RUNTIME_DIR', raising=False)
|
||||
flexmock(module).should_receive('resolve_systemd_directory').with_args(
|
||||
module.Systemd_directories.RUNTIME_DIRECTORY
|
||||
).and_return(
|
||||
@@ -155,19 +134,21 @@ def test_runtime_directory_with_relative_runtime_directory_errors():
|
||||
)
|
||||
flexmock(module.os).should_receive('makedirs').never()
|
||||
|
||||
with pytest.raises(ValueError), module.Runtime_directory({}):
|
||||
with pytest.raises(ValueError), module.Runtime_directory({}, repository_id='id'):
|
||||
pass
|
||||
|
||||
|
||||
def test_runtime_directory_falls_back_to_tmpdir_and_adds_temporary_subdirectory_that_get_cleaned_up():
|
||||
def test_runtime_directory_falls_back_to_tmpdir_and_adds_temporary_subdirectory_that_get_cleaned_up(
|
||||
monkeypatch,
|
||||
):
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
|
||||
monkeypatch.delenv('XDG_RUNTIME_DIR', raising=False)
|
||||
flexmock(module).should_receive('resolve_systemd_directory').with_args(
|
||||
module.Systemd_directories.RUNTIME_DIRECTORY
|
||||
).and_return(
|
||||
None,
|
||||
)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TMPDIR').and_return('/run')
|
||||
monkeypatch.setenv('TMPDIR', '/run')
|
||||
temporary_directory = flexmock(name='/run/borgmatic-1234')
|
||||
temporary_directory.should_receive('cleanup').once()
|
||||
flexmock(module.tempfile).should_receive('TemporaryDirectory').with_args(
|
||||
@@ -176,35 +157,37 @@ def test_runtime_directory_falls_back_to_tmpdir_and_adds_temporary_subdirectory_
|
||||
).and_return(temporary_directory)
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
|
||||
with module.Runtime_directory({}) as borgmatic_runtime_directory:
|
||||
with module.Runtime_directory({}, repository_id='id') as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/run/borgmatic-1234/./borgmatic'
|
||||
|
||||
|
||||
def test_runtime_directory_with_relative_tmpdir_errors():
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
|
||||
def test_runtime_directory_with_relative_tmpdir_errors(monkeypatch):
|
||||
monkeypatch.delenv('XDG_RUNTIME_DIR', raising=False)
|
||||
flexmock(module).should_receive('resolve_systemd_directory').with_args(
|
||||
module.Systemd_directories.RUNTIME_DIRECTORY
|
||||
).and_return(
|
||||
None,
|
||||
)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TMPDIR').and_return('run')
|
||||
monkeypatch.setenv('TMPDIR', 'run')
|
||||
flexmock(module.tempfile).should_receive('TemporaryDirectory').never()
|
||||
flexmock(module.os).should_receive('makedirs').never()
|
||||
|
||||
with pytest.raises(ValueError), module.Runtime_directory({}):
|
||||
with pytest.raises(ValueError), module.Runtime_directory({}, repository_id='id'):
|
||||
pass
|
||||
|
||||
|
||||
def test_runtime_directory_falls_back_to_temp_and_adds_temporary_subdirectory_that_get_cleaned_up():
|
||||
def test_runtime_directory_falls_back_to_temp_and_adds_temporary_subdirectory_that_get_cleaned_up(
|
||||
monkeypatch,
|
||||
):
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
|
||||
monkeypatch.delenv('XDG_RUNTIME_DIR', raising=False)
|
||||
flexmock(module).should_receive('resolve_systemd_directory').with_args(
|
||||
module.Systemd_directories.RUNTIME_DIRECTORY
|
||||
).and_return(
|
||||
None,
|
||||
)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TMPDIR').and_return(None)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TEMP').and_return('/run')
|
||||
monkeypatch.delenv('TMPDIR', raising=False)
|
||||
monkeypatch.setenv('TEMP', '/run')
|
||||
temporary_directory = flexmock(name='/run/borgmatic-1234')
|
||||
temporary_directory.should_receive('cleanup').once()
|
||||
flexmock(module.tempfile).should_receive('TemporaryDirectory').with_args(
|
||||
@@ -213,36 +196,38 @@ def test_runtime_directory_falls_back_to_temp_and_adds_temporary_subdirectory_th
|
||||
).and_return(temporary_directory)
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
|
||||
with module.Runtime_directory({}) as borgmatic_runtime_directory:
|
||||
with module.Runtime_directory({}, repository_id='id') as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/run/borgmatic-1234/./borgmatic'
|
||||
|
||||
|
||||
def test_runtime_directory_with_relative_temp_errors():
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
|
||||
def test_runtime_directory_with_relative_temp_errors(monkeypatch):
|
||||
monkeypatch.delenv('XDG_RUNTIME_DIR', raising=False)
|
||||
flexmock(module).should_receive('resolve_systemd_directory').with_args(
|
||||
module.Systemd_directories.RUNTIME_DIRECTORY
|
||||
).and_return(
|
||||
None,
|
||||
)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TMPDIR').and_return(None)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TEMP').and_return('run')
|
||||
monkeypatch.delenv('TMPDIR', raising=False)
|
||||
monkeypatch.setenv('TEMP', 'run')
|
||||
flexmock(module.tempfile).should_receive('TemporaryDirectory').never()
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
|
||||
with pytest.raises(ValueError), module.Runtime_directory({}):
|
||||
with pytest.raises(ValueError), module.Runtime_directory({}, repository_id='id'):
|
||||
pass
|
||||
|
||||
|
||||
def test_runtime_directory_falls_back_to_hard_coded_tmp_path_and_adds_temporary_subdirectory_that_get_cleaned_up():
|
||||
def test_runtime_directory_falls_back_to_hard_coded_tmp_path_and_adds_temporary_subdirectory_that_get_cleaned_up(
|
||||
monkeypatch,
|
||||
):
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
|
||||
monkeypatch.delenv('XDG_RUNTIME_DIR', raising=False)
|
||||
flexmock(module).should_receive('resolve_systemd_directory').with_args(
|
||||
module.Systemd_directories.RUNTIME_DIRECTORY
|
||||
).and_return(
|
||||
None,
|
||||
)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TMPDIR').and_return(None)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TEMP').and_return(None)
|
||||
monkeypatch.delenv('TMPDIR', raising=False)
|
||||
monkeypatch.delenv('TEMP', raising=False)
|
||||
temporary_directory = flexmock(name='/tmp/borgmatic-1234')
|
||||
temporary_directory.should_receive('cleanup').once()
|
||||
flexmock(module.tempfile).should_receive('TemporaryDirectory').with_args(
|
||||
@@ -251,20 +236,20 @@ def test_runtime_directory_falls_back_to_hard_coded_tmp_path_and_adds_temporary_
|
||||
).and_return(temporary_directory)
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
|
||||
with module.Runtime_directory({}) as borgmatic_runtime_directory:
|
||||
with module.Runtime_directory({}, repository_id='id') as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/tmp/borgmatic-1234/./borgmatic'
|
||||
|
||||
|
||||
def test_runtime_directory_with_erroring_cleanup_does_not_raise():
|
||||
def test_runtime_directory_with_erroring_cleanup_does_not_raise(monkeypatch):
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_RUNTIME_DIR').and_return(None)
|
||||
monkeypatch.delenv('XDG_RUNTIME_DIR', raising=False)
|
||||
flexmock(module).should_receive('resolve_systemd_directory').with_args(
|
||||
module.Systemd_directories.RUNTIME_DIRECTORY
|
||||
).and_return(
|
||||
None,
|
||||
)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TMPDIR').and_return(None)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('TEMP').and_return(None)
|
||||
monkeypatch.delenv('TMPDIR', raising=False)
|
||||
monkeypatch.delenv('TEMP', raising=False)
|
||||
temporary_directory = flexmock(name='/tmp/borgmatic-1234')
|
||||
temporary_directory.should_receive('cleanup').and_raise(OSError).once()
|
||||
flexmock(module.tempfile).should_receive('TemporaryDirectory').with_args(
|
||||
@@ -273,7 +258,7 @@ def test_runtime_directory_with_erroring_cleanup_does_not_raise():
|
||||
).and_return(temporary_directory)
|
||||
flexmock(module.os).should_receive('makedirs')
|
||||
|
||||
with module.Runtime_directory({}) as borgmatic_runtime_directory:
|
||||
with module.Runtime_directory({}, repository_id='id') as borgmatic_runtime_directory:
|
||||
assert borgmatic_runtime_directory == '/tmp/borgmatic-1234/./borgmatic'
|
||||
|
||||
|
||||
@@ -291,7 +276,6 @@ def test_make_runtime_directory_glob(borgmatic_runtime_directory, expected_glob)
|
||||
|
||||
def test_get_borgmatic_state_directory_uses_config_option():
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').never()
|
||||
|
||||
assert (
|
||||
module.get_borgmatic_state_directory(
|
||||
@@ -301,16 +285,16 @@ def test_get_borgmatic_state_directory_uses_config_option():
|
||||
)
|
||||
|
||||
|
||||
def test_get_borgmatic_state_directory_falls_back_to_xdg_state_home():
|
||||
def test_get_borgmatic_state_directory_falls_back_to_xdg_state_home(monkeypatch):
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_STATE_HOME').and_return('/tmp')
|
||||
monkeypatch.setenv('XDG_STATE_HOME', '/tmp')
|
||||
|
||||
assert module.get_borgmatic_state_directory({}) == '/tmp/borgmatic'
|
||||
|
||||
|
||||
def test_get_borgmatic_state_directory_falls_back_to_state_directory():
|
||||
def test_get_borgmatic_state_directory_falls_back_to_state_directory(monkeypatch):
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('XDG_STATE_HOME').and_return(None)
|
||||
monkeypatch.delenv('XDG_STATE_HOME', raising=False)
|
||||
flexmock(module).should_receive('resolve_systemd_directory').with_args(
|
||||
module.Systemd_directories.STATE_DIRECTORY
|
||||
).and_return(
|
||||
@@ -320,32 +304,26 @@ def test_get_borgmatic_state_directory_falls_back_to_state_directory():
|
||||
assert module.get_borgmatic_state_directory({}) == '/tmp/borgmatic'
|
||||
|
||||
|
||||
def test_get_borgmatic_state_directory_defaults_to_hard_coded_path():
|
||||
def test_get_borgmatic_state_directory_defaults_to_hard_coded_path(monkeypatch):
|
||||
flexmock(module).should_receive('expand_user_in_path').replace_with(lambda path: path)
|
||||
flexmock(module.os.environ).should_receive('get').and_return(None)
|
||||
monkeypatch.delenv('XDG_STATE_HOME', raising=False)
|
||||
assert module.get_borgmatic_state_directory({}) == '~/.local/state/borgmatic'
|
||||
|
||||
|
||||
def test_resolve_systemd_directory_none():
|
||||
flexmock(module.os.environ).should_receive('get').with_args('RUNTIME_DIRECTORY').and_return(
|
||||
None
|
||||
)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('STATE_DIRECTORY').and_return(None)
|
||||
def test_resolve_systemd_directory_none(monkeypatch):
|
||||
monkeypatch.delenv('RUNTIME_DIRECTORY', raising=False)
|
||||
monkeypatch.delenv('STATE_DIRECTORY', raising=False)
|
||||
|
||||
assert module.resolve_systemd_directory(module.Systemd_directories.RUNTIME_DIRECTORY) is None
|
||||
assert module.resolve_systemd_directory(module.Systemd_directories.STATE_DIRECTORY) is None
|
||||
|
||||
|
||||
def test_resolve_systemd_directory_single():
|
||||
def test_resolve_systemd_directory_single(monkeypatch):
|
||||
runtime_dir = '/run/borgmatic'
|
||||
state_dir = '/var/lib/borgmatic'
|
||||
|
||||
flexmock(module.os.environ).should_receive('get').with_args('RUNTIME_DIRECTORY').and_return(
|
||||
runtime_dir
|
||||
)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('STATE_DIRECTORY').and_return(
|
||||
state_dir
|
||||
)
|
||||
monkeypatch.setenv('RUNTIME_DIRECTORY', runtime_dir)
|
||||
monkeypatch.setenv('STATE_DIRECTORY', state_dir)
|
||||
|
||||
assert (
|
||||
module.resolve_systemd_directory(module.Systemd_directories.RUNTIME_DIRECTORY)
|
||||
@@ -354,16 +332,12 @@ def test_resolve_systemd_directory_single():
|
||||
assert module.resolve_systemd_directory(module.Systemd_directories.STATE_DIRECTORY) == state_dir
|
||||
|
||||
|
||||
def test_resolve_systemd_directory_multiple():
|
||||
def test_resolve_systemd_directory_multiple(monkeypatch):
|
||||
runtime_dirs = '/run/borgmatic:/run/second:/run/third'
|
||||
state_dirs = '/var/lib/borgmatic:/var/lib/second:/var/lib/third'
|
||||
|
||||
flexmock(module.os.environ).should_receive('get').with_args('RUNTIME_DIRECTORY').and_return(
|
||||
runtime_dirs
|
||||
)
|
||||
flexmock(module.os.environ).should_receive('get').with_args('STATE_DIRECTORY').and_return(
|
||||
state_dirs
|
||||
)
|
||||
monkeypatch.setenv('RUNTIME_DIRECTORY', runtime_dirs)
|
||||
monkeypatch.setenv('STATE_DIRECTORY', state_dirs)
|
||||
|
||||
assert (
|
||||
module.resolve_systemd_directory(module.Systemd_directories.RUNTIME_DIRECTORY)
|
||||
|
||||
@@ -66,9 +66,7 @@ def test_initialize_monitor_without_send_logs_does_not_add_handler():
|
||||
|
||||
|
||||
def test_ping_monitor_respects_dry_run():
|
||||
flexmock(module.borgmatic.hooks.credential.parse).should_receive(
|
||||
'resolve_credential'
|
||||
).replace_with(lambda url, config: url)
|
||||
flexmock(module.borgmatic.hooks.monitoring.logs).should_receive('get_handler')
|
||||
flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
|
||||
'format_buffered_logs_for_payload',
|
||||
).and_return('loggy log')
|
||||
@@ -85,9 +83,7 @@ def test_ping_monitor_respects_dry_run():
|
||||
|
||||
|
||||
def test_ping_monitor_with_no_states_does_not_notify():
|
||||
flexmock(module.borgmatic.hooks.credential.parse).should_receive(
|
||||
'resolve_credential'
|
||||
).replace_with(lambda url, config: url)
|
||||
flexmock(module.borgmatic.hooks.monitoring.logs).should_receive('get_handler').never()
|
||||
flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
|
||||
'format_buffered_logs_for_payload',
|
||||
).never()
|
||||
@@ -104,9 +100,7 @@ def test_ping_monitor_with_no_states_does_not_notify():
|
||||
|
||||
|
||||
def test_ping_monitor_notifies_fail_by_default():
|
||||
flexmock(module.borgmatic.hooks.credential.parse).should_receive(
|
||||
'resolve_credential'
|
||||
).replace_with(lambda url, config: url)
|
||||
flexmock(module.borgmatic.hooks.monitoring.logs).should_receive('get_handler')
|
||||
flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
|
||||
'format_buffered_logs_for_payload',
|
||||
).and_return('')
|
||||
@@ -129,9 +123,7 @@ def test_ping_monitor_notifies_fail_by_default():
|
||||
|
||||
|
||||
def test_ping_monitor_with_logs_appends_logs_to_body():
|
||||
flexmock(module.borgmatic.hooks.credential.parse).should_receive(
|
||||
'resolve_credential'
|
||||
).replace_with(lambda url, config: url)
|
||||
flexmock(module.borgmatic.hooks.monitoring.logs).should_receive('get_handler')
|
||||
flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
|
||||
'format_buffered_logs_for_payload',
|
||||
).and_return('loggy log')
|
||||
@@ -154,9 +146,7 @@ def test_ping_monitor_with_logs_appends_logs_to_body():
|
||||
|
||||
|
||||
def test_ping_monitor_with_finish_default_config_notifies():
|
||||
flexmock(module.borgmatic.hooks.credential.parse).should_receive(
|
||||
'resolve_credential'
|
||||
).replace_with(lambda url, config: url)
|
||||
flexmock(module.borgmatic.hooks.monitoring.logs).should_receive('get_handler')
|
||||
flexmock(module.borgmatic.hooks.monitoring.logs).should_receive(
|
||||
'format_buffered_logs_for_payload',
|
||||
).and_return('')
|
||||
|
||||
@@ -779,7 +779,6 @@ def test_raise_for_process_errors_with_no_processes_bails():
|
||||
module.raise_for_process_errors(
|
||||
buffer_readers,
|
||||
process_metadatas={},
|
||||
output_log_level=None,
|
||||
borg_local_path=flexmock(),
|
||||
borg_exit_codes=flexmock(),
|
||||
)
|
||||
@@ -796,7 +795,6 @@ def test_raise_for_process_errors_with_running_process_bails():
|
||||
module.raise_for_process_errors(
|
||||
buffer_readers,
|
||||
process_metadatas,
|
||||
output_log_level=None,
|
||||
borg_local_path=flexmock(),
|
||||
borg_exit_codes=flexmock(),
|
||||
)
|
||||
@@ -814,7 +812,6 @@ def test_raise_for_process_errors_with_running_process_and_no_buffer_readers_wai
|
||||
module.raise_for_process_errors(
|
||||
buffer_readers={},
|
||||
process_metadatas=process_metadatas,
|
||||
output_log_level=None,
|
||||
borg_local_path=flexmock(),
|
||||
borg_exit_codes=flexmock(),
|
||||
)
|
||||
@@ -832,7 +829,6 @@ def test_raise_for_process_errors_with_successful_process_bails():
|
||||
module.raise_for_process_errors(
|
||||
buffer_readers,
|
||||
process_metadatas,
|
||||
output_log_level=None,
|
||||
borg_local_path=flexmock(),
|
||||
borg_exit_codes=flexmock(),
|
||||
)
|
||||
@@ -850,7 +846,6 @@ def test_raise_for_process_errors_with_warning_process_returns_warning_status():
|
||||
module.raise_for_process_errors(
|
||||
buffer_readers,
|
||||
process_metadatas,
|
||||
output_log_level=None,
|
||||
borg_local_path=flexmock(),
|
||||
borg_exit_codes=flexmock(),
|
||||
)
|
||||
@@ -865,7 +860,6 @@ def test_raise_for_process_errors_with_error_process_raises():
|
||||
process: module.Process_metadata(last_lines=['hi', 'there'], capture=False)
|
||||
}
|
||||
flexmock(module).should_receive('interpret_exit_code').and_return(module.Exit_status.ERROR)
|
||||
flexmock(module).should_receive('log_remaining_buffer_lines').and_return(())
|
||||
command = flexmock()
|
||||
flexmock(module).should_receive('command_for_process').and_return(command)
|
||||
|
||||
@@ -873,7 +867,6 @@ def test_raise_for_process_errors_with_error_process_raises():
|
||||
module.raise_for_process_errors(
|
||||
buffer_readers,
|
||||
process_metadatas,
|
||||
output_log_level=None,
|
||||
borg_local_path=flexmock(),
|
||||
borg_exit_codes=flexmock(),
|
||||
)
|
||||
@@ -897,14 +890,12 @@ def test_raise_for_process_errors_with_success_process_and_warning_process_retur
|
||||
flexmock(module).should_receive('interpret_exit_code').with_args(
|
||||
object, 1, object, object
|
||||
).and_return(module.Exit_status.WARNING)
|
||||
flexmock(module).should_receive('log_remaining_buffer_lines').and_return(())
|
||||
flexmock(module).should_receive('command_for_process').never()
|
||||
|
||||
assert (
|
||||
module.raise_for_process_errors(
|
||||
buffer_readers,
|
||||
process_metadatas,
|
||||
output_log_level=None,
|
||||
borg_local_path=flexmock(),
|
||||
borg_exit_codes=flexmock(),
|
||||
)
|
||||
@@ -926,7 +917,6 @@ def test_raise_for_process_errors_with_warning_process_and_error_process_raises(
|
||||
flexmock(module).should_receive('interpret_exit_code').with_args(
|
||||
object, 3, object, object
|
||||
).and_return(module.Exit_status.ERROR)
|
||||
flexmock(module).should_receive('log_remaining_buffer_lines').and_return(())
|
||||
command = flexmock()
|
||||
flexmock(module).should_receive('command_for_process').and_return(command)
|
||||
|
||||
@@ -934,7 +924,6 @@ def test_raise_for_process_errors_with_warning_process_and_error_process_raises(
|
||||
module.raise_for_process_errors(
|
||||
buffer_readers,
|
||||
process_metadatas,
|
||||
output_log_level=None,
|
||||
borg_local_path=flexmock(),
|
||||
borg_exit_codes=flexmock(),
|
||||
)
|
||||
@@ -958,7 +947,6 @@ def test_raise_for_process_errors_with_warning_process_and_running_process_kills
|
||||
flexmock(module).should_receive('interpret_exit_code').with_args(
|
||||
object, 1, object, object
|
||||
).and_return(module.Exit_status.WARNING)
|
||||
flexmock(module).should_receive('log_remaining_buffer_lines').and_return(())
|
||||
command = flexmock()
|
||||
flexmock(module).should_receive('command_for_process').and_return(command)
|
||||
|
||||
@@ -966,7 +954,6 @@ def test_raise_for_process_errors_with_warning_process_and_running_process_kills
|
||||
module.raise_for_process_errors(
|
||||
buffer_readers,
|
||||
process_metadatas,
|
||||
output_log_level=None,
|
||||
borg_local_path=flexmock(),
|
||||
borg_exit_codes=flexmock(),
|
||||
)
|
||||
@@ -988,7 +975,6 @@ def test_raise_for_process_errors_with_error_process_and_running_process_kills_a
|
||||
flexmock(module).should_receive('interpret_exit_code').with_args(
|
||||
object, 3, object, object
|
||||
).and_return(module.Exit_status.ERROR)
|
||||
flexmock(module).should_receive('log_remaining_buffer_lines').and_return(())
|
||||
command = flexmock()
|
||||
flexmock(module).should_receive('command_for_process').and_return(command)
|
||||
|
||||
@@ -996,7 +982,6 @@ def test_raise_for_process_errors_with_error_process_and_running_process_kills_a
|
||||
module.raise_for_process_errors(
|
||||
buffer_readers,
|
||||
process_metadatas,
|
||||
output_log_level=None,
|
||||
borg_local_path=flexmock(),
|
||||
borg_exit_codes=flexmock(),
|
||||
)
|
||||
@@ -1013,7 +998,6 @@ def test_raise_for_process_errors_with_warning_process_and_long_output_raises_wi
|
||||
process: module.Process_metadata(last_lines=['hi', 'there'], capture=False)
|
||||
}
|
||||
flexmock(module).should_receive('interpret_exit_code').and_return(module.Exit_status.ERROR)
|
||||
flexmock(module).should_receive('log_remaining_buffer_lines').and_return(())
|
||||
command = flexmock()
|
||||
flexmock(module).should_receive('command_for_process').and_return(command)
|
||||
|
||||
@@ -1021,7 +1005,6 @@ def test_raise_for_process_errors_with_warning_process_and_long_output_raises_wi
|
||||
flexmock(module, ERROR_OUTPUT_MAX_LINE_COUNT=2).raise_for_process_errors(
|
||||
buffer_readers,
|
||||
process_metadatas,
|
||||
output_log_level=None,
|
||||
borg_local_path=flexmock(),
|
||||
borg_exit_codes=flexmock(),
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user