filewatcher 0.5.4 → 2.0.0.beta1

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.
data/Rakefile DELETED
@@ -1,19 +0,0 @@
1
- require 'rubygems'
2
- require 'rake'
3
- require 'rake/testtask'
4
-
5
- task :default => :test
6
-
7
- desc "Run tests"
8
- task :test do
9
- sh "bacon -Ilib -Itest --automatic --quiet"
10
- delete_list =
11
- %w(test/fixtures/file3.txt
12
- test/fixtures/file4.txt
13
- test/fixtures/file5.txt
14
- test/fixtures/file6.txt
15
- test/fixtures/file7.txt)
16
- delete_list.each do |file|
17
- FileUtils.rm(file)
18
- end
19
- end
@@ -1,168 +0,0 @@
1
- #!/usr/bin/env ruby
2
- require 'rubygems'
3
- require 'filewatcher'
4
- require 'trollop'
5
- require 'pathname'
6
- require 'thread'
7
-
8
- options = Trollop::options do
9
- version "filewatcher, version #{FileWatcher.VERSION} by Thomas Flemming 2016"
10
- banner <<-EOS
11
- Filewatcher scans the filesystem and executes shell commands when files changes.
12
-
13
- Usage:
14
- filewatcher [--restart] '<filenames or patterns>' '<shell command>'
15
- Where
16
- filename: filename(s) to scan.
17
- shell command: shell command to execute when file changes on disk.
18
-
19
- Examples:
20
- filewatcher "myfile" "echo 'myfile has changed'"
21
- filewatcher '*.rb' 'ruby $FILENAME'
22
- filewatcher '**/*.rb' 'ruby $FILENAME' # Watch subdirectories
23
-
24
- Other available environment variables are BASENAME, ABSOLUTE_FILENAME,
25
- RELATIVE_FILENAME, EVENT and DIRNAME.
26
-
27
- Options:
28
- EOS
29
-
30
- opt :dontwait, "Do not wait for filesystem updates before running", :short => 'd', :type => :boolean, :default => false
31
- opt :daemon, "Run in the background as system daemon.", :short => 'D', :type => :boolean, :default => false
32
- opt :restart, "Restart process when filesystem is updated", :short => 'r', :type => :boolean, :default => false
33
- opt :list, "Print name of files being watched"
34
- opt :exec, "Execute file as a script when file is updated.", :short => 'e', :type => :boolean, :default => false
35
- opt :include, "Include files", :type => :string, :default => "*"
36
- opt :exclude, "Exclude file(s) matching", :type => :string, :default => ""
37
- opt :interval, "Interval to scan filesystem.", :short => 'i', :type => :float, :default => 0.5
38
- opt :spinner, "Show an ascii spinner", :short => 's', :type => :boolean, :default => false
39
- end
40
-
41
- Trollop::die Trollop::educate if(ARGV.size == 0)
42
-
43
- files = []
44
- ARGV[0...-1].each do |a|
45
- files << a
46
- end
47
-
48
- if(ARGV.length == 1)
49
- files << ARGV[0]
50
- end
51
-
52
- def split_files_void_escaped_whitespace(files)
53
- splitted_filenames = []
54
- files.each do |name|
55
- name = name.gsub(/\\\s/,'_ESCAPED_WHITESPACE_')
56
- splitted_filenames << name.split(/\s/)
57
- end
58
- files = splitted_filenames.flatten.uniq
59
- splitted_filenames = []
60
- files.each do |name|
61
- splitted_filenames << name.gsub('_ESCAPED_WHITESPACE_','\ ')
62
- end
63
- files = splitted_filenames
64
- end
65
-
66
- files = split_files_void_escaped_whitespace(files)
67
- child_pid = nil
68
-
69
- def restart(child_pid, env, cmd)
70
- Process.kill(9, child_pid)
71
- Process.wait(child_pid)
72
- rescue Errno::ESRCH
73
- # already killed
74
- ensure
75
- return Process.spawn(env, cmd)
76
- end
77
-
78
- if(options[:exclude] != "")
79
- options[:exclude] = split_files_void_escaped_whitespace(options[:exclude].split(" "))
80
- end
81
-
82
- begin
83
- fw = FileWatcher.new(files, options)
84
-
85
- if(options[:list])
86
- puts 'Watching:'
87
- fw.last_found_filenames.each do |filename|
88
- puts " #{filename}"
89
- end
90
- end
91
-
92
- Process.daemon(true, true) if options[:daemon]
93
-
94
- fw.watch(options[:interval]) do |filename, event|
95
- cmd = nil
96
- if(options[:exec] and File.exist?(filename))
97
- extension = filename[/(\.[^\.]*)$/,0]
98
- runners = {
99
- ".py" => "python",
100
- ".js" => "node",
101
- ".rb" => "ruby",
102
- ".pl" => "perl",
103
- ".awk" => "awk",
104
- ".php" => "php",
105
- ".phtml" => "php",
106
- ".php4" => "php",
107
- ".php3" => "php",
108
- ".php5" => "php",
109
- ".phps" => "php"
110
- }
111
- runner = runners[extension]
112
- if(runner)
113
- cmd = "env #{runner.to_s} #{filename}"
114
- end
115
- elsif(ARGV.length > 1)
116
- cmd = ARGV[-1]
117
- end
118
-
119
- if(cmd)
120
- path = Pathname.new(filename)
121
- env = {
122
- 'FILENAME' => filename,
123
- 'BASENAME' => path.basename.to_s,
124
- 'FILEDIR' => File.join(Pathname.new('.').realpath.to_s, path.parent.to_s), # Deprecated
125
- 'FSEVENT' => event.to_s, # Deprecated,
126
- 'EVENT' => event.to_s,
127
- 'DIRNAME' => File.join(Pathname.new('.').realpath.to_s, path.parent.to_s),
128
- 'ABSOLUTE_FILENAME' => File.join(Pathname.new('.').realpath.to_s, path.to_s),
129
- 'RELATIVE_FILENAME' => File.join(Pathname.new('.').to_s, path.to_s)
130
- }
131
-
132
- if(event != :delete)
133
- ENV['FILEPATH'] = path.realpath.to_s
134
- end
135
-
136
- if(options[:restart])
137
- if child_pid.nil?
138
- child_pid = Process.spawn(env, cmd)
139
- else
140
- child_pid = restart(child_pid, env, cmd)
141
- end
142
- else
143
- begin
144
- pid = Process.spawn(env, cmd)
145
- Process.wait()
146
- rescue SystemExit, Interrupt
147
- exit(0)
148
- end
149
- end
150
-
151
- else
152
- case(event)
153
- when :changed
154
- print "file updated"
155
- when :delete
156
- print "file deleted"
157
- when :new
158
- print "new file"
159
- else
160
- print event.to_s
161
- end
162
- puts ": " + filename
163
- end
164
-
165
- end
166
- rescue SystemExit, Interrupt
167
- fw.finalize
168
- end
@@ -1 +0,0 @@
1
- content1
@@ -1 +0,0 @@
1
- content2
@@ -1 +0,0 @@
1
-
@@ -1 +0,0 @@
1
- puts "Hello world from Ruby!!!"
@@ -1 +0,0 @@
1
-
@@ -1 +0,0 @@
1
- puts "This is file6.rb executing"
@@ -1,181 +0,0 @@
1
- require 'rubygems'
2
- require 'bacon'
3
- require 'fileutils'
4
- require File.expand_path("../lib/filewatcher.rb",File.dirname(__FILE__))
5
-
6
-
7
-
8
- describe FileWatcher do
9
-
10
- fixtures =
11
- %w(test/fixtures/file4.rb
12
- test/fixtures/subdir/file6.rb
13
- test/fixtures/subdir/file5.rb
14
- test/fixtures/file2.txt
15
- test/fixtures/file1.txt
16
- test/fixtures/file3.rb)
17
-
18
- explicit_relative_fixtures = fixtures.map { |it| "./#{it}" }
19
-
20
- subfolder = 'test/fixtures/new_sub_folder'
21
-
22
- after do
23
- FileUtils.rm_rf subfolder
24
- end
25
-
26
- def includes_all(elements)
27
- lambda { |it| elements.all? { |element| it.include? element }}
28
- end
29
-
30
- it "should exclude selected file patterns" do
31
- filewatcher = FileWatcher.new(File.expand_path('test/fixtures/**/*'), :exclude => [File.expand_path("test/fixtures/**/*.txt")])
32
- filtered_fixtures =
33
- %w(test/fixtures/file4.rb
34
- test/fixtures/subdir/file6.rb
35
- test/fixtures/subdir/file5.rb
36
- test/fixtures/file3.rb)
37
- filewatcher.filenames.should.satisfy &includes_all(filtered_fixtures.map { |it| File.expand_path(it) })
38
- end
39
-
40
- it "should handle absolute paths with globs" do
41
- filewatcher = FileWatcher.new(File.expand_path('test/fixtures/**/*'))
42
-
43
- filewatcher.filenames.should.satisfy &includes_all(fixtures.map { |it| File.expand_path(it) })
44
- end
45
-
46
- it "should handle globs" do
47
- filewatcher = FileWatcher.new('test/fixtures/**/*')
48
-
49
- filewatcher.filenames.should.satisfy &includes_all(fixtures)
50
- end
51
-
52
-
53
- it "should handle explicit relative paths with globs" do
54
- filewatcher = FileWatcher.new('./test/fixtures/**/*')
55
-
56
- filewatcher.filenames.should.satisfy &includes_all(explicit_relative_fixtures)
57
- end
58
-
59
- it "should handle explicit relative paths" do
60
- filewatcher = FileWatcher.new('./test/fixtures')
61
-
62
- filewatcher.filenames.should.satisfy &includes_all(explicit_relative_fixtures)
63
- end
64
-
65
- it "should handle tilde expansion" do
66
- filename = File.expand_path('~/file_watcher_1.txt')
67
- open(filename, 'w') { |f| f.puts 'content1' }
68
-
69
- filewatcher = FileWatcher.new('~/file_watcher_1.txt')
70
-
71
- begin
72
- filewatcher.filenames.should == [filename]
73
- ensure
74
- FileUtils.rm(filename)
75
- end
76
- end
77
-
78
- it "should detect file deletions" do
79
- filename = "test/fixtures/file1.txt"
80
- open(filename,"w") { |f| f.puts "content1" }
81
- filewatcher = FileWatcher.new(["test/fixtures"])
82
- filewatcher.filesystem_updated?.should.be.false
83
- FileUtils.rm(filename)
84
- filewatcher.filesystem_updated?.should.be.true
85
- end
86
-
87
- it "should detect file additions" do
88
- filename = "test/fixtures/file1.txt"
89
- FileUtils.rm(filename) if File.exists?(filename)
90
- filewatcher = FileWatcher.new(["test/fixtures"])
91
- filewatcher.filesystem_updated?.should.be.false
92
- open(filename,"w") { |f| f.puts "content1" }
93
- filewatcher.filesystem_updated?.should.be.true
94
- end
95
-
96
- it "should detect file updates" do
97
- filename = "test/fixtures/file1.txt"
98
- open(filename,"w") { |f| f.puts "content1" }
99
- filewatcher = FileWatcher.new(["test/fixtures"])
100
- filewatcher.filesystem_updated?.should.be.false
101
- sleep 1
102
- open(filename,"w") { |f| f.puts "content2" }
103
- filewatcher.filesystem_updated?.should.be.true
104
- end
105
-
106
- it "should detect new files in subfolders" do
107
- FileUtils::mkdir_p subfolder
108
-
109
- filewatcher = FileWatcher.new(["./test/fixtures"])
110
- filewatcher.filesystem_updated?.should.be.false
111
-
112
- open(subfolder + "/file.txt","w") { |f| f.puts "xyz" }
113
- filewatcher.filesystem_updated?.should.be.true
114
- end
115
-
116
- it "should detect new subfolders" do
117
- filewatcher = FileWatcher.new(["test/fixtures"])
118
- filewatcher.filesystem_updated?.should.be.false
119
-
120
- FileUtils::mkdir_p subfolder
121
- filewatcher.filesystem_updated?.should.be.true
122
- end
123
-
124
- it "should be stoppable" do
125
- filewatcher = FileWatcher.new(["test/fixtures"])
126
- thread = Thread.new(filewatcher){filewatcher.watch(0.1)}
127
- sleep 0.2 # thread needs a chance to start
128
- filewatcher.stop
129
- thread.join.should.equal thread # Proves thread successfully joined
130
- end
131
-
132
- it "should be pauseable/resumable" do
133
- filewatcher = FileWatcher.new(["test/fixtures"])
134
- filewatcher.filesystem_updated?.should.be.false
135
- processed = []
136
- thread = Thread.new(filewatcher,processed) do
137
- filewatcher.watch(0.1){|f,e| processed << f }
138
- end
139
- sleep 0.2 # thread needs a chance to start
140
- filewatcher.pause
141
- (1..4).each do |n|
142
- open("test/fixtures/file#{n}.txt","w") { |f| f.puts "content#{n}" }
143
- end
144
- sleep 0.2 # Give filewatcher time to respond
145
- processed.should.equal [] #update block should not have been called
146
- filewatcher.resume
147
- sleep 0.2 # Give filewatcher time to respond
148
- processed.should.equal [] #update block still should not have been called
149
- added_files = []
150
- (5..7).each do |n|
151
- added_files << "test/fixtures/file#{n}.txt"
152
- open(added_files.last,"w") { |f| f.puts "content#{n}" }
153
- end
154
- sleep 0.2 # Give filewatcher time to respond
155
- filewatcher.stop
156
- processed.should.satisfy &includes_all(added_files)
157
- end
158
-
159
- it "should process all remaining changes at finalize" do
160
- filewatcher = FileWatcher.new(["test/fixtures"])
161
- filewatcher.filesystem_updated?.should.be.false
162
- processed = []
163
- thread = Thread.new(filewatcher,processed) do
164
- filewatcher.watch(0.1){|f,e| processed << f }
165
- end
166
- sleep 0.2 # thread needs a chance to start
167
- filewatcher.stop
168
- thread.join
169
- added_files = []
170
- (1..4).each do |n|
171
- added_files << "test/fixtures/file#{n}.txt"
172
- open(added_files.last,"w") { |f| f.puts "content#{n}" }
173
- end
174
- filewatcher.finalize
175
- puts "What is wrong with finalize:"
176
- puts "Expect: #{added_files.inspect}"
177
- puts "Actual: #{processed.inspect}"
178
- # processed.should.satisfy &includes_all(added_files)
179
- end
180
-
181
- end