Code Monkey home page Code Monkey logo

fswatch's Introduction

FSWatch

CI Dub version Dub downloads

A cross platform library simplifying watching for file changes using a non-blocking interface using the Win32 API, inotify or std.file.dirEntries as fallback.

Comparison between implementations

Platform Watching Directory Watching File
Windows ReadDirectoryChangesW (very fast, accurate) polling using std.file.timeLastModified and std.file.exists (fast, not accurate for quick write)
Linux inotify (very fast, accurate) inotify (very fast, accurate)
Other polling using std.file.dirEntries (slow, not accurate) polling using std.file.timeLastModified and std.file.exists (fast, not accurate for quick write)

To force usage of the std.file polling implementation you can just add version = FSWForcePoll;

Don't do this unless you have a specific reason as you will lose speed and accuracy!

Example

void main()
{
	// Initializes a FileWatch instance to watch on `project1/` (first argument) recursively (second argument)
	auto watcher = FileWatch("project1/", true);
	while (true)
	{
		// This will fetch all queued events or an empty array if there are none
		foreach (event; watcher.getEvents())
		{
			// paths are relative to the watched directory in most cases
			if (event.path == "dub.json" || event.path == "dub.sdl")
			{
				if (event.type == FileChangeEventType.create)
				{
					// dub.json or dub.sdl got created
				}
				else if (event.type == FileChangeEventType.modify)
				{
					// dub.json or dub.sdl got modified
				}
				else if (event.type == FileChangeEventType.remove)
				{
					// dub.json or dub.sdl got deleted
				}
			}
			if (event.type == FileChangeEventType.rename)
			{
				// The file `event.path` has been removed to `event.newPath`
			}
			else if (event.type == FileChangeEventType.createSelf)
			{
				// the folder we are watching has been created
			}
			else if (event.type == FileChangeEventType.removeSelf)
			{
				// the folder we are watching has been deleted or renamed
			}
		}
		// ...
		myapp.handleInput();
		myapp.update();
		myapp.draw();
	}
}

fswatch's People

Contributors

aravindavk avatar dkorpel avatar freeslave avatar lempiji avatar mrcsnm avatar webfreak001 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

fswatch's Issues

Multiple dynamic watchers

Is it possible to create multiple watchers and store them in an array and then loop that array in a while loop to watch for events?

I can't seem to get that working and I suspect it doesn't work, because FileWatch is a struct?

Perhaps if FileWatch was a class it would work?

Basically what I'm doing now is this: (Minimal example)

I create an array like:

FileWatch[] watchers;

Then I load the watchers from a config file with the paths:

foreach (path; paths)
{
    watchers ~= FileWatch(path, true);
}

And then I do this:

while (true)
{
    foreach (watcher; watchers)
     {
        foreach (event; watcher.getEvents())
        {
            // It never gets anything here ...
        }
    }
}

Maybe I'm using it wrong?

Also I'm on Windows. Could it be a Windows issue?

Does not work on Debian 12 x64 Linux without FSWForcePoll

    "dependencies": {
        "fswatch": "~>0.6.1"
    "versions": []
dmd --version
DMD64 D Compiler v2.105.3
Copyright (C) 1999-2023 by The D Language Foundation, All Rights Reserved written by Walter Bright
uname -a
Linux i7 6.1.0-13-amd64 #1 SMP PREEMPT_DYNAMIC Debian 6.1.55-1 (2023-09-29) x86_64 GNU/Linux

sample code:

void watcher() {
    auto src = FileWatch("src/", true);
    auto views = FileWatch("views/", true);
    auto dub = FileWatch("dub.json", true);
    while (true) {
        Thread.sleep(1111.msecs);
        foreach (e; src.getEvents)
            writeln(e.path, '\t', e.type);
        foreach (e; views.getEvents)
            writeln(e.path, '\t', e.type);
        foreach (e; dub.getEvents)
            writeln(e.path, '\t', e.type);
    }
}

void main(string[] args) {
    writeln(args);
    // autorestart
    spawn(&watcher);

Moving file to and from observable directory leads to errors

  1. Create directory, watch it with my example.
  2. Create file in this directory, move it to upper directory. No events reported.
  3. Move this file again to observable directory, library will throw
core.exception.AssertError@source/fswatch.d(306): Cookies don't match

Tested on Debian 8.

Directory watching on Windows doesn't work

Code like this:

watcher = FileWatch("C:/test/", true); while (1) { foreach (event; watcher.getEvents()) { writeln(event.path); } }

when ran and creating/deleting/modifying files in C:\test\ directory, no paths get written to stdout

Checking a file or directory

How to check if event.path is a file or a directory in an event? isDir and isFile don't work with it.

In my application, I want to check if a file in a directory has changed, but at the same time I get a notification that its directory has changed. I need to get just for the file.

Double update messages

I tried out watching a folder named "test" in Windows 10:

import core.thread: Thread, msecs;
import std.stdio;
import fswatch;

void main(string[] args) {
	FileWatch watcher = FileWatch("test", true);
	while(true) {
		writeln(watcher.getEvents());
		Thread.sleep(500.msecs);
	}
}

I noticed that I receive more messages than needed:

// Saving a file in notepad
[]
[FileChangeEvent(modify, "file.txt", "")]
[]
[FileChangeEvent(modify, "file.txt", "")]
[]
[]
// Saving a new file in notepad
[]
[FileChangeEvent(create, "newfile.txt", "")]
[]
[FileChangeEvent(remove, "newfile.txt", ""), FileChangeEvent(create, "newfile.txt", ""), FileChangeEvent(modify, "newfile.txt", ""), FileChangeEvent(modify, "newfile.txt", "")]
[]
// Creating a file using std.file.write
[]
[FileChangeEvent(create, "hey.txt", "")]
[]
[FileChangeEvent(modify, "hey.txt", "")]
[]

Even if I change the sleep time, it's always first an empty event array and then an array with redundant messages. I don't know if this is just how the Windows API works or if some extra modifications are being done under the hood, but it's weird how they show up only after calling getEvents() twice more.

Is getEvents() a blocking read?

If it is then doesn't there need to be a version with a timeout?

If I have a thread running a watcher and getEvents() blocks, then it is not possible to terminate the thread and so terminate the application.

DInotify added the read(Duration) function to deal with this.

Windows file name with invalid characters

Had to replace:
string fileName = (cast(wchar[])(cast(ubyte*) info.FileName)[0 .. info.FileNameLength]).toUTF8.idup;
with:
wstring wfileName = info.FileName[0 .. info.FileNameLength].idup; string fileName = wfileName.toUTF8.idup;
(BTW Formatting got broken on paste).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.