Commit 41b43374 authored by Romain Vimont's avatar Romain Vimont

Fix empty playlists on restore

The PathProbe stores the state (the m_splitPath stack) used by
FsDiscoverer::discover(). It assumes that the discoverer calls
PathProbe::proceedOnDirectory() in a certain order (it updates its
internal state accordingly).

If the "current depth level" or the target path (m_splitPath.top()) is
different from the directory name, the directory is rejected.

For example, here are the successive directories considered to discover
"/home/user/Music/album/track.mp3" from the entryPoint "/home":

    -- depth 0
    m_path:            "/home/user/Music/album/track.mp3"
    m_splitPath:       ["track.mp3", "album", "Music", "user", "home"]
    m_splitPath.top(): "home"
    directory:         "/home"
    directory name:    "home"
    return:            true

    -- depth 1
    m_path:            "/home/user/Music/album/track.mp3"
    m_splitPath:       ["track.mp3", "album", "Music", "user"]
    m_splitPath.top(): "user"
    directory:         "/home/user"
    directory name:    "user"
    return:            true

    -- depth 2
    m_path:            "/home/user/Music/album/track.mp3"
    m_splitPath:       ["track.mp3", "album", "Music"]
    m_splitPath.top(): "Music"
    directory:         "/home/user/Videos"
    directory name:    "Videos"
    return:            false

    -- depth 2
    m_path:            "/home/user/Music/album/track.mp3"
    m_splitPath:       ["track.mp3", "album", "Music"]
    m_splitPath.top(): "Music"
    directory:         "/home/user/Music"
    directory name:    "Music"
    return:            true

    ...

The problem is that it can only work if the first directory (the entry
point) does not contain more than 1 token. For example,

    -- depth 0
    m_path:            "/sdcard/emulated/0/Music/track.mp3"
    m_splitPath:       ["track.mp3", "Music", "0", "emulated", "sdcard"]
    m_splitPath.top(): "sdcard"
    directory:         "/sdcard/emulated/0"
    directory name:    "0"
    return:            false

Since the initial directory is "/sdcard/emulated/0", the directory name
("0") does not match the first token of the target path ("sdcard"): the
internal state of PathProbe is inconsistent with the sequence of calls
it expects from the discoverer.

This commit quick-fixes the problem by handling the entry point
separately to "consume" all the initial path tokens, so that the
internal state of PathProbe is synchronized with the calls it receives
from the discoverer.
parent 78a40ef2
Pipeline #9428 failed with stage
in 43 minutes and 8 seconds
......@@ -42,6 +42,7 @@ PathProbe::PathProbe( std::string path, bool isDirectory,
int64_t parentPlaylistId, int64_t playlistIndex, bool reload )
: m_isDirectory( isDirectory )
, m_isDiscoveryEnded( false )
, m_entryPointHandled( false )
, m_parentFolder( std::move( parentFolder ) )
, m_path( std::move( path ) )
, m_parentPlaylistId( parentPlaylistId )
......@@ -67,8 +68,39 @@ PathProbe::PathProbe( std::string path, bool isDirectory,
m_splitPath.pop();
}
bool PathProbe::proceedOnEntryPoint( const fs::IDirectory& entryPoint )
{
if ( m_splitPath.empty() == true )
return true;
auto directoryPath = utils::file::toLocalPath( entryPoint.mrl() );
#ifndef _WIN32
// In case we are discovering from "/", the root folder isn't part of the
// splitted path stack, which would cause the prober to reject it.
if ( directoryPath == "/" )
return true;
#endif
auto splitDirectoryPath = utils::file::splitPath( directoryPath, true );
while ( !splitDirectoryPath.empty() )
{
if (m_splitPath.top() != splitDirectoryPath.top() )
return false;
m_splitPath.pop();
if ( m_splitPath.empty() )
return true;
splitDirectoryPath.pop();
}
return true;
}
bool PathProbe::proceedOnDirectory( const fs::IDirectory& directory )
{
if ( !m_entryPointHandled )
{
m_entryPointHandled = true;
return proceedOnEntryPoint(directory);
}
if ( m_isDirectory && m_splitPath.empty() == true )
{
auto directoryPath = utils::file::toLocalPath( directory.mrl() );
......
......@@ -87,9 +87,12 @@ public:
}
private:
bool proceedOnEntryPoint( const fs::IDirectory& directory );
bool m_isDirectory;
std::stack<std::string> m_splitPath;
bool m_isDiscoveryEnded;
bool m_entryPointHandled;
std::shared_ptr<Folder> m_parentFolder;
std::string m_path;
int64_t m_parentPlaylistId;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment