file_manager: fix sync issues with hidden directories

While inotify watches are not applied to hidden directories it is still valid to use Moonraker's endpoints to perform operations on them.  When performing an operation on an item within a hidden directory, or on a hidden directory itself,  do not sync the request with inotify.

Signed-off-by:  Eric Callahan <arksine.code@gmail.com>
This commit is contained in:
Arksine 2021-05-20 08:35:26 -04:00
parent e7ca2d6adc
commit c335b62d26
1 changed files with 23 additions and 8 deletions

View File

@ -192,6 +192,13 @@ class FileManager:
return "" return ""
return os.path.relpath(full_path, start=root_dir) return os.path.relpath(full_path, start=root_dir)
def has_hidden_dir(self, rel_path: str) -> bool:
parts = rel_path.split("/")
for part in parts:
if part and part[0] == '.':
return True
return False
def check_file_exists(self, root: str, filename: str) -> bool: def check_file_exists(self, root: str, filename: str) -> bool:
root_dir = self.file_paths.get(root, "") root_dir = self.file_paths.get(root, "")
file_path = os.path.join(root_dir, filename) file_path = os.path.join(root_dir, filename)
@ -267,7 +274,8 @@ class FileManager:
self.notify_sync_lock.cancel() self.notify_sync_lock.cancel()
self.notify_sync_lock = None self.notify_sync_lock = None
raise raise
await self.notify_sync_lock.wait(30.) if not self.has_hidden_dir(directory):
await self.notify_sync_lock.wait(30.)
self.notify_sync_lock = None self.notify_sync_lock = None
else: else:
try: try:
@ -363,7 +371,9 @@ class FileManager:
self.notify_sync_lock = None self.notify_sync_lock = None
raise self.server.error(str(e)) raise self.server.error(str(e))
self.notify_sync_lock.update_dest(full_dest) self.notify_sync_lock.update_dest(full_dest)
await self.notify_sync_lock.wait(600.) if not self.has_hidden_dir(self.get_relative_path(
dest_root, full_dest)):
await self.notify_sync_lock.wait(600.)
self.notify_sync_lock = None self.notify_sync_lock = None
result['item']['path'] = self.get_relative_path(dest_root, full_dest) result['item']['path'] = self.get_relative_path(dest_root, full_dest)
return result return result
@ -420,7 +430,7 @@ class FileManager:
try: try:
upload_info = self._parse_upload_args(form_args) upload_info = self._parse_upload_args(form_args)
root = upload_info['root'] root = upload_info['root']
if root == "gcodes": if root == "gcodes" and upload_info['ext'] in VALID_GCODE_EXTS:
result = await self._finish_gcode_upload(upload_info) result = await self._finish_gcode_upload(upload_info)
elif root in FULL_ACCESS_ROOTS: elif root in FULL_ACCESS_ROOTS:
result = await self._finish_standard_upload(upload_info) result = await self._finish_standard_upload(upload_info)
@ -472,7 +482,8 @@ class FileManager:
'dest_path': dest_path, 'dest_path': dest_path,
'tmp_file_path': upload_args['tmp_file_path'], 'tmp_file_path': upload_args['tmp_file_path'],
'start_print': start_print, 'start_print': start_print,
'unzip_ufp': unzip_ufp 'unzip_ufp': unzip_ufp,
'ext': f_ext
} }
async def _finish_gcode_upload(self, async def _finish_gcode_upload(self,
@ -507,7 +518,9 @@ class FileManager:
except self.server.error: except self.server.error:
# Attempt to start print failed # Attempt to start print failed
start_print = False start_print = False
await self.notify_sync_lock.wait(300.) rel_dir_path = os.path.dirname(upload_info['filename'])
if not self.has_hidden_dir(rel_dir_path):
await self.notify_sync_lock.wait(300.)
self.notify_sync_lock = None self.notify_sync_lock = None
return { return {
'item': { 'item': {
@ -521,7 +534,12 @@ class FileManager:
async def _finish_standard_upload(self, async def _finish_standard_upload(self,
upload_info: Dict[str, Any] upload_info: Dict[str, Any]
) -> Dict[str, Any]: ) -> Dict[str, Any]:
self.notify_sync_lock = NotifySyncLock(upload_info['dest_path'])
self._process_uploaded_file(upload_info) self._process_uploaded_file(upload_info)
rel_dir_path = os.path.dirname(upload_info['filename'])
if not self.has_hidden_dir(rel_dir_path):
await self.notify_sync_lock.wait(5.)
self.notify_sync_lock = None
return { return {
'item': { 'item': {
'path': upload_info['filename'], 'path': upload_info['filename'],
@ -1211,9 +1229,6 @@ class INotifyHandler:
ext: str = os.path.splitext(evt.name)[-1].lower() ext: str = os.path.splitext(evt.name)[-1].lower()
root = node.get_root() root = node.get_root()
node_path = node.get_path() node_path = node.get_path()
if root == "gcodes" and ext not in VALID_GCODE_EXTS:
# Don't notify files with invalid gcode extensions
return
if evt.mask & iFlags.CREATE: if evt.mask & iFlags.CREATE:
logging.debug(f"Inotify file create: {root}, " logging.debug(f"Inotify file create: {root}, "
f"{node_path}, {evt.name}") f"{node_path}, {evt.name}")