7 Module implementing the file system interface to the eric-ide server. |
7 Module implementing the file system interface to the eric-ide server. |
8 """ |
8 """ |
9 |
9 |
10 import base64 |
10 import base64 |
11 import contextlib |
11 import contextlib |
|
12 import fnmatch |
|
13 import os |
|
14 import re |
12 import stat |
15 import stat |
13 |
16 |
14 from PyQt6.QtCore import QEventLoop, QObject |
17 from PyQt6.QtCore import QEventLoop, QObject |
15 |
18 |
16 from eric7.RemoteServer.EricRequestCategory import EricRequestCategory |
19 from eric7.RemoteServer.EricRequestCategory import EricRequestCategory |
17 from eric7.SystemUtilities import FileSystemUtilities |
20 from eric7.SystemUtilities import FileSystemUtilities |
18 |
21 |
19 |
22 |
20 # TODO: sanitize all file names with FileSystemUtilities.plainFileName() |
|
21 class EricServerFileSystemInterface(QObject): |
23 class EricServerFileSystemInterface(QObject): |
22 """ |
24 """ |
23 Class implementing the file system interface to the eric-ide server. |
25 Class implementing the file system interface to the eric-ide server. |
24 """ |
26 """ |
25 |
27 |
|
28 _MagicCheck = re.compile("([*?[])") |
|
29 |
26 def __init__(self, serverInterface): |
30 def __init__(self, serverInterface): |
27 """ |
31 """ |
28 Constructor |
32 Constructor |
29 |
33 |
30 @param serverInterface reference to the eric-ide server interface |
34 @param serverInterface reference to the eric-ide server interface |
31 @type EricServerInterface |
35 @type EricServerInterface |
32 """ |
36 """ |
33 super().__init__(parent=serverInterface) |
37 super().__init__(parent=serverInterface) |
34 |
38 |
35 self.__serverInterface = serverInterface |
39 self.__serverInterface = serverInterface |
|
40 |
|
41 def __hasMagic(self, pathname): |
|
42 """ |
|
43 Private method to check, if a given path contains glob style magic characters. |
|
44 |
|
45 Note: This was taken from 'glob.glob'. |
|
46 |
|
47 @param pathname path name to be checked |
|
48 @type str |
|
49 @return flag indicating the presence of magic characters |
|
50 @rtype bool |
|
51 """ |
|
52 match = self._MagicCheck.search(pathname) |
|
53 return match is not None |
36 |
54 |
37 def getcwd(self): |
55 def getcwd(self): |
38 """ |
56 """ |
39 Public method to get the current working directory of the eric-ide server. |
57 Public method to get the current working directory of the eric-ide server. |
40 |
58 |
173 raise OSError(error) |
191 raise OSError(error) |
174 |
192 |
175 return listedDirectory, separator, listing |
193 return listedDirectory, separator, listing |
176 |
194 |
177 def direntries( |
195 def direntries( |
178 self, directory, filesonly=False, pattern=None, followsymlinks=True, ignore=None |
196 self, |
|
197 directory, |
|
198 filesonly=False, |
|
199 pattern=None, |
|
200 followsymlinks=True, |
|
201 ignore=None, |
|
202 recursive=True, |
|
203 dirsonly=False, |
179 ): |
204 ): |
180 """ |
205 """ |
181 Public method to get a list of all files and directories of a given directory. |
206 Public method to get a list of all files and directories of a given directory. |
182 |
207 |
183 @param directory root of the tree to check |
208 @param directory root of the tree to check |
190 @param followsymlinks flag indicating whether symbolic links should be |
215 @param followsymlinks flag indicating whether symbolic links should be |
191 followed (defaults to True) |
216 followed (defaults to True) |
192 @type bool (optional) |
217 @type bool (optional) |
193 @param ignore list of entries to be ignored (defaults to None) |
218 @param ignore list of entries to be ignored (defaults to None) |
194 @type list of str (optional) |
219 @type list of str (optional) |
|
220 @param recursive flag indicating a recursive search (defaults to True) |
|
221 @type bool (optional) |
|
222 @param dirsonly flag indicating to return only directories. When True it has |
|
223 precedence over the 'filesonly' parameter ((defaults to False) |
|
224 @type bool |
195 @return list of all files and directories in the tree rooted at path. |
225 @return list of all files and directories in the tree rooted at path. |
196 The names are expanded to start with the given directory name. |
226 The names are expanded to start with the given directory name. |
197 @rtype list of str |
227 @rtype list of str |
198 @exception OSError raised in case the server reported an issue |
228 @exception OSError raised in case the server reported an issue |
199 """ |
229 """ |
229 "directory": FileSystemUtilities.plainFileName(directory), |
259 "directory": FileSystemUtilities.plainFileName(directory), |
230 "files_only": filesonly, |
260 "files_only": filesonly, |
231 "pattern": [] if pattern is None else pattern, |
261 "pattern": [] if pattern is None else pattern, |
232 "follow_symlinks": followsymlinks, |
262 "follow_symlinks": followsymlinks, |
233 "ignore": [] if ignore is None else ignore, |
263 "ignore": [] if ignore is None else ignore, |
|
264 "recursive": recursive, |
|
265 "dirs_only": dirsonly, |
234 }, |
266 }, |
235 callback=callback, |
267 callback=callback, |
236 ) |
268 ) |
237 |
269 |
238 loop.exec() |
270 loop.exec() |
239 if not ok: |
271 if not ok: |
240 raise OSError(error) |
272 raise OSError(error) |
|
273 |
|
274 return result |
|
275 |
|
276 def glob(self, pathname, recursive=False, includeHidden=False): |
|
277 """ |
|
278 Public method to get a list of of all files matching a given pattern |
|
279 like 'glob.glob()'. |
|
280 |
|
281 @param pathname path name pattern with simple shell-style wildcards |
|
282 @type str |
|
283 @param recursive flag indicating a recursive list (defaults to False) |
|
284 @type bool (optional) |
|
285 @param includeHidden flag indicating to include hidden files (defaults to False) |
|
286 @type bool (optional) |
|
287 @return list of all files matching the pattern |
|
288 @rtype list of str |
|
289 """ |
|
290 result = [] |
|
291 |
|
292 pathname = FileSystemUtilities.plainFileName(pathname) |
|
293 dirname, basename = os.path.split(pathname) |
|
294 if dirname and not self.__hasMagic(dirname): |
|
295 with contextlib.suppress(OSError): |
|
296 entries = self.direntries( |
|
297 dirname, pattern=basename, recursive=recursive, filesonly=True |
|
298 ) |
|
299 if includeHidden: |
|
300 result = entries |
|
301 else: |
|
302 result = [e for e in entries if not e.startswith(".")] |
241 |
303 |
242 return result |
304 return result |
243 |
305 |
244 def stat(self, filename, stNames): |
306 def stat(self, filename, stNames): |
245 """ |
307 """ |