db/simple: prune CUE entries from database for non-existent songs
Closes https://github.com/MusicPlayerDaemon/MPD/issues/1019
This commit is contained in:
parent
8e0d39ae94
commit
1985786ed2
1
NEWS
1
NEWS
|
@ -4,6 +4,7 @@ ver 0.22.10 (not yet released)
|
||||||
* database
|
* database
|
||||||
- simple: fix crash bug
|
- simple: fix crash bug
|
||||||
- simple: fix absolute paths in CUE "as_directory" entries
|
- simple: fix absolute paths in CUE "as_directory" entries
|
||||||
|
- simple: prune CUE entries from database for non-existent songs
|
||||||
* input
|
* input
|
||||||
- curl: fix crash bug after stream with Icy metadata was closed by peer
|
- curl: fix crash bug after stream with Icy metadata was closed by peer
|
||||||
- tidal: remove defunct unmaintained plugin
|
- tidal: remove defunct unmaintained plugin
|
||||||
|
|
|
@ -109,6 +109,23 @@ Directory::FindChild(std::string_view name) const noexcept
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Directory::TargetExists(std::string_view _target) const noexcept
|
||||||
|
{
|
||||||
|
StringView target{_target};
|
||||||
|
|
||||||
|
if (target.SkipPrefix("../")) {
|
||||||
|
if (parent == nullptr)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return parent->TargetExists(target);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sorry for the const_cast ... */
|
||||||
|
const auto lr = const_cast<Directory *>(this)->LookupDirectory(target);
|
||||||
|
return lr.directory->FindSong(lr.rest) != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
Directory::PruneEmpty() noexcept
|
Directory::PruneEmpty() noexcept
|
||||||
{
|
{
|
||||||
|
|
|
@ -118,13 +118,17 @@ public:
|
||||||
return new Directory(std::string(), nullptr);
|
return new Directory(std::string(), nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsPlaylist() const noexcept {
|
||||||
|
return device == DEVICE_PLAYLIST;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is this really a regular file which is being treated like a
|
* Is this really a regular file which is being treated like a
|
||||||
* directory?
|
* directory?
|
||||||
*/
|
*/
|
||||||
bool IsReallyAFile() const noexcept {
|
bool IsReallyAFile() const noexcept {
|
||||||
return device == DEVICE_INARCHIVE ||
|
return device == DEVICE_INARCHIVE ||
|
||||||
device == DEVICE_PLAYLIST ||
|
IsPlaylist() ||
|
||||||
device == DEVICE_CONTAINER;
|
device == DEVICE_CONTAINER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,6 +214,9 @@ public:
|
||||||
gcc_pure
|
gcc_pure
|
||||||
LookupResult LookupDirectory(std::string_view uri) noexcept;
|
LookupResult LookupDirectory(std::string_view uri) noexcept;
|
||||||
|
|
||||||
|
[[gnu::pure]]
|
||||||
|
bool TargetExists(std::string_view target) const noexcept;
|
||||||
|
|
||||||
gcc_pure
|
gcc_pure
|
||||||
bool IsEmpty() const noexcept {
|
bool IsEmpty() const noexcept {
|
||||||
return children.empty() &&
|
return children.empty() &&
|
||||||
|
|
|
@ -133,6 +133,28 @@ UpdateWalk::PurgeDeletedFromDirectory(Directory &directory) noexcept
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
UpdateWalk::PurgeDanglingFromPlaylists(Directory &directory) noexcept
|
||||||
|
{
|
||||||
|
/* recurse */
|
||||||
|
for (Directory &child : directory.children)
|
||||||
|
PurgeDanglingFromPlaylists(child);
|
||||||
|
|
||||||
|
if (!directory.IsPlaylist())
|
||||||
|
/* this check is only for virtual directories
|
||||||
|
representing a playlist file */
|
||||||
|
return;
|
||||||
|
|
||||||
|
directory.ForEachSongSafe([&](Song &song){
|
||||||
|
if (!song.target.empty() &&
|
||||||
|
!PathTraitsUTF8::IsAbsoluteOrHasScheme(song.target.c_str()) &&
|
||||||
|
!directory.TargetExists(song.target)) {
|
||||||
|
editor.DeleteSong(directory, &song);
|
||||||
|
modified = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
static bool
|
static bool
|
||||||
update_directory_stat(Storage &storage, Directory &directory) noexcept
|
update_directory_stat(Storage &storage, Directory &directory) noexcept
|
||||||
|
@ -530,5 +552,10 @@ UpdateWalk::Walk(Directory &root, const char *path, bool discard) noexcept
|
||||||
UpdateDirectory(root, exclude_list, info);
|
UpdateDirectory(root, exclude_list, info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
const ScopeDatabaseLock protect;
|
||||||
|
PurgeDanglingFromPlaylists(root);
|
||||||
|
}
|
||||||
|
|
||||||
return modified;
|
return modified;
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,6 +85,12 @@ private:
|
||||||
|
|
||||||
void PurgeDeletedFromDirectory(Directory &directory) noexcept;
|
void PurgeDeletedFromDirectory(Directory &directory) noexcept;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove all virtual songs inside playlists whose "target"
|
||||||
|
* field points to a non-existing song file.
|
||||||
|
*/
|
||||||
|
void PurgeDanglingFromPlaylists(Directory &directory) noexcept;
|
||||||
|
|
||||||
void UpdateSongFile2(Directory &directory,
|
void UpdateSongFile2(Directory &directory,
|
||||||
const char *name, const char *suffix,
|
const char *name, const char *suffix,
|
||||||
const StorageFileInfo &info) noexcept;
|
const StorageFileInfo &info) noexcept;
|
||||||
|
|
Loading…
Reference in New Issue