From 870d9c665a88250653db97cc5c08449cf14e9c64 Mon Sep 17 00:00:00 2001 From: Paul Albertella Date: Wed, 4 Sep 2024 16:37:58 +0100 Subject: [PATCH] Allow references to hidden file paths Doorstop excludes hidden files from paths included in its representation of the version control system files, but this means that e.g. CI config files in a hidden folder cannot be included in the references of an item. This patch allows users to specify file patterns that should not be hidden in a file (default name: .doorstop_unhidden) --- doorstop/core/vcs/base.py | 28 ++++++++++++++++++++++++++++ doorstop/settings.py | 3 +++ 2 files changed, 31 insertions(+) diff --git a/doorstop/core/vcs/base.py b/doorstop/core/vcs/base.py index ac67ca6d..d4ab1e37 100644 --- a/doorstop/core/vcs/base.py +++ b/doorstop/core/vcs/base.py @@ -22,6 +22,7 @@ class BaseWorkingCopy(metaclass=ABCMeta): def __init__(self, path): self.path = path self._ignores_cache: Optional[List[str]] = None + self._unhidden_cache: Optional[List[str]] = None self._path_cache: Optional[List[Tuple[str, str, str]]] = None @staticmethod @@ -81,6 +82,21 @@ def ignores(self): self._ignores_cache.append(pattern + "*") yield from self._ignores_cache + @property + def unhidden(self): + """Yield glob expressions for paths that should not be hidden.""" + if self._unhidden_cache is None: + self._unhidden_cache = [] + log.debug("reading and caching the unhidden patterns...") + path = os.path.join(self.path, settings.UNHIDDEN_FILEPATH) + if os.path.isfile(path): + for line in common.read_lines(path): + log.debug(f"unhiding {line}") + pattern = line.strip(" @\\/*\n") + if pattern and not pattern.startswith("#"): + self._unhidden_cache.append("*" + pattern + "*") + yield from self._unhidden_cache + @property def paths(self): """Yield non-ignored paths in the working copy.""" @@ -94,6 +110,11 @@ def paths(self): # Skip ignored paths if self.ignored(relpath): continue + # Don't skip unhidden paths + if self.is_unhidden(relpath): + log.debug(f"not skipping: {relpath}") + self._path_cache.append((path, filename, relpath)) + continue # Skip hidden paths if os.path.sep + "." in os.path.sep + relpath: continue @@ -106,3 +127,10 @@ def ignored(self, path): if fnmatch.fnmatch(path, pattern): return True return False + + def is_unhidden(self, path): + """Determine if a path matches a pattern that should not hidden.""" + for pattern in self.unhidden: + if fnmatch.fnmatch(path, pattern): + return True + return False diff --git a/doorstop/settings.py b/doorstop/settings.py index bb474162..b568e577 100644 --- a/doorstop/settings.py +++ b/doorstop/settings.py @@ -64,3 +64,6 @@ # Server settings SERVER_HOST = None # '' = server not specified, None = no server in use SERVER_PORT = 7867 + +# Unhidden file +UNHIDDEN_FILEPATH = ".doorstop_unhidden" # list of paths that should not be hidden