Merge tag 'v0.22.10'
release v0.22.10
This commit is contained in:
@@ -109,6 +109,23 @@ Directory::FindChild(std::string_view name) const noexcept
|
||||
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
|
||||
Directory::PruneEmpty() noexcept
|
||||
{
|
||||
|
||||
@@ -118,13 +118,17 @@ public:
|
||||
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
|
||||
* directory?
|
||||
*/
|
||||
bool IsReallyAFile() const noexcept {
|
||||
return device == DEVICE_INARCHIVE ||
|
||||
device == DEVICE_PLAYLIST ||
|
||||
IsPlaylist() ||
|
||||
device == DEVICE_CONTAINER;
|
||||
}
|
||||
|
||||
@@ -206,11 +210,13 @@ public:
|
||||
* Looks up a directory by its relative URI.
|
||||
*
|
||||
* @param uri the relative URI
|
||||
* @return the Directory, or nullptr if none was found
|
||||
*/
|
||||
gcc_pure
|
||||
LookupResult LookupDirectory(std::string_view uri) noexcept;
|
||||
|
||||
[[gnu::pure]]
|
||||
bool TargetExists(std::string_view target) const noexcept;
|
||||
|
||||
gcc_pure
|
||||
bool IsEmpty() const noexcept {
|
||||
return children.empty() &&
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
#include "playlist/SongEnumerator.hxx"
|
||||
#include "storage/FileInfo.hxx"
|
||||
#include "storage/StorageInterface.hxx"
|
||||
#include "fs/Traits.hxx"
|
||||
#include "util/StringFormat.hxx"
|
||||
#include "Log.hxx"
|
||||
|
||||
@@ -71,7 +72,14 @@ UpdateWalk::UpdatePlaylistFile(Directory &parent, std::string_view name,
|
||||
|
||||
auto db_song = std::make_unique<Song>(std::move(*song),
|
||||
*directory);
|
||||
db_song->target = "../" + db_song->filename;
|
||||
db_song->target =
|
||||
PathTraitsUTF8::IsAbsoluteOrHasScheme(db_song->filename.c_str())
|
||||
? db_song->filename
|
||||
/* prepend "../" to relative paths to
|
||||
go from the virtual directory
|
||||
(DEVICE_PLAYLIST) to the containing
|
||||
directory */
|
||||
: "../" + db_song->filename;
|
||||
db_song->filename = StringFormat<64>("track%04u",
|
||||
++track);
|
||||
|
||||
|
||||
@@ -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
|
||||
static bool
|
||||
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);
|
||||
}
|
||||
|
||||
{
|
||||
const ScopeDatabaseLock protect;
|
||||
PurgeDanglingFromPlaylists(root);
|
||||
}
|
||||
|
||||
return modified;
|
||||
}
|
||||
|
||||
@@ -85,6 +85,12 @@ private:
|
||||
|
||||
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,
|
||||
const char *name, std::string_view suffix,
|
||||
const StorageFileInfo &info) noexcept;
|
||||
|
||||
Reference in New Issue
Block a user