ak47 0.2.3 → 0.2.4
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/bin/ak47 +1 -1
- data/lib/ak47.rb +1 -48
- data/lib/ak47/cli.rb +54 -0
- data/lib/ak47/runner.rb +58 -7
- data/lib/ak47/version.rb +1 -1
- metadata +5 -4
data/bin/ak47
CHANGED
data/lib/ak47.rb
CHANGED
@@ -5,57 +5,10 @@ require 'optparse'
|
|
5
5
|
|
6
6
|
require "ak47/version"
|
7
7
|
require "ak47/runner"
|
8
|
+
require 'ak47/cli'
|
8
9
|
|
9
10
|
module Ak47
|
10
11
|
Reload = Class.new(RuntimeError)
|
11
|
-
|
12
|
-
class << self
|
13
|
-
def run(*argv)
|
14
|
-
argv_opts, commands = if argv == ['--help'] or argv == ['-help']
|
15
|
-
[argv, []]
|
16
|
-
elsif divider_index = argv.index('--')
|
17
|
-
[argv[0...divider_index], argv[divider_index.succ...argv.size]]
|
18
|
-
else
|
19
|
-
[[], argv]
|
20
|
-
end
|
21
|
-
|
22
|
-
interval, maximum, error_time = nil, nil, 5
|
23
|
-
optparse = OptionParser.new do |opts|
|
24
|
-
opts.banner = "Usage: ak47 [cmd] / ak47 [options] -- [cmd]"
|
25
|
-
opts.on( '-i', '--interval [FLOAT]', 'Interval before restarting' ) do |i|
|
26
|
-
interval = Float(i) rescue raise("Interval must be a valid floating point number (e.g. -i0.5)")
|
27
|
-
raise("Interval must be a positive number") unless interval >= 0
|
28
|
-
end
|
29
|
-
opts.on( '-m', '--maximum [FLOAT]', 'Maximum time to wait before restarting' ) do |m|
|
30
|
-
maximum = Float(m) rescue raise("Maximum must be a valid floating point number (e.g. -m60)")
|
31
|
-
raise("Maximum must be a positive number") unless maximum >= 0
|
32
|
-
end
|
33
|
-
opts.on( '-e', '--error-time [FLOAT]', 'Maximum time to wait before restarting if there was an abnormal status code' ) do |e|
|
34
|
-
error_time = Float(e) rescue raise("Error time must be a valid floating point number (e.g. -e10)")
|
35
|
-
raise("Maximum must be a positive number") unless error_time >= 0
|
36
|
-
end
|
37
|
-
opts.on( '-h', '--help', 'Display this screen' ) do
|
38
|
-
puts opts
|
39
|
-
exit
|
40
|
-
end
|
41
|
-
end
|
42
|
-
optparse.parse!(argv_opts)
|
43
|
-
watch_dirs = argv_opts
|
44
|
-
watch_dirs << Dir.pwd if watch_dirs.empty?
|
45
|
-
watch_dirs.map! { |wd| File.expand_path(wd, Dir.pwd) }
|
46
|
-
|
47
|
-
command = ShellTools.escape(commands).strip
|
48
|
-
if command.empty?
|
49
|
-
puts optparse
|
50
|
-
puts
|
51
|
-
raise "No command supplied"
|
52
|
-
end
|
53
|
-
Runner.new(:watch_dirs => watch_dirs, :maximum => maximum, :interval => interval, :error_time => error_time, :command => command) { exec(command) }.start
|
54
|
-
rescue
|
55
|
-
puts $!.message.red
|
56
|
-
exit 1
|
57
|
-
end
|
58
|
-
end
|
59
12
|
end
|
60
13
|
|
61
14
|
def Ak47(opts = nil, &blk)
|
data/lib/ak47/cli.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
module Ak47
|
2
|
+
module CLI
|
3
|
+
def self.run(*argv)
|
4
|
+
argv_opts, commands = if argv == ['--help'] or argv == ['-help']
|
5
|
+
[argv, []]
|
6
|
+
elsif divider_index = argv.index('--')
|
7
|
+
[argv[0...divider_index], argv[divider_index.succ...argv.size]]
|
8
|
+
else
|
9
|
+
[[], argv]
|
10
|
+
end
|
11
|
+
|
12
|
+
interval, maximum, error_time, interrupt = nil, nil, 5, true
|
13
|
+
optparse = OptionParser.new do |opts|
|
14
|
+
opts.banner = "Usage: ak47 [cmd] / ak47 [options] -- [cmd]"
|
15
|
+
opts.on( '-i', '--interval [FLOAT]', 'Interval before restarting' ) do |i|
|
16
|
+
interval = Float(i) rescue raise("Interval must be a valid floating point number (e.g. -i0.5)")
|
17
|
+
raise("Interval must be a positive number") unless interval >= 0
|
18
|
+
end
|
19
|
+
opts.on( '-m', '--maximum [FLOAT]', 'Maximum time to wait before restarting' ) do |m|
|
20
|
+
maximum = Float(m) rescue raise("Maximum must be a valid floating point number (e.g. -m60)")
|
21
|
+
raise("Maximum must be a positive number") unless maximum >= 0
|
22
|
+
end
|
23
|
+
opts.on( '-e', '--error-time [FLOAT]', 'Maximum time to wait before restarting if there was an abnormal status code' ) do |e|
|
24
|
+
error_time = Float(e) rescue raise("Error time must be a valid floating point number (e.g. -e10)")
|
25
|
+
raise("Maximum must be a positive number") unless error_time >= 0
|
26
|
+
end
|
27
|
+
opts.on( '-d', '--dont-interrupt', 'Don\'t interrupt a running process, wait for it to finish before reloading' ) do
|
28
|
+
interrupt = false
|
29
|
+
end
|
30
|
+
opts.on( '-h', '--help', 'Display this screen' ) do
|
31
|
+
puts opts
|
32
|
+
exit
|
33
|
+
end
|
34
|
+
end
|
35
|
+
optparse.parse!(argv_opts)
|
36
|
+
watch_dirs = argv_opts
|
37
|
+
watch_dirs << Dir.pwd if watch_dirs.empty?
|
38
|
+
watch_dirs.map! { |wd| File.expand_path(wd, Dir.pwd) }
|
39
|
+
|
40
|
+
command = ShellTools.escape(commands).strip
|
41
|
+
if command.empty?
|
42
|
+
puts optparse
|
43
|
+
puts
|
44
|
+
raise "No command supplied"
|
45
|
+
end
|
46
|
+
Runner.new(:watch_dirs => watch_dirs, :maximum => maximum, :interval => interval, :error_time => error_time, :command => command, :interrupt => interrupt) {
|
47
|
+
exec(command)
|
48
|
+
}.start
|
49
|
+
rescue
|
50
|
+
puts $!.message.red
|
51
|
+
exit 1
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
data/lib/ak47/runner.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
module Ak47
|
2
2
|
class Runner
|
3
|
-
attr_reader :watch_dirs, :maximum, :interval, :error_time, :command
|
3
|
+
attr_reader :watch_dirs, :maximum, :interval, :error_time, :command, :interrupt
|
4
4
|
|
5
5
|
def initialize(opts = nil, &blk)
|
6
6
|
@watch_dirs = Array(opts && opts[:watch_dirs] || Dir.pwd)
|
@@ -8,17 +8,27 @@ module Ak47
|
|
8
8
|
@interval = opts && opts[:interval] || 0.01
|
9
9
|
@error_time = opts && opts[:error_time] || 5
|
10
10
|
@command = opts && opts[:command]
|
11
|
+
@interrupt = opts && opts.key?(:interrupt) ? opts[:interrupt] : true
|
11
12
|
@blk = blk
|
12
13
|
end
|
13
14
|
|
14
15
|
def start
|
15
16
|
listeners = watch_dirs.map {|wd| Guard::Listener.select_and_init(:watchdir => wd, :watch_all_modifications => true) }
|
17
|
+
change_detected = false
|
18
|
+
running = false
|
16
19
|
listeners.each do |l|
|
17
|
-
l.on_change { |f|
|
20
|
+
l.on_change { |f|
|
21
|
+
if @interrupt
|
22
|
+
Thread.main.raise Reload, "File system changed"
|
23
|
+
else
|
24
|
+
change_detected = true
|
25
|
+
Thread.main.raise Reload, "File system changed" unless running
|
26
|
+
end
|
27
|
+
}
|
18
28
|
Thread.new { l.start }
|
19
29
|
end
|
20
30
|
|
21
|
-
at_exit {
|
31
|
+
at_exit { kill_pid }
|
22
32
|
|
23
33
|
puts "[Starting ak47 #{VERSION} in #{watch_dirs.join(', ')}]".green
|
24
34
|
loop do
|
@@ -28,17 +38,30 @@ module Ak47
|
|
28
38
|
if maximum
|
29
39
|
@thread = Thread.new { sleep maximum; Thread.main.raise Reload, "Cancelled due to maximum time" }
|
30
40
|
end
|
31
|
-
|
32
|
-
|
41
|
+
running = true
|
42
|
+
change_detected = false
|
43
|
+
begin
|
44
|
+
@pid = fork(&@blk)
|
45
|
+
Process.detach(@pid)
|
46
|
+
_, status = Process.waitpid2(@pid)
|
47
|
+
ensure
|
48
|
+
running = false
|
49
|
+
end
|
33
50
|
@thread.kill if @thread
|
34
51
|
if status.success?
|
35
|
-
|
36
|
-
|
52
|
+
if change_detected
|
53
|
+
puts "[Change detected while previously running]".green
|
54
|
+
change_detected = false
|
55
|
+
else
|
56
|
+
puts "[Terminated, waiting for file system change]".green
|
57
|
+
maximum ? sleep(interval) : sleep
|
58
|
+
end
|
37
59
|
else
|
38
60
|
puts "[Terminated abnormally (#{status.inspect}), retrying in 5s]".red
|
39
61
|
sleep error_time
|
40
62
|
end
|
41
63
|
rescue Reload => e
|
64
|
+
kill_pid
|
42
65
|
sleep interval
|
43
66
|
puts "[Reloading (#{e.message}) #{Time.new.to_s}]".yellow
|
44
67
|
rescue Interrupt
|
@@ -47,5 +70,33 @@ module Ak47
|
|
47
70
|
end
|
48
71
|
end
|
49
72
|
end
|
73
|
+
|
74
|
+
def kill_pid
|
75
|
+
if @pid
|
76
|
+
begin
|
77
|
+
unless wait_pid('INT')
|
78
|
+
unless wait_pid('KILL')
|
79
|
+
raise "[Unable to kill #{@pid}]"
|
80
|
+
end
|
81
|
+
end
|
82
|
+
rescue Errno::ESRCH
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def wait_pid(sig)
|
88
|
+
count = 0
|
89
|
+
while count < 5
|
90
|
+
begin
|
91
|
+
Process.kill(sig, @pid)
|
92
|
+
count += 1
|
93
|
+
sleep 1
|
94
|
+
rescue Errno::ESRCH
|
95
|
+
@pid = nil
|
96
|
+
return true
|
97
|
+
end
|
98
|
+
end
|
99
|
+
false
|
100
|
+
end
|
50
101
|
end
|
51
102
|
end
|
data/lib/ak47/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ak47
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 4
|
10
|
+
version: 0.2.4
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Josh Hull
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2012-01-
|
18
|
+
date: 2012-01-11 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
21
|
name: guard
|
@@ -80,6 +80,7 @@ files:
|
|
80
80
|
- ak47.gemspec
|
81
81
|
- bin/ak47
|
82
82
|
- lib/ak47.rb
|
83
|
+
- lib/ak47/cli.rb
|
83
84
|
- lib/ak47/runner.rb
|
84
85
|
- lib/ak47/version.rb
|
85
86
|
homepage: ""
|