Closed megumumpkin closed 2 years ago
Already set the option for both followSymlinks and allowOutOfScopeLinks to true.
Folders too
Hi! What file system are you using? Is it a network file system (NFS, SMB)?
I use ext4 on Linux.
I think I'll need a minimum example to be able to reproduce it. I'm on the same setup and works just fine with the efsw test using followSymlinks and allowOutOfScopeLinks enabled and adding a symlink to a folder out of scope. If possible try to provide an example that creates that symlink and writes a file to the symlinked folder. Thanks.
So first, this is the code I'm writing for checking file changes:
struct FSEvent{
enum TYPE{
ADD,
MODIFY,
DELETE
};
TYPE type;
std::string filetype;
std::string filepath;
};
wi::unordered_map<std::string, FSEvent> fsevents;
std::mutex event_sync;
class FSUpdateListener : public efsw::FileWatchListener
{
void handleFileAction(efsw::WatchID watchid, const std::string& dir, const std::string& filename, efsw::Action action, std::string oldFilename) override
{
bool store = false;
FSEvent::TYPE action_type;
switch(action){
case efsw::Actions::Add:
{
store = true;
action_type = FSEvent::ADD;
break;
}
case efsw::Actions::Modified:
{
store = true;
action_type = FSEvent::MODIFY;
break;
}
case efsw::Actions::Delete:
{
store = true;
action_type = FSEvent::DELETE;
break;
}
default:
break;
}
std::scoped_lock lock (event_sync);
fsevents[filename] = {
action_type,
wi::helper::toUpper(wi::helper::GetExtensionFromFileName(filename)),
dir+filename,
};
}
};
std::shared_ptr<efsw::FileWatcher> filewatcher;
std::shared_ptr<FSUpdateListener> fwlistener;
efsw::WatchID watch_all;
void Game::LiveUpdate::Init()
{
filewatcher = std::make_shared<efsw::FileWatcher>();
fwlistener = std::make_shared<FSUpdateListener>();
watch_all = filewatcher->addWatch(wi::helper::GetCurrentPath(), fwlistener.get(), true);
filewatcher->watch();
}
void Game::LiveUpdate::Update(float dt)
{
std::scoped_lock lock (event_sync);
for(auto& pair_event : fsevents){
wi::backlog::post("wiix");
auto& event = pair_event.second;
if(event.filetype == "LUA"){
Game::ScriptBindings::LiveUpdate::PushEvent({
(event.type == FSEvent::DELETE) ? Game::ScriptBindings::LiveUpdate::ScriptReloadEvent::UNLOAD : Game::ScriptBindings::LiveUpdate::ScriptReloadEvent::RELOAD,
Game::ScriptBindings::LiveUpdate::ScriptReloadEvent::LUA,
event.filepath
});
}
}
fsevents.clear();
Resources::LiveUpdate::Update(dt);
ScriptBindings::LiveUpdate::Update(dt);
}
Second, this is the file structure:
Program
script.lua <-- symlink to a file out of scope
Expected behavior: Program detects changes to the symlink file after the file is updated (saved over) from a text editor. What happened instead: Program does not detect file changes at all.
If i have a folder that is symlinked like this:
Program
FolderX <-- symlink to a folder out of scope
|-- script.lua
symlink is using ln -s script.lua
The result is the same, it won't react to the change at all.
Does efsw needs some specific file/folder flags for symlinked ones to work? Atleast for non symlink with those two structures above is working for me.
For the full repo i have it in here: https://github.com/megumumpkin/WickedEngine-Demo/ The code mentioned above is from LiveUpdate.cpp from Sources/ folder Program ran from build/ folder (exists after bulding)
Oh.
The first example shouldn't return any event, since the file descriptor of the symlink isn't modified, what's being modified is the file that it's being linked to. In that case, you will need to manually detect symlink files and add the folder that contains the real file. This is not a limitation of the library but how the file system works.
The second example I'm not sure if I understand you, but, if the only symlink is the folder FolderX
and script.lua
is an actual file, it should work, but if script.lua
is also a symlink, the same issue should happen.
So I set up the liveupdate tracking like this:
void Game::LiveUpdate::Init()
{
filewatcher = std::make_shared<efsw::FileWatcher>();
fwlistener = std::make_shared<FSUpdateListener>();
watch_all = filewatcher->addWatch(wi::helper::GetCurrentPath(), fwlistener.get(), true);
filewatcher->followSymlinks(true);
filewatcher->allowOutOfScopeLinks(true);
filewatcher->watch();
}
Trying out the 2nd case, and it does not detect too.
For file links it needs to be hardlink and not symlink, and has to edit the hardlinked one, not the source it seems.
The function call order is wrong. The configuration should be done before adding the watch (when the flags are used).
void Game::LiveUpdate::Init()
{
filewatcher = std::make_shared<efsw::FileWatcher>();
fwlistener = std::make_shared<FSUpdateListener>();
filewatcher->followSymlinks(true);
filewatcher->allowOutOfScopeLinks(true);
watch_all = filewatcher->addWatch(wi::helper::GetCurrentPath(), fwlistener.get(), true);
filewatcher->watch();
}
Yeah, it works now, thanks :+1:
The file exists on the same folder as the program, as I did update the script file it won't detect the changes