Beispiel #1
0
bool
wxFileSystemWatcherBase::AddAny(const wxFileName& path,
                                int events,
                                wxFSWPathType type,
                                const wxString& filespec)
{
    wxString canonical = GetCanonicalPath(path);
    if (canonical.IsEmpty())
        return false;

    // adding a path in a platform specific way
    wxFSWatchInfo watch(canonical, events, type, filespec);
    if ( !m_service->Add(watch) )
        return false;

    // on success, either add path to our 'watch-list'
    // or, if already watched, inc the refcount. This may happen if
    // a dir is Add()ed, then later AddTree() is called on a parent dir
    wxFSWatchInfoMap::iterator it = m_watches.find(canonical);
    if ( it == m_watches.end() )
    {
        wxFSWatchInfoMap::value_type val(canonical, watch);
        m_watches.insert(val);
    }
    else
    {
        wxFSWatchInfo& watch = it->second;
        int count = watch.IncRef();
        wxLogTrace(wxTRACE_FSWATCHER,
                   "'%s' is now watched %d times", canonical, count);
    }
    return true;
}
bool wxFsEventsFileSystemWatcher::RemoveTree(const wxFileName& path)
{
    wxString canonical = GetCanonicalPath(path);
    if ( canonical.empty() )
    {
        return false;
    }

    // Remove any kqueue watches created with Add()
    // RemoveTree() should remove all watches no matter
    // if they are tree watches or single directory watches.
    wxArrayString dirsWatched;
    wxKqueueFileSystemWatcher::GetWatchedPaths(&dirsWatched);
    for ( size_t i = 0; i < dirsWatched.size(); i++ )
    {
        if (dirsWatched[i].Find(canonical) == 0)
        {
            wxKqueueFileSystemWatcher::Remove(dirsWatched[i]);
        }
    }

    FSEventStreamRefMap::iterator it = m_streams.find(canonical);
    bool removed = false;
    if ( it != m_streams.end() )
    {
        FSEventStreamStop(it->second);
        FSEventStreamInvalidate(it->second);
        FSEventStreamRelease(it->second);
        m_streams.erase(it);
        removed = true;
    }
    return removed;
}
bool wxFileSystemWatcherBase::Remove(const wxFileName& path)
{
    // args validation & consistency checks
    wxString canonical = GetCanonicalPath(path);
    if (canonical.IsEmpty())
        return false;

    wxFSWatchInfoMap::iterator it = m_watches.find(canonical);
    wxCHECK_MSG(it != m_watches.end(), false,
                wxString::Format("Path '%s' is not watched", canonical));

    // remove from watch-list
    wxFSWatchInfo watch = it->second;
    m_watches.erase(it);

    // remove in a platform specific way
    return m_service->Remove(watch);
}
bool wxFileSystemWatcherBase::Add(const wxFileName& path, int events)
{
    // args validation & consistency checks
    if (!path.FileExists() && !path.DirExists())
        return false;

    wxString canonical = GetCanonicalPath(path);
    if (canonical.IsEmpty())
        return false;

    wxCHECK_MSG(m_watches.find(canonical) == m_watches.end(), false,
                wxString::Format("Path '%s' is already watched", canonical));

    // adding a path in a platform specific way
    wxFSWatchInfo watch(canonical, events);
    if ( !m_service->Add(watch) )
        return false;

    // on success, add path to our 'watch-list'
    wxFSWatchInfoMap::value_type val(canonical, watch);
    return m_watches.insert(val).second;
}
Beispiel #5
0
///////////////////////////////
// NodeJs-Directory
TNodeJsFPath::TNodeJsFPath(const TStr& FPath): CanonicalFPath(GetCanonicalPath(FPath)) { }
Beispiel #6
0
bool wxFileSystemWatcherBase::RemoveTree(const wxFileName& path)
{
    if (!path.DirExists())
        return false;

    // OPT could be optimised if we stored information about relationships
    // between paths
    class RemoveTraverser : public wxDirTraverser
    {
    public:
        RemoveTraverser(wxFileSystemWatcherBase* watcher,
                        const wxString& filespec) :
            m_watcher(watcher), m_filespec(filespec)
        {
        }

        virtual wxDirTraverseResult OnFile(const wxString& WXUNUSED(filename))
        {
            // We never watch the individual files when watching the tree, so
            // nothing to do here.
            return wxDIR_CONTINUE;
        }

        virtual wxDirTraverseResult OnDir(const wxString& dirname)
        {
            m_watcher->Remove(wxFileName::DirName(dirname));
            return wxDIR_CONTINUE;
        }

    private:
        wxFileSystemWatcherBase* m_watcher;
        wxString m_filespec;
    };

    // If AddTree() used a filespec, we must use the same one
    wxString canonical = GetCanonicalPath(path);
    wxFSWatchInfoMap::iterator it = m_watches.find(canonical);
    wxCHECK_MSG( it != m_watches.end(), false,
                 wxString::Format("Path '%s' is not watched", canonical) );
    wxFSWatchInfo watch = it->second;
    const wxString filespec = watch.GetFilespec();

#if defined(__WINDOWS__)
    // When there's no filespec, the wxMSW AddTree() would have set a watch
    // on only the passed 'path'. We must therefore remove only this
    if (filespec.empty())
    {
        return Remove(path);
    }
    // Otherwise fall through to the generic implementation
#endif // __WINDOWS__

    wxDir dir(path.GetFullPath());
    // AddTree() might have used the wxDIR_NO_FOLLOW to prevent asserts or
    // infinite loops in trees containing symlinks. We need to do the same
    // or we'll try to remove unwatched items. Let's hope the caller used
    // the same ShouldFollowLink() setting as in AddTree()...
    int flags = wxDIR_DIRS;
    if ( !path.ShouldFollowLink() )
    {
        flags |= wxDIR_NO_FOLLOW;
    }
    RemoveTraverser traverser(this, filespec);
    dir.Traverse(traverser, filespec, flags);

    // As in AddTree() above, handle the path itself explicitly.
    Remove(path);

    return true;
}
bool wxFsEventsFileSystemWatcher::AddTree(const wxFileName& path, int events,
    const wxString& filespec)
{
    if (!path.DirExists())
    {
        return false;
    }
    wxString canonical = GetCanonicalPath(path);
    if ( canonical.empty() )
    {
        return false;
    }
    CFRunLoopRef cfLoop = CFRunLoopGetCurrent();
    wxASSERT_MSG(
        cfLoop,
        "there must be a current event loop; this file watcher needs it."
    );
    if ( ! cfLoop )
    {
        return false;
    }

    if ( m_streams.find(canonical) != m_streams.end() )
    {
        // How to take into account filespec
        // if client adds a watch for /home/*.cpp
        // and then on another call wants to add a
        // call to /home/*.h
        // Ideally we should not create another watch
        // however we would need to keep both filespecs
        // around, which we don't do now.
        return false;
    }

    // Will need to pass the desired event flags
    // and filespec to our callback via the context
    // we make sure to give the context a cleanup
    // callback.
    FSEventStreamContext ctx;
    wxFSEventWatcherContext* watcherContext = new wxFSEventWatcherContext(
        this, events, filespec.Clone()
    );
    ctx.version = 0;
    ctx.info = watcherContext;
    ctx.retain = NULL;
    ctx.release = &wxDeleteContext;
    ctx.copyDescription = NULL;
    CFTimeInterval latency = 0.2;

    wxMacUniCharBuffer pathChars(path.GetPath());
    CFStringRef pathRef = CFStringCreateWithCharacters(
        kCFAllocatorDefault,
        pathChars.GetBuffer(),
        pathChars.GetChars()
    );
    CFArrayRef pathRefs = CFArrayCreate(
        kCFAllocatorDefault, (const void**)&pathRef, 1, NULL
    );
    FSEventStreamCreateFlags flags = kFSEventStreamCreateFlagWatchRoot
        | kFSEventStreamCreateFlagFileEvents;

    FSEventStreamRef stream = FSEventStreamCreate(
        kCFAllocatorDefault,
        &wxFSEventCallback,
        &ctx,
        pathRefs, kFSEventStreamEventIdSinceNow,
        latency, flags);
    bool started = false;
    if ( stream )
    {
        FSEventStreamScheduleWithRunLoop(stream, cfLoop, kCFRunLoopDefaultMode);
        started = FSEventStreamStart(stream);
        if ( started )
        {
            m_streams[canonical] = stream;
        }
    }

    // cleanup the paths, as we own the pointers
    CFRelease(pathRef);
    CFRelease(pathRefs);

    wxASSERT_MSG(stream, "could not create FS stream");
    return started;
}