unused.py 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. """
  2. This component will look for files to be removed. There are some assumptions:
  3. * Only files in $TMPDIR are removed. Please remember that larigira has its
  4. own specific TMPDIR
  5. * MPD URIs are parsed, and only file:/// is supported
  6. """
  7. import os
  8. from os.path import normpath
  9. import logging
  10. import mpd
  11. def old_commonpath(directories):
  12. if any(p for p in directories if p.startswith("/")) and any(
  13. p for p in directories if not p.startswith("/")
  14. ):
  15. raise ValueError("Can't mix absolute and relative paths")
  16. norm_paths = [normpath(p) + os.path.sep for p in directories]
  17. ret = os.path.dirname(os.path.commonprefix(norm_paths))
  18. if len(ret) > 0 and ret == "/" * len(ret):
  19. return "/"
  20. return ret
  21. try:
  22. from os.path import commonpath
  23. except ImportError:
  24. commonpath = old_commonpath
  25. class UnusedCleaner:
  26. def __init__(self, conf):
  27. self.conf = conf
  28. self.waiting_removal_files = set()
  29. self.log = logging.getLogger(self.__class__.__name__)
  30. def _get_mpd(self):
  31. mpd_client = mpd.MPDClient(use_unicode=True)
  32. mpd_client.connect(self.conf["MPD_HOST"], self.conf["MPD_PORT"])
  33. return mpd_client
  34. def watch(self, uri):
  35. """
  36. adds fpath to the list of "watched" file
  37. as soon as it leaves the mpc playlist, it is removed
  38. """
  39. if not uri.startswith("file:///"):
  40. return # not a file URI
  41. fpath = uri[len("file://") :]
  42. if (
  43. "TMPDIR" in self.conf
  44. and self.conf["TMPDIR"]
  45. and commonpath([self.conf["TMPDIR"], fpath])
  46. != normpath(self.conf["TMPDIR"])
  47. ):
  48. self.log.info("Not watching file %s: not in TMPDIR", fpath)
  49. return
  50. if not os.path.exists(fpath):
  51. self.log.warning("a path that does not exist is being monitored")
  52. self.waiting_removal_files.add(fpath)
  53. def check_playlist(self):
  54. """check playlist + internal watchlist to see what can be removed"""
  55. mpdc = self._get_mpd()
  56. files_in_playlist = {
  57. song["file"] for song in mpdc.playlistid() if song["file"].startswith("/")
  58. }
  59. for fpath in self.waiting_removal_files - files_in_playlist:
  60. # we can remove it!
  61. self.log.debug("removing unused: %s", fpath)
  62. self.waiting_removal_files.remove(fpath)
  63. if os.path.exists(fpath):
  64. os.unlink(fpath)