Source code for snapm.fsdiff.options
# Copyright Red Hat
#
# snapm/fsdiff/options.py - Snapshot Manager fs diff options
#
# This file is part of the snapm project.
#
# SPDX-License-Identifier: Apache-2.0
"""
File system diff options and categories.
"""
from dataclasses import dataclass, field, fields
from typing import Optional, Tuple, Union
from argparse import Namespace
from enum import Enum
import logging
_log = logging.getLogger(__name__)
_log_debug = _log.debug
_log_info = _log.info
_log_warn = _log.warning
_log_error = _log.error
[docs]@dataclass(frozen=True)
class DiffOptions:
"""
File system comparison options.
"""
#: Ignore timestamps in diff comparisons
ignore_timestamps: bool = False
#: Ignore permissions in diff comparisons
ignore_permissions: bool = False
#: Ignore ownership in diff comparisons
ignore_ownership: bool = False
#: Only consider content changes
content_only: bool = False
#: Include system directories in diff comparisons
include_system_dirs: bool = False
#: Generate content diffs for detected file modifications
include_content_diffs: bool = True
#: Generate file type information using magic
use_magic_file_type: bool = False
#: Follow symlinks when walking file system trees
follow_symlinks: bool = False
#: Maximum file size for diff comparisons
max_file_size: int = 0
#: Maximum size for generating content diffs
max_content_diff_size: int = 2**20
#: Maximum file size for generating content hashes
max_content_hash_size: int = 2**20
#: File patterns to include (glob notation)
file_patterns: Tuple[str, ...] = field(default_factory=tuple)
#: File patterns to exclude (glob notation)
exclude_patterns: Tuple[str, ...] = field(default_factory=tuple)
#: Start path(s) for file system comparison
from_path: Optional[Union[str, Tuple[str]]] = ("/",)
#: Do not output progress or status updates
quiet: bool = False
#: Disable RSS memory pressure safety checks
no_mem_check: bool = False
[docs] def __str__(self):
"""
Return a human readable string representation of this
``DiffOptions`` instance.
:returns: A human readable string.
:rtype: ``str``
"""
def _join_tuple(val: Tuple[str, ...]) -> str:
"""
Convert string tuples into space separated strings.
:param val: The value to join.
:type val: ``Tuple[str, ...]``
:returns: The string tuple value converted to a space separated
string.
:rtype: ``str``
"""
return " ".join(val)
items = [
(key, val) if not isinstance(val, tuple) else (key, _join_tuple(val))
for key, val in self.__dict__.items()
]
return "\n".join(f"{key}={val}" for key, val in items)
[docs] @classmethod
def from_cmd_args(cls, cmd_args: Namespace) -> "DiffOptions":
"""
Initialise DiffOptions from command line arguments.
Construct a new ``DiffOptions`` object from the command line
arguments in ``cmd_args``.
:param cmd_args: The command line selection arguments.
:type cmd_args: ``Namespace``
:returns: A new ``DiffOptions`` instance
:rtype: ``DiffOptions``
"""
def get_value(name: str) -> Union[bool, int, Optional[str], Tuple[str, ...]]:
"""
Get a value from ``cmd_args``, converting lists to tuples.
:param name: The name of the argument.
:type name: ``str``
:returns: The argument converted to a tuple if appropriate.
:rtype: ``Union[bool, int, str, Optional[str], Tuple[str, ...]]``
"""
attr = getattr(cmd_args, name)
if isinstance(attr, list):
return tuple(attr)
if attr is None and name in ("file_patterns", "exclude_patterns"):
return ()
return attr
field_names = {f.name for f in fields(cls)}
kwargs = {
name: get_value(name) for name in field_names if hasattr(cmd_args, name)
}
options = cls(**kwargs)
_log_debug("Initialised DiffOptions from arguments: %s", repr(options))
return options
[docs]class DiffCategories(Enum):
"""
Enum for categories of difference based on type or file system location.
"""
CRITICAL_SYSTEM = "critical_system" # /etc, /boot changes
USER_DATA = "user_data" # /home changes
APPLICATION = "application" # /usr, /opt changes
TEMPORARY = "temporary" # /tmp, /var/tmp
LOG_FILES = "log_files" # /var/log changes
PACKAGE_MANAGEMENT = "package_mgmt" # Package-related changes