From 97d94a698671a0ba88655dde70a8ebb545eda71c Mon Sep 17 00:00:00 2001 From: buhtz Date: Tue, 4 Jun 2024 22:21:24 +0200 Subject: [PATCH 01/18] prototyp --- common/flock.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/common/flock.py b/common/flock.py index baa8f6de3..b75503057 100644 --- a/common/flock.py +++ b/common/flock.py @@ -10,6 +10,7 @@ from pathlib import Path import logger +logger.DEBUG = True class _FlockContext: """Context manager to manage file locks (flock). @@ -38,6 +39,20 @@ def __init__(self, filename: str, folder: Path = None): self._file_path = folder / filename """Path to used for flock""" + if not self._file_path.exists(): + try: + self._file_path.touch() + except PermissionError: + self._file_path = self._determine_user_flock(filename) + + def _determine_user_flock(self, filename: str): + folder = Path(Path.cwd().root) / 'run' / 'user' + folder = folder / str(os.getuid()) / filename + + logger.info(f'{folder=}') + + folder.touch() + def __enter__(self): self._log('Set') From 90d79d297b421730c5ce0cde7070078884ddc834 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Wed, 5 Jun 2024 22:15:37 +0200 Subject: [PATCH 02/18] x --- common/flock.py | 37 +++++++++++++++++++++++++------------ 1 file changed, 25 insertions(+), 12 deletions(-) diff --git a/common/flock.py b/common/flock.py index b75503057..b9e1c5678 100644 --- a/common/flock.py +++ b/common/flock.py @@ -10,7 +10,8 @@ from pathlib import Path import logger -logger.DEBUG = True +logger.DEBUG = True # REMOVE BEFORE MERGE + class _FlockContext: """Context manager to manage file locks (flock). @@ -37,21 +38,33 @@ def __init__(self, filename: str, folder: Path = None): folder = Path(Path.cwd().root) / 'var' / 'lock' self._file_path = folder / filename - """Path to used for flock""" + """Path used for flock""" + + if not self._can_use_file(self._file_path): + # Try user specific file lock + self._file_path = Path(os.environ['XDG_RUNTIME_DIR']) / filename + + if not self._can_use_file(self._file_path): + # Last try users cache dir + self._file_path \ + = Path(os.environ.get('XDG_CACHE_HOME', '~/.cache')) / filename - if not self._file_path.exists(): - try: - self._file_path.touch() - except PermissionError: - self._file_path = self._determine_user_flock(filename) + if not self._can_use_file(self._file_path): + raise RuntimeError('Can not set global flock') - def _determine_user_flock(self, filename: str): - folder = Path(Path.cwd().root) / 'run' / 'user' - folder = folder / str(os.getuid()) / filename + def _can_use_file(self, file_path: Path) -> bool: + """ + """ + if file_path.exists(): + return True - logger.info(f'{folder=}') + # Try to create it + try: + file_path.touch(mode=0o666) + except PermissionError: + logger.info(f'Cannot use file lock on {file_path}.') - folder.touch() + return False def __enter__(self): self._log('Set') From 6bbaf629a25383dd57443425ff3427c3aea23bfa Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Wed, 5 Jun 2024 22:21:50 +0200 Subject: [PATCH 03/18] X --- common/flock.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/common/flock.py b/common/flock.py index b9e1c5678..bd52b0239 100644 --- a/common/flock.py +++ b/common/flock.py @@ -63,6 +63,8 @@ def _can_use_file(self, file_path: Path) -> bool: file_path.touch(mode=0o666) except PermissionError: logger.info(f'Cannot use file lock on {file_path}.') + else: + logger.info(f'Use {file_path} for file lock.') return False From 6b40e84c22ac8d817d7cf1e94dee4dc9e8a113f3 Mon Sep 17 00:00:00 2001 From: buhtz Date: Wed, 5 Jun 2024 22:29:38 +0200 Subject: [PATCH 04/18] x --- common/flock.py | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/common/flock.py b/common/flock.py index bd52b0239..d4a9e102b 100644 --- a/common/flock.py +++ b/common/flock.py @@ -62,9 +62,14 @@ def _can_use_file(self, file_path: Path) -> bool: try: file_path.touch(mode=0o666) except PermissionError: - logger.info(f'Cannot use file lock on {file_path}.') + logger.debug(f'Cannot use file lock on {file_path}.') + except Exception as err: + logger.error(f'Unknown error while testing file ' + f'lock on {file_path}. Error was {err}.') else: - logger.info(f'Use {file_path} for file lock.') + print('X'*100) + logger.debug(f'Use {file_path} for file lock.') + return True return False From 21cfe6066182d19e07e8fd3f478d419f25c58612 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Thu, 6 Jun 2024 17:32:27 +0200 Subject: [PATCH 05/18] docstring --- common/flock.py | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/common/flock.py b/common/flock.py index d4a9e102b..73ac46cad 100644 --- a/common/flock.py +++ b/common/flock.py @@ -16,8 +16,10 @@ class _FlockContext: """Context manager to manage file locks (flock). - The flock file is stored in the folder `/run/lock` or if not present in - `/var/lock`. + It will be tried to establish a multi-user file lock; if not feasible a + single-user file lock will be used. It depends on the GNU Linux + distribution used and the write permissions to the file lock locations in + the file system. Usage example :: @@ -28,6 +30,22 @@ def __init__(self): with MyFlock(): do_fancy_things() + The following directories will be checked in sequence to determine if they + exist, if a file lock file exists within them, or if there are sufficient + permissions to create such a file within them. :: + + /run/lock + /var/lock + /run/user// + ~/.cache + + The first and second directory in that list is for multi-user file lock. + + To the experience of the developers on Debian-based distributions there is + no problem having a multi-user file lock. But on Arch-based distributions + only a user with root privileges is able to do it. Because of that on Arch + a single-user file lock is used by default until Back In Time is started + once as root. """ def __init__(self, filename: str, folder: Path = None): if folder is None: @@ -42,6 +60,7 @@ def __init__(self, filename: str, folder: Path = None): if not self._can_use_file(self._file_path): # Try user specific file lock + # e.g. /run/user/ self._file_path = Path(os.environ['XDG_RUNTIME_DIR']) / filename if not self._can_use_file(self._file_path): From 8d03c4dcb73e6eb3094fa146dbb66018cc8ffb68 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Thu, 6 Jun 2024 20:37:50 +0200 Subject: [PATCH 06/18] x --- common/flock.py | 51 ++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 20 deletions(-) diff --git a/common/flock.py b/common/flock.py index 73ac46cad..4239f8af4 100644 --- a/common/flock.py +++ b/common/flock.py @@ -47,29 +47,39 @@ def __init__(self): a single-user file lock is used by default until Back In Time is started once as root. """ - def __init__(self, filename: str, folder: Path = None): - if folder is None: - folder = Path(Path.cwd().root) / 'run' / 'lock' + def __init__(self, + filename: str, + disable: bool = False): + folder = Path(Path.cwd().root) / 'run' / 'lock' - # out-dated default - if not folder.exists(): - folder = Path(Path.cwd().root) / 'var' / 'lock' + if not folder.exists(): + # On older systems + folder = Path(Path.cwd().root) / 'var' / 'lock' self._file_path = folder / filename - """Path used for flock""" + """Full path used for the flock file""" - if not self._can_use_file(self._file_path): - # Try user specific file lock - # e.g. /run/user/ - self._file_path = Path(os.environ['XDG_RUNTIME_DIR']) / filename + if self._can_use_file(self._file_path): + return - if not self._can_use_file(self._file_path): - # Last try users cache dir - self._file_path \ - = Path(os.environ.get('XDG_CACHE_HOME', '~/.cache')) / filename + # Try user specific file lock + # e.g. /run/user/ + self._file_path = Path(os.environ['XDG_RUNTIME_DIR']) / filename - if not self._can_use_file(self._file_path): - raise RuntimeError('Can not set global flock') + if self._can_use_file(self._file_path): + return + + # At last, try users cache dir. + self._file_path = Path( + os.environ.get('XDG_CACHE_HOME', + Path.home() / 'cache') + ) / filename + + if self._can_use_file(self._file_path): + return + + raise RuntimeError( + f'Can not establish global flock file {self._file_path}') def _can_use_file(self, file_path: Path) -> bool: """ @@ -80,13 +90,14 @@ def _can_use_file(self, file_path: Path) -> bool: # Try to create it try: file_path.touch(mode=0o666) + except PermissionError: logger.debug(f'Cannot use file lock on {file_path}.') + except Exception as err: logger.error(f'Unknown error while testing file ' f'lock on {file_path}. Error was {err}.') else: - print('X'*100) logger.debug(f'Use {file_path} for file lock.') return True @@ -124,5 +135,5 @@ def _log(self, prefix: str): class GlobalFlock(_FlockContext): """Flock context manager used for global flock in Back In Time.""" - def __init__(self): - super().__init__('backintime.lock') + def __init__(self, disable: bool = False): + super().__init__('backintime.lock', disable=disable) From 5b4918cb6773c7544d5b98c20d98de6c2f3605c5 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Fri, 7 Jun 2024 11:31:08 +0200 Subject: [PATCH 07/18] #1751 workaround using "disabled". Improved docstrings and fixed that damn Sphinx config again" --- common/doc-dev/conf.py | 170 +++-------------------------------------- common/flock.py | 75 +++++++++++++++--- common/tools.py | 48 ++++++------ 3 files changed, 94 insertions(+), 199 deletions(-) diff --git a/common/doc-dev/conf.py b/common/doc-dev/conf.py index e61e7ed2e..d84fc3034 100644 --- a/common/doc-dev/conf.py +++ b/common/doc-dev/conf.py @@ -1,18 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- -# -# BackInTime documentation build configuration file, created by -# sphinx-quickstart on Sat Jan 9 00:04:35 2016. -# -# This file is execfile()d with the current directory set to its -# containing dir. -# -# Note that not all possible configuration values are present in this -# autogenerated file. -# -# All configuration values have a default; values that are commented out -# serve to show the default. - import sys import os @@ -24,17 +10,11 @@ sys.path.insert(0, os.path.abspath(os.path.join(os.pardir))) sys.path.insert(0, os.path.abspath(os.path.join(os.pardir, "plugins"))) -#import config to solve race conditions between config an mount +# Import to solve race conditions between config an mount. import config # -- General configuration ------------------------------------------------ -# If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' - -# Add any Sphinx extension module names here, as strings. They can be -# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom -# ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.napoleon', @@ -49,9 +29,6 @@ # The suffix of source filenames. source_suffix = '.rst' -# The encoding of source files. -#source_encoding = 'utf-8-sig' - # The master toctree document. master_doc = 'index' @@ -66,43 +43,21 @@ # The full version, including alpha/beta/rc tags. release = version # '1.3.3-dev' -# The language for content autogenerated by Sphinx. Refer to documentation -# for a list of supported languages. -#language = None - -# There are two options for replacing |today|: either, you set today to some -# non-false value, then it is used: -#today = '' -# Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' - # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] -# The reST default role (used for this markup: `text`) to use for all -# documents. -#default_role = None - -# If true, '()' will be appended to :func: etc. cross-reference text. -#add_function_parentheses = True - -# If true, the current module name will be prepended to all description -# unit titles (such as .. function::). -#add_module_names = True - -# If true, sectionauthor and moduleauthor directives will be shown in the -# output. They are ignored by default. -#show_authors = False - # The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' -# A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] - -# If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +autodoc_default_options = { + 'members': True, + 'member-order': 'bysource', + 'private-members': True, + 'undoc-members': True, + 'special-members': True, + 'exclude-members': '__weakref__,__dict__,__module__,__annotations__', +} # -- Intersphinx options -------------------------------------------------- @@ -111,95 +66,26 @@ } # -- Napoleon include private members which have docstrings --------------- - napoleon_include_private_with_doc = True # -- Options for HTML output ---------------------------------------------- - # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. # html_theme = 'classic' html_theme = 'sphinx_rtd_theme' -# Theme options are theme-specific and customize the look and feel of a theme -# further. For a list of options available for each theme, see the -# documentation. -#html_theme_options = {} - -# Add any paths that contain custom themes here, relative to this directory. -#html_theme_path = [] - -# The name for this set of Sphinx documents. If None, it defaults to -# " v documentation". -#html_title = None - -# A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None - -# The name of an image file (relative to this directory) to place at the top -# of the sidebar. -#html_logo = None - -# The name of an image file (within the static path) to use as favicon of the -# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 -# pixels large. -#html_favicon = None - # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] -# Add any extra paths that contain custom files (such as robots.txt or -# .htaccess) here, relative to this directory. These files are copied -# directly to the root of the documentation. -#html_extra_path = [] - # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. html_last_updated_fmt = '%b %d, %Y, %H:%M (%Z)' -# If true, SmartyPants will be used to convert quotes and dashes to -# typographically correct entities. -#html_use_smartypants = True - -# Custom sidebar templates, maps document names to template names. -#html_sidebars = {} - -# Additional templates that should be rendered to pages, maps page names to -# template names. -#html_additional_pages = {} - -# If false, no module index is generated. -#html_domain_indices = True - -# If false, no index is generated. -#html_use_index = True - -# If true, the index is split into individual pages for each letter. -#html_split_index = False - -# If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True - -# If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True - -# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True - -# If true, an OpenSearch description file will be output, and all pages will -# contain a tag referring to it. The value of this option must be the -# base URL from which the finished HTML is served. -#html_use_opensearch = '' - -# This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None - # Output file base name for HTML help builder. htmlhelp_basename = 'BackInTimeDevDoc' - # -- Options for LaTeX output --------------------------------------------- latex_elements = { @@ -221,27 +107,6 @@ 'Germar Reitze', 'manual'), ] -# The name of an image file (relative to this directory) to place at the top of -# the title page. -#latex_logo = None - -# For "manual" documents, if this is true, then toplevel headings are parts, -# not chapters. -#latex_use_parts = False - -# If true, show page references after internal links. -#latex_show_pagerefs = False - -# If true, show URL addresses after external links. -#latex_show_urls = False - -# Documents to append as an appendix to all manuals. -#latex_appendices = [] - -# If false, no module index is generated. -#latex_domain_indices = True - - # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples @@ -251,10 +116,6 @@ ['Germar Reitze'], 1) ] -# If true, show URL addresses after external links. -#man_show_urls = False - - # -- Options for Texinfo output ------------------------------------------- # Grouping the document tree into Texinfo files. List of tuples @@ -266,16 +127,3 @@ 'Miscellaneous'), ] -# Documents to append as an appendix to all manuals. -#texinfo_appendices = [] - -# If false, no module index is generated. -#texinfo_domain_indices = True - -# How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' - -# If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False -# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, -# using the given strftime format. diff --git a/common/flock.py b/common/flock.py index 4239f8af4..1d67ac465 100644 --- a/common/flock.py +++ b/common/flock.py @@ -50,6 +50,29 @@ def __init__(self): def __init__(self, filename: str, disable: bool = False): + """Check if an flock file can be used or created. + + See the classes documentation about details. + + Args: + filename: The filename (without path) used for the flock file. + disabled: Disable the whole context managers behavior. This is a + workaround. See #1751 and :func:``Snapshots.backup()`` for + details. + + Raises: + RuntimeError: If it wasn't possible to use + """ + self._file_path = None + """Full path used for the flock file""" + + self._flock_handle = None + """File handle (descriptor) to the flock file.""" + + # Workaround for #1751. Remove after refactoring Snapshots.backup() + if disable: + return + folder = Path(Path.cwd().root) / 'run' / 'lock' if not folder.exists(): @@ -82,7 +105,18 @@ def __init__(self, f'Can not establish global flock file {self._file_path}') def _can_use_file(self, file_path: Path) -> bool: - """ + """Check if ``file_path`` is usable as an flock file. + + The answer is ``True`` if the file exists without checking its + permissions. If not the file will be created and if successfull + ``True`` will be returned. + + Returns: + bool: The answer. + + Raises: + PermissionError: Not enough permissions to create the file. + Exception: Any other error. """ if file_path.exists(): return True @@ -95,8 +129,10 @@ def _can_use_file(self, file_path: Path) -> bool: logger.debug(f'Cannot use file lock on {file_path}.') except Exception as err: - logger.error(f'Unknown error while testing file ' - f'lock on {file_path}. Error was {err}.') + logger.error( + f'Unknown error while testing file lock on {file_path}. ' + f'Please open a bug report. Error was {err}.') + else: logger.debug(f'Use {file_path} for file lock.') return True @@ -104,23 +140,29 @@ def _can_use_file(self, file_path: Path) -> bool: return False def __enter__(self): + """Request an exclucive file lock on :data:``self._file_path``. + """ + # Workaround for #1751. Remove after refactoring Snapshots.backup() + # See __init__() for details + if self._file_path is None: + return + self._log('Set') - # Open (and create if needed) the file - mode = 'r' if self._file_path.exists() else 'w' - self._flock_handle = self._file_path.open(mode) + # Open file for reading + self._flock_handle = self._file_path.open(mode='r') # blocks (waits) until an existing flock is released fcntl.flock(self._flock_handle, fcntl.LOCK_EX) - # If new created file set itspermissions to "rw-rw-rw". - # otherwise a foreign user is not able to use it. - if mode == 'w': - self._file_path.chmod(int('0o666', 8)) - return self def __exit__(self, exc_type, exc_value, exc_tb): + # Workaround for #1751. Remove after refactoring Snapshots.backup() + # See __init__() for details + if self._flock_handle is None: + return + self._log('Release') fcntl.fcntl(self._flock_handle, fcntl.LOCK_UN) self._flock_handle.close() @@ -128,12 +170,21 @@ def __exit__(self, exc_type, exc_value, exc_tb): def _log(self, prefix: str): """Generate a log message including the current lock files path and the process ID. + + Args: + prefix: Used in front of the log message. """ logger.debug(f'{prefix} flock {self._file_path} by PID {os.getpid()}', self) class GlobalFlock(_FlockContext): - """Flock context manager used for global flock in Back In Time.""" + """Context manager used for global file lock in Back In Time. + + If it is a multi-user or single-user flock depends on the several + aspects. See :class:`_FlockContext` for details. + """ def __init__(self, disable: bool = False): + """See :func:`_FlockContext.__init__()` for details. + """ super().__init__('backintime.lock', disable=disable) diff --git a/common/tools.py b/common/tools.py index 7bdac7e77..3ce243ba5 100644 --- a/common/tools.py +++ b/common/tools.py @@ -89,19 +89,20 @@ # | Handling paths | # |-----------------| - def sharePath(): """Get path where Back In Time is installed. - This is similar to $XDG_DATA_DIRS (XDG Base Directory Specification). - If running from source return default ``/usr/share``. + This is similar to ``XDG_DATA_DIRS``. If running from source return + default ``/usr/share``. - Returns: - str: share path like:: + Share path like: :: - /usr/share - /usr/local/share - /opt/usr/share + /usr/share + /usr/local/share + /opt/usr/share + + Returns: + str: Share path. """ share = os.path.abspath( os.path.join(__file__, os.pardir, os.pardir, os.pardir) @@ -115,16 +116,14 @@ def sharePath(): def backintimePath(*path): """ - Get path inside 'backintime' install folder. + Get path inside ``backintime`` install folder. Args: - *path (str): paths that should be joined to 'backintime' + *path (str): Paths that should be joined to ``backintime``. Returns: - str: 'backintime' child path like:: - - /usr/share/backintime/common - /usr/share/backintime/qt + str: Child path of ``backintime`` child path e.g. + ``/usr/share/backintime/common``or ``/usr/share/backintime/qt``. """ return os.path.abspath(os.path.join(__file__, os.pardir, os.pardir, *path)) @@ -2021,20 +2020,17 @@ class Alarm(object): (reentrance) or you may cause non-deterministic "random" RTEs. """ def __init__(self, callback = None, overwrite = True): - """ - Create a new alarm instance + """Create a new alarm instance Args: - callback: Function to call when the timer ran down - (ensure calling only reentrant code). - Use ``None`` to throw a ``Timeout`` exception instead. - overwrite: Is it allowed to (re)start the timer - even though the current timer is still running - ("ticking"): - ``True`` cancels the current timer (if active) - and restarts with the new timeout. - ``False` silently ignores the start request - if the current timer is still "ticking" + callback: Function to call when the timer ran down (ensure + calling only reentrant code). Use ``None`` to throw a + ``Timeout`` exception instead. + overwrite: Is it allowed to (re)start the timer even though the + current timer is still running ("ticking"). ``True`` cancels + the current timer (if active) and restarts with the new + timeout. ``False`` silently ignores the start request if the + current timer is still "ticking" """ self.callback = callback self.ticking = False From b56050149a6a4893d5a72c5b8a2446377801640b Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Fri, 7 Jun 2024 11:38:20 +0200 Subject: [PATCH 08/18] changelock --- CHANGES | 1 + common/snapshots.py | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index d4df5235c..4a14346c5 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,7 @@ Back In Time Version 1.4.4-dev (development of upcoming release) +* Fix: Global flock fallback to single-user mode if not enough permissions (#1743) * Fix: Names of weekdays and months translated correct (#1729) * Fix: Global flock for multiple users (#1122, #1676) * Fix bug: "Backup folders" list does reflect the selected snapshot (#1585) (@rafaelhdr Rafael Hurpia da Rocha) diff --git a/common/snapshots.py b/common/snapshots.py index 55f082b52..a37e52d8f 100644 --- a/common/snapshots.py +++ b/common/snapshots.py @@ -779,10 +779,11 @@ def backup(self, force=False): instance.startApplication() - # global flock to block backups from other profiles or users - # (and run them serialized) - # self.flockExclusive() - with flock.GlobalFlock(): + # Global flock to block backups from other profiles or users + # (and run them serialized). The argument "disabled" is a + # workaround (#1751) that should be removed/refactored after + # this method ("backup()") is refactored. + with flock.GlobalFlock(disable=not self.config.globalFlock()): logger.info('Lock', self) now = datetime.datetime.today() From 52fdd7a7be7de98d9bcba317c4560c5e2d637913 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Fri, 7 Jun 2024 11:53:30 +0200 Subject: [PATCH 09/18] fix typo [skip ci] --- common/flock.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/flock.py b/common/flock.py index 1d67ac465..610c02a9a 100644 --- a/common/flock.py +++ b/common/flock.py @@ -108,7 +108,7 @@ def _can_use_file(self, file_path: Path) -> bool: """Check if ``file_path`` is usable as an flock file. The answer is ``True`` if the file exists without checking its - permissions. If not the file will be created and if successfull + permissions. If not the file will be created and if successful ``True`` will be returned. Returns: From 4b01a570857a48f340c867eadf90142653982160 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Fri, 7 Jun 2024 13:01:41 +0200 Subject: [PATCH 10/18] fix docstring [skip ci] --- common/flock.py | 1 - 1 file changed, 1 deletion(-) diff --git a/common/flock.py b/common/flock.py index 610c02a9a..122f4459d 100644 --- a/common/flock.py +++ b/common/flock.py @@ -80,7 +80,6 @@ def __init__(self, folder = Path(Path.cwd().root) / 'var' / 'lock' self._file_path = folder / filename - """Full path used for the flock file""" if self._can_use_file(self._file_path): return From 84226f32bfe04f8c5e76041e9e03d17e44ef85f0 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Fri, 7 Jun 2024 15:35:47 +0200 Subject: [PATCH 11/18] mod logging --- common/flock.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/common/flock.py b/common/flock.py index 122f4459d..eabbb2841 100644 --- a/common/flock.py +++ b/common/flock.py @@ -173,8 +173,7 @@ def _log(self, prefix: str): Args: prefix: Used in front of the log message. """ - logger.debug(f'{prefix} flock {self._file_path} by PID {os.getpid()}', - self) + logger.debug(f'{prefix} flock {self._file_path} by PID {os.getpid()}') class GlobalFlock(_FlockContext): From 3ec3a14a677b3c2a9b7fa704215de2c3e6f34dfa Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Mon, 17 Jun 2024 14:33:57 +0200 Subject: [PATCH 12/18] add missing translator credits [skip ci] --- TRANSLATIONS | 1 + 1 file changed, 1 insertion(+) diff --git a/TRANSLATIONS b/TRANSLATIONS index df438aa80..0b639f5b6 100644 --- a/TRANSLATIONS +++ b/TRANSLATIONS @@ -3,6 +3,7 @@ Bokmål (Norwegian) [nb_NO]: Hans Fredrik Nordhaug Catalan [ca]: Josep Sanchez Chinese (Simplified) [zh_CN,zh_Hans]: Kuntao Zhao Chinese (Traditional) [zh_TW,zh_Hant]: Kuntao Zhao +Danish [da]: Adam Sjøgren German [de]: Michael Wiedmann French [fr]: Michel Corps , jej@github Indonesian [id]: Andika Triwidada From 55735e74f73e251135bae93455618c374cebe635 Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Mon, 17 Jun 2024 16:03:37 +0200 Subject: [PATCH 13/18] add missing Greek translator [skip ci] --- TRANSLATIONS | 1 + 1 file changed, 1 insertion(+) diff --git a/TRANSLATIONS b/TRANSLATIONS index 0b639f5b6..d74f9b2aa 100644 --- a/TRANSLATIONS +++ b/TRANSLATIONS @@ -5,6 +5,7 @@ Chinese (Simplified) [zh_CN,zh_Hans]: Kuntao Zhao Chinese (Traditional) [zh_TW,zh_Hant]: Kuntao Zhao Danish [da]: Adam Sjøgren German [de]: Michael Wiedmann +Greek [el]: Iliana Panagopoulou (hpanago) French [fr]: Michel Corps , jej@github Indonesian [id]: Andika Triwidada Japanese [ja]: Ayako Buhtz From 2434e05c8e4bacb9b404110d775005f8298854cd Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Wed, 19 Jun 2024 09:38:34 +0200 Subject: [PATCH 14/18] fix linter error --- common/doc-dev/conf.py | 1 - 1 file changed, 1 deletion(-) diff --git a/common/doc-dev/conf.py b/common/doc-dev/conf.py index d1b840c71..65a156daa 100644 --- a/common/doc-dev/conf.py +++ b/common/doc-dev/conf.py @@ -128,4 +128,3 @@ 'Germar Reitze', 'BackInTime', 'One line description of project.', 'Miscellaneous'), ] - From e196098adc2abe1e8fe1c140d092e5786b806aaf Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Mon, 1 Jul 2024 13:09:01 +0200 Subject: [PATCH 15/18] remove debug code and add modul docstring --- common/flock.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/common/flock.py b/common/flock.py index eabbb2841..ec794d1f7 100644 --- a/common/flock.py +++ b/common/flock.py @@ -5,13 +5,15 @@ # This file is part of the program "Back In time" which is released under GNU # General Public License v2 (GPLv2). # See file LICENSE or go to . +"""Manage file lock. + +Offer context managers to manage file lock (flock) files. +""" import os import fcntl from pathlib import Path import logger -logger.DEBUG = True # REMOVE BEFORE MERGE - class _FlockContext: """Context manager to manage file locks (flock). From 4271c5bb69defb496fba27e4a3e38b873ab6c6bd Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Sat, 6 Jul 2024 14:22:57 +0200 Subject: [PATCH 16/18] improve changelog [skip ci] --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index e6e2b60dc..18d4b76d1 100644 --- a/CHANGES +++ b/CHANGES @@ -1,7 +1,7 @@ Back In Time Version 1.4.4-dev (development of upcoming release) -* Fix: Global flock fallback to single-user mode if not enough permissions (#1743) +* Fix: Fallback to single-user mode if insufficient permissions for global flock (#1743, #1751) * Chore!: Remove "debian" folder (#1548) * Breaking Change: EncFS deprecation warning (#1735, #1734) * Fix: Fix Qt segmentation fault with uninstall ExtraMouseButtonEventFilter when closing main window (#1095) From 01af2b0411d81ea5917ee54a480150915e60508c Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Sat, 6 Jul 2024 14:24:26 +0200 Subject: [PATCH 17/18] improve changelog [skip ci] --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 18d4b76d1..bd2efca3e 100644 --- a/CHANGES +++ b/CHANGES @@ -1,7 +1,7 @@ Back In Time Version 1.4.4-dev (development of upcoming release) -* Fix: Fallback to single-user mode if insufficient permissions for global flock (#1743, #1751) +* Fix: Global flock with fallback to single-user mode if insufficient permissions (#1743, #1751) * Chore!: Remove "debian" folder (#1548) * Breaking Change: EncFS deprecation warning (#1735, #1734) * Fix: Fix Qt segmentation fault with uninstall ExtraMouseButtonEventFilter when closing main window (#1095) From 96cb6a399d6b0879f609048deda31e98ac2e67bc Mon Sep 17 00:00:00 2001 From: Christian Buhtz Date: Sat, 6 Jul 2024 14:26:51 +0200 Subject: [PATCH 18/18] improve changelog [skip ci] --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index bd2efca3e..972d016f4 100644 --- a/CHANGES +++ b/CHANGES @@ -1,7 +1,7 @@ Back In Time Version 1.4.4-dev (development of upcoming release) -* Fix: Global flock with fallback to single-user mode if insufficient permissions (#1743, #1751) +* Fix: Global flock fallback to single-user mode if insufficient permissions (#1743, #1751) * Chore!: Remove "debian" folder (#1548) * Breaking Change: EncFS deprecation warning (#1735, #1734) * Fix: Fix Qt segmentation fault with uninstall ExtraMouseButtonEventFilter when closing main window (#1095)