diff -r 8264ea1f42e5 -r 2114cc7275e8 src/eric7/RemoteServerInterface/EricServerFileSystemInterface.py --- a/src/eric7/RemoteServerInterface/EricServerFileSystemInterface.py Sat Feb 17 11:26:37 2024 +0100 +++ b/src/eric7/RemoteServerInterface/EricServerFileSystemInterface.py Sat Feb 17 19:46:33 2024 +0100 @@ -9,6 +9,9 @@ import base64 import contextlib +import fnmatch +import os +import re import stat from PyQt6.QtCore import QEventLoop, QObject @@ -17,12 +20,13 @@ from eric7.SystemUtilities import FileSystemUtilities -# TODO: sanitize all file names with FileSystemUtilities.plainFileName() class EricServerFileSystemInterface(QObject): """ Class implementing the file system interface to the eric-ide server. """ + _MagicCheck = re.compile("([*?[])") + def __init__(self, serverInterface): """ Constructor @@ -34,6 +38,20 @@ self.__serverInterface = serverInterface + def __hasMagic(self, pathname): + """ + Private method to check, if a given path contains glob style magic characters. + + Note: This was taken from 'glob.glob'. + + @param pathname path name to be checked + @type str + @return flag indicating the presence of magic characters + @rtype bool + """ + match = self._MagicCheck.search(pathname) + return match is not None + def getcwd(self): """ Public method to get the current working directory of the eric-ide server. @@ -175,7 +193,14 @@ return listedDirectory, separator, listing def direntries( - self, directory, filesonly=False, pattern=None, followsymlinks=True, ignore=None + self, + directory, + filesonly=False, + pattern=None, + followsymlinks=True, + ignore=None, + recursive=True, + dirsonly=False, ): """ Public method to get a list of all files and directories of a given directory. @@ -192,6 +217,11 @@ @type bool (optional) @param ignore list of entries to be ignored (defaults to None) @type list of str (optional) + @param recursive flag indicating a recursive search (defaults to True) + @type bool (optional) + @param dirsonly flag indicating to return only directories. When True it has + precedence over the 'filesonly' parameter ((defaults to False) + @type bool @return list of all files and directories in the tree rooted at path. The names are expanded to start with the given directory name. @rtype list of str @@ -231,6 +261,8 @@ "pattern": [] if pattern is None else pattern, "follow_symlinks": followsymlinks, "ignore": [] if ignore is None else ignore, + "recursive": recursive, + "dirs_only": dirsonly, }, callback=callback, ) @@ -241,6 +273,36 @@ return result + def glob(self, pathname, recursive=False, includeHidden=False): + """ + Public method to get a list of of all files matching a given pattern + like 'glob.glob()'. + + @param pathname path name pattern with simple shell-style wildcards + @type str + @param recursive flag indicating a recursive list (defaults to False) + @type bool (optional) + @param includeHidden flag indicating to include hidden files (defaults to False) + @type bool (optional) + @return list of all files matching the pattern + @rtype list of str + """ + result = [] + + pathname = FileSystemUtilities.plainFileName(pathname) + dirname, basename = os.path.split(pathname) + if dirname and not self.__hasMagic(dirname): + with contextlib.suppress(OSError): + entries = self.direntries( + dirname, pattern=basename, recursive=recursive, filesonly=True + ) + if includeHidden: + result = entries + else: + result = [e for e in entries if not e.startswith(".")] + + return result + def stat(self, filename, stNames): """ Public method to get the status of a file.