beets/beetsplug/permissions.py

128 lines
4.1 KiB
Python

from __future__ import (division, absolute_import, print_function,
unicode_literals)
"""Fixes file permissions after the file gets written on import. Put something
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 displayable_path
def convert_perm(perm):
"""If the perm is a int it will first convert it to a string and back
to an oct int. Else it just converts it to oct.
"""
if isinstance(perm, int):
return int(bytes(perm), 8)
else:
return int(perm, 8)
def check_permissions(path, permission):
"""Checks the permissions of a path.
"""
return oct(os.stat(path).st_mode & 0o777) == oct(permission)
def get_music_directories(music_directory, imported_item):
"""Creates a list of directories the imported item is in.
"""
# Checks for the directory in config and if it has a tilde in it.
# If its that way it will be expanded to the full path.
if '~' in music_directory:
music_directory = os.path.expanduser(music_directory)
# Getting the absolute path of the directory.
music_directory = os.path.abspath(music_directory)
# Creates a differential path list of the directory config path and
# the path of the imported item.
differential_path_list = os.path.split(
displayable_path(imported_item).split(
music_directory)[1])[0].split('/')[1:]
# Creating a list with full paths of all directories in the music library
# we need to look at for chaning permissions.
directory_list = []
for path in differential_path_list:
if len(directory_list) > 0:
directory_list.append(os.path.join(directory_list[-1], path))
else:
directory_list.append(os.path.join(music_directory, path))
return directory_list
class Permissions(BeetsPlugin):
def __init__(self):
super(Permissions, self).__init__()
# Adding defaults.
self.config.add({
u'file': 644,
u'dir': 755
})
@Permissions.listen('item_imported')
@Permissions.listen('album_imported')
def permissions(lib, item=None, album=None):
"""Running the permission fixer.
"""
# Getting the config.
file_perm = config['permissions']['file'].get()
dir_perm = config['permissions']['dir'].get()
# Converts permissions to oct.
file_perm = convert_perm(file_perm)
dir_perm = convert_perm(dir_perm)
# Create chmod_queue.
file_chmod_queue = []
if item:
file_chmod_queue.append(item.path)
elif album:
for album_item in album.items():
file_chmod_queue.append(album_item.path)
# A list of directories to set permissions for.
dir_chmod_queue = []
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.
if not check_permissions(util.bytestring_path(path), file_perm):
message = 'There was a problem setting permission on {}'.format(
path)
print(message)
# Adding directories to the chmod queue.
dir_chmod_queue.append(
get_music_directories(config['directory'].get(), path))
# Unpack sublists.
dir_chmod_queue = [directory
for dir_list in dir_chmod_queue
for directory in dir_list]
# Get rid of duplicates.
dir_chmod_queue = list(set(dir_chmod_queue))
# 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)