diff --git a/beetsplug/permissions.py b/beetsplug/permissions.py index 256f09e52..7039f491a 100644 --- a/beetsplug/permissions.py +++ b/beetsplug/permissions.py @@ -6,10 +6,12 @@ like the following in your config.yaml to configure: permissions: file: 644 + dir: 755 """ import os from beets import config, util from beets.plugins import BeetsPlugin +from beets.util import ancestry def convert_perm(perm): @@ -28,13 +30,22 @@ def check_permissions(path, permission): return oct(os.stat(path).st_mode & 0o777) == oct(permission) +def dirs_in_library(library, item): + """Creates a list of ancestor directories in the beets library path. + """ + return [ancestor + for ancestor in ancestry(item) + if ancestor.startswith(library)][1:] + + class Permissions(BeetsPlugin): def __init__(self): super(Permissions, self).__init__() # Adding defaults. self.config.add({ - u'file': 644 + u'file': 644, + u'dir': 755 }) @@ -45,21 +56,25 @@ def permissions(lib, item=None, album=None): """ # Getting the config. file_perm = config['permissions']['file'].get() + dir_perm = config['permissions']['dir'].get() - # Converts file permissions to oct. + # Converts permissions to oct. file_perm = convert_perm(file_perm) + dir_perm = convert_perm(dir_perm) # Create chmod_queue. - chmod_queue = [] + file_chmod_queue = [] if item: - chmod_queue.append(item.path) + file_chmod_queue.append(item.path) elif album: for album_item in album.items(): - chmod_queue.append(album_item.path) + file_chmod_queue.append(album_item.path) - # Setting permissions for every path in the queue. - for path in chmod_queue: - # Changing permissions on the destination path. + # A set of directories to change permissions for. + dir_chmod_queue = set() + + for path in file_chmod_queue: + # Changing permissions on the destination file. os.chmod(util.bytestring_path(path), file_perm) # Checks if the destination path has the permissions configured. @@ -67,3 +82,19 @@ def permissions(lib, item=None, album=None): message = 'There was a problem setting permission on {}'.format( path) print(message) + + # Adding directories to the directory chmod queue. + dir_chmod_queue.update( + dirs_in_library(config['directory'].get(), + path)) + + # Change permissions for the directories. + for path in dir_chmod_queue: + # Chaning permissions on the destination directory. + os.chmod(util.bytestring_path(path), dir_perm) + + # Checks if the destination path has the permissions configured. + if not check_permissions(util.bytestring_path(path), dir_perm): + message = 'There was a problem setting permission on {}'.format( + path) + print(message) diff --git a/docs/changelog.rst b/docs/changelog.rst index 329770102..ca96f1d3f 100644 --- a/docs/changelog.rst +++ b/docs/changelog.rst @@ -44,6 +44,8 @@ Features: * The number of missing/unmatched tracks is shown during import. :bug:`1088` * The data source used during import (e.g., MusicBrainz) is now saved as a flexible attribute `data_source` of an Item/Album. :bug:`1311` +* :doc:`/plugins/permissions`: Now handles also the permissions of the + directories. :bug:`1308` bug:`1324` Core changes: diff --git a/docs/plugins/permissions.rst b/docs/plugins/permissions.rst index 06b034b51..9c4cdc0aa 100644 --- a/docs/plugins/permissions.rst +++ b/docs/plugins/permissions.rst @@ -2,7 +2,7 @@ Permissions Plugin ================== The ``permissions`` plugin allows you to set file permissions for imported -music files. +music files and its directories. To use the ``permissions`` plugin, enable it in your configuration (see :ref:`using-plugins`). Permissions will be adjusted automatically on import. @@ -12,9 +12,10 @@ Configuration To configure the plugin, make an ``permissions:`` section in your configuration file. The ``file`` config value therein uses **octal modes** to specify the -desired permissions. The default flags are octal 644. +desired permissions. The default flags for files are octal 644 and 755 for directories. Here's an example:: permissions: file: 644 + dir: 755 diff --git a/test/test_permissions.py b/test/test_permissions.py index 1e16a1c34..20e33b7d2 100644 --- a/test/test_permissions.py +++ b/test/test_permissions.py @@ -5,7 +5,9 @@ from __future__ import (division, absolute_import, print_function, from test._common import unittest from test.helper import TestHelper -from beetsplug.permissions import check_permissions, convert_perm +from beetsplug.permissions import (check_permissions, + convert_perm, + dirs_in_library) class PermissionsPluginTest(unittest.TestCase, TestHelper): @@ -14,7 +16,8 @@ class PermissionsPluginTest(unittest.TestCase, TestHelper): self.load_plugins('permissions') self.config['permissions'] = { - 'file': 777} + 'file': 777, + 'dir': 777} def tearDown(self): self.teardown_beets() @@ -24,23 +27,45 @@ class PermissionsPluginTest(unittest.TestCase, TestHelper): self.importer = self.create_importer() self.importer.run() item = self.lib.items().get() - config_perm = self.config['permissions']['file'].get() - config_perm = convert_perm(config_perm) - self.assertTrue(check_permissions(item.path, config_perm)) + file_perm = self.config['permissions']['file'].get() + file_perm = convert_perm(file_perm) + + dir_perm = self.config['permissions']['dir'].get() + dir_perm = convert_perm(dir_perm) + + music_dirs = dirs_in_library(self.config['directory'].get(), + item.path) + + self.assertTrue(check_permissions(item.path, file_perm)) self.assertFalse(check_permissions(item.path, convert_perm(644))) + for path in music_dirs: + self.assertTrue(check_permissions(path, dir_perm)) + self.assertFalse(check_permissions(path, convert_perm(644))) + def test_permissions_on_item_imported(self): self.config['import']['singletons'] = True self.importer = self.create_importer() self.importer.run() item = self.lib.items().get() - config_perm = self.config['permissions']['file'].get() - config_perm = convert_perm(config_perm) - self.assertTrue(check_permissions(item.path, config_perm)) + file_perm = self.config['permissions']['file'].get() + file_perm = convert_perm(file_perm) + + dir_perm = self.config['permissions']['dir'].get() + dir_perm = convert_perm(dir_perm) + + music_dirs = dirs_in_library(self.config['directory'].get(), + item.path) + + self.assertTrue(check_permissions(item.path, file_perm)) self.assertFalse(check_permissions(item.path, convert_perm(644))) + for path in music_dirs: + self.assertTrue(check_permissions(path, dir_perm)) + self.assertFalse(check_permissions(path, convert_perm(644))) + def suite(): return unittest.TestLoader().loadTestsFromName(__name__)