From ce296e691bac261a26f1ac55211a1a6be899df86 Mon Sep 17 00:00:00 2001 From: Bas Stottelaar Date: Sat, 6 Dec 2014 13:24:57 +0100 Subject: [PATCH] Add advanced option to ignore folder patterns (#2037). Applies to post processing folders and library scan folders. There is no configuration option in the web interface (yet), but one can specify the following in the INI file (make sure Headphones is shut down!). [Advances] ... ignored_folders = *.git, *.btsync ... --- headphones/config.py | 1 + headphones/helpers.py | 38 ++++++++++++++++++++++++++----------- headphones/librarysync.py | 14 +++++++++----- headphones/postprocessor.py | 14 +++++++++++++- 4 files changed, 50 insertions(+), 17 deletions(-) diff --git a/headphones/config.py b/headphones/config.py index 7cae3861..176c49cb 100644 --- a/headphones/config.py +++ b/headphones/config.py @@ -91,6 +91,7 @@ _CONFIG_DEFINITIONS = { 'HTTP_ROOT': (str, 'General', '/'), 'HTTP_USERNAME': (str, 'General', ''), 'IGNORED_WORDS': (str, 'General', ''), + 'IGNORED_FOLDERS': (list, 'Advanced', ''), 'INCLUDE_EXTRAS': (int, 'General', 0), 'INTERFACE': (str, 'General', 'default'), 'JOURNAL_MODE': (str, 'Advanced', 'wal'), diff --git a/headphones/helpers.py b/headphones/helpers.py index bc15b015..57715cf1 100644 --- a/headphones/helpers.py +++ b/headphones/helpers.py @@ -13,17 +13,19 @@ # You should have received a copy of the GNU General Public License # along with Headphones. If not, see . -import os -import re -import time -import shutil -import datetime -import headphones -import unicodedata -import sys +from beets.mediafile import MediaFile, FileTypeError, UnreadableFileError from operator import itemgetter -from beets.mediafile import MediaFile, FileTypeError, UnreadableFileError + +import unicodedata +import headphones +import datetime +import fnmatch +import shutil +import time +import sys +import re +import os # Modified from https://github.com/Verrus/beets-plugin-featInTitle RE_FEATURING = re.compile(r"[fF]t\.|[fF]eaturing|[fF]eat\.|\b[wW]ith\b|&|vs\.") @@ -330,6 +332,20 @@ def expand_subfolders(f): return media_folders +def path_match_patterns(path, patterns): + """ + Check if a path matches one or more patterns. The whole path will be + matched be matched against the patterns. + """ + + for pattern in patterns: + if fnmatch.fnmatch(path, pattern): + return True + + # No match + return False + + def extract_data(s): s = s.replace('_', ' ') @@ -474,8 +490,8 @@ def get_downloaded_track_list(albumpath): def preserve_torrent_direcory(albumpath): """ - Copy torrent directory to headphones-modified to keep files for seeding. - """ + Copy torrent directory to headphones-modified to keep files for seeding. + """ from headphones import logger new_folder = os.path.join(albumpath, 'headphones-modified'.encode(headphones.SYS_ENCODING, 'replace')) logger.info("Copying files to 'headphones-modified' subfolder to preserve downloaded files for seeding") diff --git a/headphones/librarysync.py b/headphones/librarysync.py index 3644dbc5..a05d1938 100644 --- a/headphones/librarysync.py +++ b/headphones/librarysync.py @@ -79,12 +79,16 @@ def libraryScan(dir=None, append=False, ArtistID=None, ArtistName=None, cron=Fal latest_subdirectory = [] for r, d, f in helpers.walk_directory(dir): - # Need to abuse slicing to get a copy of the list, doing it directly - # will skip the element after a deleted one using a list comprehension - # will not work correctly for nested subdirectories (os.walk keeps its - # original list) + # Scan for ignored folders. A copy of the list is taken because the + # original list is modified and list comprehensions don't work because + # of logging. + patterns = headphones.CONFIG.IGNORED_FOLDERS + for directory in d[:]: - if directory.startswith("."): + full_path = os.path.join(r, directory) + + if helpers.path_match_patterns(full_path, patterns): + logger.debug("Folder ignored by pattern: %s", full_path) d.remove(directory) for files in f: diff --git a/headphones/postprocessor.py b/headphones/postprocessor.py index 238703da..5359ffd3 100755 --- a/headphones/postprocessor.py +++ b/headphones/postprocessor.py @@ -1078,10 +1078,22 @@ def forcePostProcess(dir=None, expand_subfolders=True, album_dir=None): else: folders.append(path_to_folder) + # Scan for ignored folders. A copy of the list is taken because the original + # list is modified and list comprehensions don't work because of logging. + patterns = headphones.CONFIG.IGNORED_FOLDERS + ignored = 0 + + for folder in folders[:]: + if helpers.path_match_patterns(folder, patterns): + logger.debug("Folder ignored by pattern: %s", folder) + folders.remove(folder) + ignored += 1 + # Log number of folders if folders: - logger.info('Found %i folders to process.', len(folders)) logger.debug('Expanded post processing folders: %s', folders) + logger.info('Found %d folders to process (%d ignored).', + len(folders), ignored) else: logger.info('Found no folders to process. Aborting.') return