diff --git a/NEWS b/NEWS index 8d45ce5b7..7700571c3 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,6 @@ ver 0.22.2 (not yet released) +* database + - simple: purge virtual directories for unavailable plugins on update ver 0.22.1 (2020/10/17) * decoder diff --git a/src/db/meson.build b/src/db/meson.build index 2a0c8a5bd..69bf50cd6 100644 --- a/src/db/meson.build +++ b/src/db/meson.build @@ -31,6 +31,7 @@ db_glue_sources = [ 'update/Remove.cxx', 'update/ExcludeList.cxx', 'update/VirtualDirectory.cxx', + 'update/SpecialDirectory.cxx', 'DatabaseGlue.cxx', 'Configured.cxx', 'DatabaseSong.cxx', diff --git a/src/db/plugins/simple/Directory.hxx b/src/db/plugins/simple/Directory.hxx index 7062e609c..ea14420d0 100644 --- a/src/db/plugins/simple/Directory.hxx +++ b/src/db/plugins/simple/Directory.hxx @@ -132,6 +132,13 @@ public: return mounted_database != nullptr; } + /** + * Checks whether this is a "special" directory + * (e.g. #DEVICE_PLAYLIST) and whether the underlying plugin + * is available. + */ + bool IsPluginAvailable() const noexcept; + /** * Remove this #Directory object from its parent and free it. This * must not be called with the root Directory. diff --git a/src/db/update/SpecialDirectory.cxx b/src/db/update/SpecialDirectory.cxx new file mode 100644 index 000000000..49c025d18 --- /dev/null +++ b/src/db/update/SpecialDirectory.cxx @@ -0,0 +1,74 @@ +/* + * Copyright 2003-2020 The Music Player Daemon Project + * http://www.musicpd.org + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "db/plugins/simple/Directory.hxx" +#include "archive/ArchiveList.hxx" +#include "decoder/DecoderList.hxx" +#include "playlist/PlaylistRegistry.hxx" +#include "fs/Traits.hxx" + +gcc_pure +static bool +HaveArchivePluginForFilename(const char *filename) noexcept +{ +#ifdef ENABLE_ARCHIVE + const char *suffix = PathTraitsUTF8::GetFilenameSuffix(filename); + return suffix != nullptr && + archive_plugin_from_suffix(suffix) != nullptr; +#else + (void)filename; + return false; +#endif +} + +gcc_pure +static bool +HaveContainerPluginForFilename(const char *filename) noexcept +{ + const char *suffix = PathTraitsUTF8::GetFilenameSuffix(filename); + return suffix != nullptr && + // TODO: check if this plugin really supports containers + decoder_plugins_supports_suffix(suffix); +} + +gcc_pure +static bool +HavePlaylistPluginForFilename(const char *filename) noexcept +{ + const char *suffix = PathTraitsUTF8::GetFilenameSuffix(filename); + return suffix != nullptr && playlist_suffix_supported(suffix); +} + +bool +Directory::IsPluginAvailable() const noexcept +{ + switch (device) { + case DEVICE_INARCHIVE: + return HaveArchivePluginForFilename(GetName()); + + case DEVICE_CONTAINER: + return HaveContainerPluginForFilename(GetName()); + + case DEVICE_PLAYLIST: + return HavePlaylistPluginForFilename(GetName()); + + default: + return true; + } +} diff --git a/src/db/update/Walk.cxx b/src/db/update/Walk.cxx index 87304df62..6ac12776e 100644 --- a/src/db/update/Walk.cxx +++ b/src/db/update/Walk.cxx @@ -93,7 +93,11 @@ inline void UpdateWalk::PurgeDeletedFromDirectory(Directory &directory) noexcept { directory.ForEachChildSafe([&](Directory &child){ - if (child.IsMount() || DirectoryExists(storage, child)) + if (child.IsMount()) + return; + + if (DirectoryExists(storage, child) && + child.IsPluginAvailable()) return; editor.LockDeleteDirectory(&child);