watchly 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/README.md +57 -0
- data/lib/watchly/changeset.rb +24 -0
- data/lib/watchly/snapshot.rb +47 -0
- data/lib/watchly/version.rb +3 -0
- data/lib/watchly/watcher.rb +33 -0
- data/lib/watchly.rb +3 -0
- metadata +50 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: f99ea235b8e5f9266131b1e25353c54c6a5c725cb9fca3c2ec7a503ae84bd73b
|
|
4
|
+
data.tar.gz: 170a74f2b7e9642f57d19a141b65b3ab50d20199de44c9f48f0d5a16692732c5
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 61e82c4f0f9077a6af68fe057ece3bffacd1030eaeab69f77b6476b71f2dfa172d0f3f934552a45b9e6cd2d1d898f35e896dd5bf1d8dca59d53e16b2dca47a1c
|
|
7
|
+
data.tar.gz: 30bcceb7691daab5d6def2ff15a5284ebcb89c2a492c83020713a8bea3db9ec470ed732dccc197e65f8f507e1e6a882a1e7ec884635a1286a2d797dac4c4d6f1
|
data/README.md
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Watchly
|
|
2
|
+
|
|
3
|
+
Watchly is a lightweight, dependency-free, polling-based file watcher for Ruby.
|
|
4
|
+
It watches one or more glob patterns and reports changes.
|
|
5
|
+
|
|
6
|
+
## Installation
|
|
7
|
+
|
|
8
|
+
```bash
|
|
9
|
+
gem install watchly
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Or in your Gemfile:
|
|
13
|
+
|
|
14
|
+
```ruby
|
|
15
|
+
gem 'watchly'
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Usage
|
|
19
|
+
|
|
20
|
+
**Initialize a watcher:**
|
|
21
|
+
|
|
22
|
+
```ruby
|
|
23
|
+
require 'watchly'
|
|
24
|
+
|
|
25
|
+
# with the default interval (1 second)
|
|
26
|
+
watcher = Watchly::Watcher.new '**/*'
|
|
27
|
+
|
|
28
|
+
# with a different interval
|
|
29
|
+
watcher = Watchly::Watcher.new '**/*', interval: 2.0
|
|
30
|
+
|
|
31
|
+
# with multiple glob patterns
|
|
32
|
+
watcher = Watchly::Watcher.new 'spec/**/*.rb', 'lib/*.*'
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**Watch for changes:**
|
|
36
|
+
|
|
37
|
+
```ruby
|
|
38
|
+
watcher.on_change do |changes|
|
|
39
|
+
puts "Added: #{changes.added.join(', ')}" if changes.added.any?
|
|
40
|
+
puts "Removed: #{changes.removed.join(', ')}" if changes.removed.any?
|
|
41
|
+
puts "Modified: #{changes.modified.join(', ')}" if changes.modified.any?
|
|
42
|
+
end
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
**Stop the watcher:**
|
|
46
|
+
|
|
47
|
+
```ruby
|
|
48
|
+
# Mainly for tests, but can be called from another thread
|
|
49
|
+
watcher.stop
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Contributing / Support
|
|
53
|
+
|
|
54
|
+
If you experience any issue, have a question, or if you wish
|
|
55
|
+
to contribute, feel free to [open an issue][issues].
|
|
56
|
+
|
|
57
|
+
[issues]: https://github.com/dannyben/watchly/issues
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module Watchly
|
|
2
|
+
class Changeset
|
|
3
|
+
attr_reader :added, :removed, :modified
|
|
4
|
+
|
|
5
|
+
def initialize(added:, removed:, modified:)
|
|
6
|
+
@added = added.freeze
|
|
7
|
+
@removed = removed.freeze
|
|
8
|
+
@modified = modified.freeze
|
|
9
|
+
freeze
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def empty? = added.empty? && removed.empty? && modified.empty?
|
|
13
|
+
def any? = !empty?
|
|
14
|
+
def to_h = { added: added, removed: removed, modified: modified }
|
|
15
|
+
|
|
16
|
+
def each
|
|
17
|
+
return enum_for(:each) unless block_given?
|
|
18
|
+
|
|
19
|
+
added.each { |path| yield :added, path }
|
|
20
|
+
removed.each { |path| yield :removed, path }
|
|
21
|
+
modified.each { |path| yield :modified, path }
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module Watchly
|
|
2
|
+
class Snapshot
|
|
3
|
+
attr_reader :globs, :files
|
|
4
|
+
|
|
5
|
+
def initialize(globs)
|
|
6
|
+
@globs = globs
|
|
7
|
+
@files = capture(globs)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def diff(other)
|
|
11
|
+
Changeset.new(
|
|
12
|
+
added: added_files(other),
|
|
13
|
+
removed: removed_files(other),
|
|
14
|
+
modified: modified_files(other)
|
|
15
|
+
)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def ==(other)
|
|
19
|
+
return false unless other.is_a? self.class
|
|
20
|
+
|
|
21
|
+
files == other.files
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
private
|
|
25
|
+
|
|
26
|
+
def added_files(other) = other.files.keys - files.keys
|
|
27
|
+
def removed_files(other) = files.keys - other.files.keys
|
|
28
|
+
|
|
29
|
+
def modified_files(other)
|
|
30
|
+
(files.keys & other.files.keys).reject do |path|
|
|
31
|
+
files[path] == other.files[path]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def capture(globs)
|
|
36
|
+
Array(globs)
|
|
37
|
+
.flat_map { |glob| Dir.glob glob }
|
|
38
|
+
.uniq
|
|
39
|
+
.each_with_object({}) do |path, acc|
|
|
40
|
+
next unless File.file? path
|
|
41
|
+
|
|
42
|
+
stat = File.stat path
|
|
43
|
+
acc[path] = [stat.mtime.to_i, stat.size]
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
module Watchly
|
|
2
|
+
class Watcher
|
|
3
|
+
DEFAULT_INTERVAL = 1.0
|
|
4
|
+
|
|
5
|
+
attr_reader :globs, :interval, :stopped
|
|
6
|
+
|
|
7
|
+
def initialize(*globs, interval: nil)
|
|
8
|
+
@globs = globs
|
|
9
|
+
@interval = interval || DEFAULT_INTERVAL
|
|
10
|
+
@stopped = false
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def stop = @stopped = true
|
|
14
|
+
|
|
15
|
+
def on_change
|
|
16
|
+
raise ArgumentError, 'Block required' unless block_given?
|
|
17
|
+
|
|
18
|
+
previous = Snapshot.new globs
|
|
19
|
+
|
|
20
|
+
until stopped
|
|
21
|
+
sleep interval
|
|
22
|
+
|
|
23
|
+
current = Snapshot.new globs
|
|
24
|
+
next if previous == current
|
|
25
|
+
|
|
26
|
+
changes = previous.diff current
|
|
27
|
+
yield changes
|
|
28
|
+
|
|
29
|
+
previous = current
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
data/lib/watchly.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: watchly
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Danny Ben Shitrit
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies: []
|
|
12
|
+
description: A small, dependency-free, polling-based library that watches one or more
|
|
13
|
+
glob patterns and reports on change
|
|
14
|
+
email: db@dannyben.com
|
|
15
|
+
executables: []
|
|
16
|
+
extensions: []
|
|
17
|
+
extra_rdoc_files: []
|
|
18
|
+
files:
|
|
19
|
+
- README.md
|
|
20
|
+
- lib/watchly.rb
|
|
21
|
+
- lib/watchly/changeset.rb
|
|
22
|
+
- lib/watchly/snapshot.rb
|
|
23
|
+
- lib/watchly/version.rb
|
|
24
|
+
- lib/watchly/watcher.rb
|
|
25
|
+
homepage: https://github.com/dannyben/watchly
|
|
26
|
+
licenses:
|
|
27
|
+
- MIT
|
|
28
|
+
metadata:
|
|
29
|
+
bug_tracker_uri: https://github.com/dannyben/watchly/issues
|
|
30
|
+
changelog_uri: https://github.com/dannyben/watchly/blob/master/CHANGELOG.md
|
|
31
|
+
source_code_uri: https://github.com/dannyben/watchly
|
|
32
|
+
rubygems_mfa_required: 'true'
|
|
33
|
+
rdoc_options: []
|
|
34
|
+
require_paths:
|
|
35
|
+
- lib
|
|
36
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '3.2'
|
|
41
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
42
|
+
requirements:
|
|
43
|
+
- - ">="
|
|
44
|
+
- !ruby/object:Gem::Version
|
|
45
|
+
version: '0'
|
|
46
|
+
requirements: []
|
|
47
|
+
rubygems_version: 4.0.3
|
|
48
|
+
specification_version: 4
|
|
49
|
+
summary: Lightweight, polling-based file system watcher
|
|
50
|
+
test_files: []
|