filewatcher 1.1.1 → 2.0.0.beta5
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 +5 -5
- data/lib/filewatcher.rb +46 -60
- data/lib/filewatcher/cycles.rb +21 -12
- data/lib/filewatcher/snapshot.rb +64 -0
- data/lib/filewatcher/snapshots.rb +47 -0
- data/lib/filewatcher/spec_helper.rb +89 -0
- data/lib/filewatcher/spec_helper/watch_run.rb +72 -0
- data/lib/filewatcher/version.rb +1 -3
- data/spec/filewatcher/snapshot_spec.rb +68 -0
- data/spec/filewatcher/version_spec.rb +9 -0
- data/spec/filewatcher_spec.rb +302 -0
- data/spec/spec_helper.rb +22 -0
- data/spec/spec_helper/ruby_watch_run.rb +82 -0
- metadata +110 -46
- data/bin/banner.txt +0 -17
- data/bin/filewatcher +0 -106
- data/lib/filewatcher/env.rb +0 -33
- data/lib/filewatcher/runner.rb +0 -33
- data/test/dumpers/env_dumper.rb +0 -10
- data/test/dumpers/watched_dumper.rb +0 -5
- data/test/filewatcher/test_env.rb +0 -70
- data/test/filewatcher/test_runner.rb +0 -75
- data/test/filewatcher/test_version.rb +0 -13
- data/test/helper.rb +0 -238
- data/test/test_filewatcher.rb +0 -354
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'simplecov'
|
4
|
+
SimpleCov.start
|
5
|
+
|
6
|
+
if ENV['CODECOV_TOKEN']
|
7
|
+
require 'codecov'
|
8
|
+
SimpleCov.formatter = SimpleCov::Formatter::Codecov
|
9
|
+
end
|
10
|
+
|
11
|
+
require_relative '../lib/filewatcher/spec_helper'
|
12
|
+
|
13
|
+
require_relative 'spec_helper/ruby_watch_run'
|
14
|
+
|
15
|
+
## For case when required from dumpers
|
16
|
+
if Object.const_defined?(:RSpec)
|
17
|
+
RSpec::Matchers.define :include_all_files do |expected|
|
18
|
+
match do |actual|
|
19
|
+
expected.all? { |file| actual.include? File.expand_path(file) }
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class Filewatcher
|
4
|
+
module SpecHelper
|
5
|
+
class RubyWatchRun < WatchRun
|
6
|
+
attr_reader :filewatcher, :thread, :watched, :processed
|
7
|
+
|
8
|
+
def initialize(filewatcher:, **args)
|
9
|
+
super(**args)
|
10
|
+
@filewatcher = filewatcher
|
11
|
+
|
12
|
+
@mutex = Mutex.new
|
13
|
+
end
|
14
|
+
|
15
|
+
def start
|
16
|
+
super
|
17
|
+
@thread = thread_initialize
|
18
|
+
# thread needs a chance to start
|
19
|
+
wait seconds: 1
|
20
|
+
wait do
|
21
|
+
keep_watching = filewatcher.keep_watching
|
22
|
+
debug "keep_watching = #{keep_watching}"
|
23
|
+
keep_watching
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def stop
|
28
|
+
thread.exit
|
29
|
+
|
30
|
+
wait do
|
31
|
+
thread.stop?
|
32
|
+
end
|
33
|
+
|
34
|
+
super
|
35
|
+
end
|
36
|
+
|
37
|
+
def wait(seconds: 1)
|
38
|
+
super seconds: seconds, interval: filewatcher.interval
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
|
43
|
+
def make_changes
|
44
|
+
super
|
45
|
+
|
46
|
+
# Some OS, file systems and Ruby interpretators
|
47
|
+
# doesn't catch milliseconds of `File.mtime`
|
48
|
+
wait do
|
49
|
+
@mutex.synchronize do
|
50
|
+
debug "processed = #{processed}"
|
51
|
+
debug "processed.any? = #{processed.any?}"
|
52
|
+
processed.any?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def thread_initialize
|
58
|
+
@watched ||= 0
|
59
|
+
@processed = []
|
60
|
+
Thread.new { setup_filewatcher }
|
61
|
+
end
|
62
|
+
|
63
|
+
def setup_filewatcher
|
64
|
+
debug 'setup_filewatcher'
|
65
|
+
debug filewatcher.inspect
|
66
|
+
filewatcher.watch do |changes|
|
67
|
+
debug filewatcher.inspect
|
68
|
+
@mutex.synchronize do
|
69
|
+
debug "watch callback: changes = #{changes.inspect}"
|
70
|
+
increment_watched
|
71
|
+
@processed.push(changes)
|
72
|
+
# debug 'pushed to processed'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def increment_watched
|
78
|
+
@watched += 1
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
metadata
CHANGED
@@ -1,98 +1,167 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: filewatcher
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.beta5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Thomas Flemming
|
8
|
-
|
8
|
+
- Alexander Popov
|
9
|
+
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
|
-
date:
|
12
|
+
date: 2021-04-29 00:00:00.000000000 Z
|
12
13
|
dependencies:
|
13
14
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
15
|
+
name: bundler
|
15
16
|
requirement: !ruby/object:Gem::Requirement
|
16
17
|
requirements:
|
17
18
|
- - "~>"
|
18
19
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
20
|
+
version: '2.0'
|
20
21
|
type: :development
|
21
22
|
prerelease: false
|
22
23
|
version_requirements: !ruby/object:Gem::Requirement
|
23
24
|
requirements:
|
24
25
|
- - "~>"
|
25
26
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
27
|
+
version: '2.0'
|
27
28
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
29
|
+
name: bundler-audit
|
29
30
|
requirement: !ruby/object:Gem::Requirement
|
30
31
|
requirements:
|
31
32
|
- - "~>"
|
32
33
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
34
|
-
type: :
|
34
|
+
version: 0.8.0
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - "~>"
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 0.8.0
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: gem_toys
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - "~>"
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 0.8.0
|
49
|
+
type: :development
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - "~>"
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 0.8.0
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: toys
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - "~>"
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.11.4
|
63
|
+
type: :development
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - "~>"
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.11.4
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: codecov
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - "~>"
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.5.1
|
77
|
+
type: :development
|
35
78
|
prerelease: false
|
36
79
|
version_requirements: !ruby/object:Gem::Requirement
|
37
80
|
requirements:
|
38
81
|
- - "~>"
|
39
82
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
83
|
+
version: 0.5.1
|
41
84
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
85
|
+
name: rspec
|
43
86
|
requirement: !ruby/object:Gem::Requirement
|
44
87
|
requirements:
|
45
88
|
- - "~>"
|
46
89
|
- !ruby/object:Gem::Version
|
47
|
-
version: '
|
90
|
+
version: '3.8'
|
48
91
|
type: :development
|
49
92
|
prerelease: false
|
50
93
|
version_requirements: !ruby/object:Gem::Requirement
|
51
94
|
requirements:
|
52
95
|
- - "~>"
|
53
96
|
- !ruby/object:Gem::Version
|
54
|
-
version: '
|
97
|
+
version: '3.8'
|
55
98
|
- !ruby/object:Gem::Dependency
|
56
99
|
name: rubocop
|
57
100
|
requirement: !ruby/object:Gem::Requirement
|
58
101
|
requirements:
|
59
102
|
- - "~>"
|
60
103
|
- !ruby/object:Gem::Version
|
61
|
-
version: '
|
104
|
+
version: '1.3'
|
62
105
|
type: :development
|
63
106
|
prerelease: false
|
64
107
|
version_requirements: !ruby/object:Gem::Requirement
|
65
108
|
requirements:
|
66
109
|
- - "~>"
|
67
110
|
- !ruby/object:Gem::Version
|
68
|
-
version: '
|
69
|
-
|
111
|
+
version: '1.3'
|
112
|
+
- !ruby/object:Gem::Dependency
|
113
|
+
name: rubocop-performance
|
114
|
+
requirement: !ruby/object:Gem::Requirement
|
115
|
+
requirements:
|
116
|
+
- - "~>"
|
117
|
+
- !ruby/object:Gem::Version
|
118
|
+
version: '1.5'
|
119
|
+
type: :development
|
120
|
+
prerelease: false
|
121
|
+
version_requirements: !ruby/object:Gem::Requirement
|
122
|
+
requirements:
|
123
|
+
- - "~>"
|
124
|
+
- !ruby/object:Gem::Version
|
125
|
+
version: '1.5'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: rubocop-rspec
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - "~>"
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '2.0'
|
133
|
+
type: :development
|
134
|
+
prerelease: false
|
135
|
+
version_requirements: !ruby/object:Gem::Requirement
|
136
|
+
requirements:
|
137
|
+
- - "~>"
|
138
|
+
- !ruby/object:Gem::Version
|
139
|
+
version: '2.0'
|
140
|
+
description: Detect changes in file system. Works anywhere.
|
70
141
|
email:
|
71
142
|
- thomas.flemming@gmail.com
|
72
|
-
|
73
|
-
|
143
|
+
- alex.wayfer@gmail.com
|
144
|
+
executables: []
|
74
145
|
extensions: []
|
75
146
|
extra_rdoc_files: []
|
76
147
|
files:
|
77
|
-
- bin/banner.txt
|
78
|
-
- bin/filewatcher
|
79
148
|
- lib/filewatcher.rb
|
80
149
|
- lib/filewatcher/cycles.rb
|
81
|
-
- lib/filewatcher/
|
82
|
-
- lib/filewatcher/
|
150
|
+
- lib/filewatcher/snapshot.rb
|
151
|
+
- lib/filewatcher/snapshots.rb
|
152
|
+
- lib/filewatcher/spec_helper.rb
|
153
|
+
- lib/filewatcher/spec_helper/watch_run.rb
|
83
154
|
- lib/filewatcher/version.rb
|
84
|
-
-
|
85
|
-
-
|
86
|
-
-
|
87
|
-
-
|
88
|
-
-
|
89
|
-
|
90
|
-
- test/test_filewatcher.rb
|
91
|
-
homepage: http://github.com/thomasfl/filewatcher
|
155
|
+
- spec/filewatcher/snapshot_spec.rb
|
156
|
+
- spec/filewatcher/version_spec.rb
|
157
|
+
- spec/filewatcher_spec.rb
|
158
|
+
- spec/spec_helper.rb
|
159
|
+
- spec/spec_helper/ruby_watch_run.rb
|
160
|
+
homepage: http://github.com/filewatcher/filewatcher
|
92
161
|
licenses:
|
93
162
|
- MIT
|
94
163
|
metadata: {}
|
95
|
-
post_install_message:
|
164
|
+
post_install_message:
|
96
165
|
rdoc_options: []
|
97
166
|
require_paths:
|
98
167
|
- lib
|
@@ -100,23 +169,18 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
100
169
|
requirements:
|
101
170
|
- - ">="
|
102
171
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
172
|
+
version: '2.5'
|
173
|
+
- - "<"
|
174
|
+
- !ruby/object:Gem::Version
|
175
|
+
version: '4'
|
104
176
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
105
177
|
requirements:
|
106
|
-
- - "
|
178
|
+
- - ">"
|
107
179
|
- !ruby/object:Gem::Version
|
108
|
-
version:
|
180
|
+
version: 1.3.1
|
109
181
|
requirements: []
|
110
|
-
|
111
|
-
|
112
|
-
signing_key:
|
182
|
+
rubygems_version: 3.2.15
|
183
|
+
signing_key:
|
113
184
|
specification_version: 4
|
114
|
-
summary:
|
115
|
-
test_files:
|
116
|
-
- test/dumpers/env_dumper.rb
|
117
|
-
- test/dumpers/watched_dumper.rb
|
118
|
-
- test/filewatcher/test_env.rb
|
119
|
-
- test/filewatcher/test_runner.rb
|
120
|
-
- test/filewatcher/test_version.rb
|
121
|
-
- test/helper.rb
|
122
|
-
- test/test_filewatcher.rb
|
185
|
+
summary: Lightweight filewatcher.
|
186
|
+
test_files: []
|
data/bin/banner.txt
DELETED
@@ -1,17 +0,0 @@
|
|
1
|
-
Filewatcher scans the filesystem and executes shell commands when files changes.
|
2
|
-
|
3
|
-
Usage:
|
4
|
-
filewatcher [--restart] '<filenames or patterns>' '<shell command>'
|
5
|
-
Where
|
6
|
-
filename: filename(s) to scan.
|
7
|
-
shell command: shell command to execute when file changes on disk.
|
8
|
-
|
9
|
-
Examples:
|
10
|
-
filewatcher "myfile" "echo 'myfile has changed'"
|
11
|
-
filewatcher '*.rb' 'ruby $FILENAME'
|
12
|
-
filewatcher '**/*.rb' 'ruby $FILENAME' # Watch subdirectories
|
13
|
-
|
14
|
-
Other available environment variables are BASENAME, ABSOLUTE_FILENAME,
|
15
|
-
RELATIVE_FILENAME, EVENT and DIRNAME.
|
16
|
-
|
17
|
-
Options:
|
data/bin/filewatcher
DELETED
@@ -1,106 +0,0 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
2
|
-
# frozen_string_literal: true
|
3
|
-
|
4
|
-
require_relative '../lib/filewatcher'
|
5
|
-
require_relative '../lib/filewatcher/env'
|
6
|
-
require_relative '../lib/filewatcher/runner'
|
7
|
-
require_relative '../lib/filewatcher/version'
|
8
|
-
|
9
|
-
require 'optimist'
|
10
|
-
|
11
|
-
options = Optimist.options do
|
12
|
-
version "filewatcher, version #{Filewatcher::VERSION} by Thomas Flemming 2016"
|
13
|
-
banner File.read File.join(__dir__, 'banner.txt')
|
14
|
-
|
15
|
-
opt :immediate, 'Immediately execute a command',
|
16
|
-
short: 'I', type: :boolean, default: false
|
17
|
-
opt :every, 'Run command for every updated file in one filesystem check',
|
18
|
-
short: 'E', type: :boolean, default: false
|
19
|
-
opt :daemon, 'Run in the background as system daemon',
|
20
|
-
short: 'D', type: :boolean, default: false
|
21
|
-
opt :restart, 'Restart process when filesystem is updated',
|
22
|
-
short: 'r', type: :boolean, default: false
|
23
|
-
opt :list, 'Print name of files being watched'
|
24
|
-
opt :exec, 'Execute file as a script when file is updated',
|
25
|
-
short: 'e', type: :boolean, default: false
|
26
|
-
opt :include, 'Include files',
|
27
|
-
type: :string, default: File.join('**', '*')
|
28
|
-
opt :exclude, 'Exclude file(s) matching',
|
29
|
-
type: :string, default: nil
|
30
|
-
opt :interval, 'Interval to scan filesystem',
|
31
|
-
short: 'i', type: :float, default: 0.5
|
32
|
-
opt :spinner, 'Show an ascii spinner',
|
33
|
-
short: 's', type: :boolean, default: false
|
34
|
-
end
|
35
|
-
|
36
|
-
Optimist.die Optimist.educate if ARGV.empty?
|
37
|
-
|
38
|
-
files = ARGV[0..-2]
|
39
|
-
|
40
|
-
files << ARGV.first if files.empty?
|
41
|
-
|
42
|
-
def split_files_void_escaped_whitespace(files)
|
43
|
-
files
|
44
|
-
.map { |name| name.gsub(/\\\s/, '_ESCAPED_WHITESPACE_').split(/\s/) }
|
45
|
-
.flatten
|
46
|
-
.uniq
|
47
|
-
.map { |name| name.gsub('_ESCAPED_WHITESPACE_', '\ ') }
|
48
|
-
end
|
49
|
-
|
50
|
-
files = split_files_void_escaped_whitespace(files)
|
51
|
-
child_pid = nil
|
52
|
-
|
53
|
-
def restart(pid, env, cmd)
|
54
|
-
begin
|
55
|
-
raise Errno::ESRCH unless pid
|
56
|
-
Process.kill(9, pid)
|
57
|
-
Process.wait(pid)
|
58
|
-
rescue Errno::ESRCH
|
59
|
-
nil # already killed
|
60
|
-
end
|
61
|
-
Process.spawn(env, cmd)
|
62
|
-
end
|
63
|
-
|
64
|
-
if options[:exclude].to_s != ''
|
65
|
-
options[:exclude] = split_files_void_escaped_whitespace(
|
66
|
-
options[:exclude].split(' ')
|
67
|
-
)
|
68
|
-
end
|
69
|
-
|
70
|
-
begin
|
71
|
-
fw = Filewatcher.new(files, options)
|
72
|
-
|
73
|
-
if options[:list]
|
74
|
-
puts 'Watching:'
|
75
|
-
fw.last_found_filenames.each do |filename|
|
76
|
-
puts " #{filename}"
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
Process.daemon(true, true) if options[:daemon]
|
81
|
-
|
82
|
-
fw.watch do |filename, event|
|
83
|
-
cmd =
|
84
|
-
if options[:exec] && File.exist?(filename)
|
85
|
-
Filewatcher::Runner.new(filename).command
|
86
|
-
elsif ARGV.length > 1
|
87
|
-
ARGV[-1]
|
88
|
-
end
|
89
|
-
|
90
|
-
next puts "file #{event}: #{filename}" unless cmd
|
91
|
-
|
92
|
-
env = Filewatcher::Env.new(filename, event).to_h
|
93
|
-
if options[:restart]
|
94
|
-
child_pid = restart(child_pid, env, cmd)
|
95
|
-
else
|
96
|
-
begin
|
97
|
-
Process.spawn(env, cmd)
|
98
|
-
Process.wait
|
99
|
-
rescue SystemExit, Interrupt
|
100
|
-
exit(0)
|
101
|
-
end
|
102
|
-
end
|
103
|
-
end
|
104
|
-
rescue SystemExit, Interrupt
|
105
|
-
fw.finalize
|
106
|
-
end
|