jmhodges/justrun

Don't terminate process if file contents did not change

Opened this issue · 6 comments

If I open a file and save it without making any modifications, it would be neat if justrun did not terminate the process. This would help prevent against unnecessary server reloads, also because I compulsively hit :w when I am working with a file in vim.

The implementation might be a little tricky. On Macs, here are the events that get generated when I save a file in TextEdit:

2018/01/05 17:09:13 unignored file change: "/Users/kevin/src/github.com/kevinburke/portfolio/static/dashboard.js": REMOVE
2018/01/05 17:09:13 unignored file change: "/Users/kevin/src/github.com/kevinburke/portfolio/static/dashboard.js": CREATE
2018/01/05 17:09:13 unignored file change: "/Users/kevin/src/github.com/kevinburke/portfolio/static/dashboard.js": CHMOD
2018/01/05 17:09:13 unignored file change: "/Users/kevin/src/github.com/kevinburke/portfolio/static/dashboard.js": CHMOD

So it wouldn't be enough to e.g. check only for single events, since you'd have to wait for the second or third event to determine "the file is still there and didn't change". You could check right after you get the tick.C event if you have the delay turned on.

It would also be slow if a file was particularly large, though you could decide to bail on the "is this actually the same file" strategy after like 4MB or whatever.

See also fsnotify/fsnotify#232, but I'm not sure that's the right place for it.

Well, with that optimization, we'd have bugs where for large files that were appended to not triggering new builds.

Do you know of another watcher system that does this? I've not been able to find one.

I don't think so... maybe the Bazel one, but I haven't tested it. https://github.com/bazelbuild/bazel-watcher

we'd have bugs where for large files that were appended to not triggering new builds.

Ah, I was imagining the optimization would be "don't trigger new build if the source exactly matches" but if a file is large enough that it can't be checksummed efficiently, you just trigger the build every time / don't apply the optimization.

Well, it's got the backing of all of bazel, but yeah, that's definitely better.

I'd be willing to look at a patch for this, but don't have time to implement.

Here's a rough patch, which I believe behaves the way I expect. kevinburke@639e375

It's pretty slow though, I watch maybe 50 files on a Mac (Go files, CSS, JS, templates) and getting the digest for all of them takes 20ms. We could potentially parallelize it but that would add more complexity.

If you're actually interested in this after looking at what's involved I could clean it up and try to work on the performance.

I'd be up for it but yeah that's way too slow.

A friend of mine got nerd-sniped and started poking at doing a concurrent version, but you'll likely have to carry it across the way. Here's a gist of that work https://gist.github.com/blinsay/41a1a775f83d9ed2b6ed241dcaf6b21e

Thanks for the gist! It might take me a while to update the patch but this is something I am still definitely interested in