thekid/inotify-win

Wrong Result

xpresso opened this issue · 10 comments

inotifywait -e create,delete,modify,move -mrq C:\Test

When moving C:\Test\TestFolder1\testfile.txt to C:\Test\TestFolder2
It results in c:\Test DELETE TestFolder1\testfile.txt which is wrong,
should be

c:\Test MOVED_FROM TestFolder1\testfile.txt
c:\Test MOVED_TO TestFolder2\testfile.txt

Verified.

This is going to be a bit tougher:

For example, when a file is moved from one directory to another, several OnChanged and some OnCreated and OnDeleted events might be raised. Moving a file is a complex operation that consists of multiple simple operations, therefore raising multiple events.

http://msdn.microsoft.com/en-us/library/system.io.filesystemwatcher.aspx

Pull requests welcome 😄 :octocat:

The fact that one event went missing might have been caused by some events being swallowed. Initial tests suggest this have been fixed:

issue-7

The next thing would be to detect that in fact this was the same file and re-work it to MOVED_FROM / MOVED_TO combination; though not sure this would work.

any update ?

Sorry, no. This goes over my C# / Windows programming skills (how can I find out testfile.txt was the same file as something deleted when examining the CREATE event?), which is why I'm open to accept any pull requests.

This might be comparable to moving files across partitions on Unix. Although moving files is an atomic operation there, it only applies to the situtation when files are on the same file system (in other cases, it's a cp followed by an rm). Not sure how the original inotify tool handles this...

Anyways: I'm not sure this is possible due to the nature how moving files works on Windows.

Alright, thanks.

I would suggest comparing the hashed values. (The technique used in web frameworks to invalidate a cached file, if there has been a minor change by altering the filname, wich contains a hash value.)

I think, knowing C#, which I don't, it's pretty straight forward.

Here is the relevenat part copied from stackoverflow:

You could use MD5CryptoServiceProvider, which will work with text based files as well as binary files.

byte[] myFileData = File.ReadAllBytes(myFileName);
byte[] myHash = MD5.Create().ComputeHash(myFileData);

Or... if you work with large files and do not want to load the whole file into memory:

byte[] myFileData;
using (var md5 = MD5.Create())
using (var stream = File.OpenRead(myFileName))
    myFileData = md5.ComputeHash(stream);

You can compare to byte arrays from two files with Enumerable.SequenceEqual:

myHash1.SequenceEqual(myHash2); 

BTW, thanks for the good work! This is very relevant to boot2docker people working with windows and not beeing able to use fswath library: Connect it with rsync and you can use inotify autoreload features in your development cycle.

byte[] myFileData = File.ReadAllBytes(myFileName);

Yes, I'd been thinking about this too. On the downside, this could be quite an issue for a 2 Gigabyte file on a Network drive... but even for smaller checkouts around 10 - 50 Megabytes but say with frequent changes this could be quite a performance hit.

Maybe "fingerprinting" as suggested here, but that would mean keeping all files in memory when starting a watch (because what's the fingerprint of a deleted file? -> it would need to be calculated beforehand).

BTW, thanks for the good work!

You're welcome!

Reading through this blog, I'd say: For the usecase you're thinking about I think keeping the intelligence about replicating the changes in rsync is sufficient (it does this kind of fingerprinting AFAIK), and just using this tool to detect that there have been changes.

I was about to say, the -c command of rsync does checksum, but not by default, as it is slow as you suggested... I'm working on a shellscript to do exactly what you suggest, leaving apart the moving case, as for development in case of reordering the file structure a need restarting the server is not that far fetched.