snooper 1.0.1 → 2.0.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 +4 -4
- data/bin/snooper +14 -116
- data/lib/snooper.rb +7 -8
- data/lib/snooper/config.rb +140 -0
- data/lib/snooper/config.rb~ +88 -0
- data/lib/snooper/hook.rb +6 -2
- data/lib/snooper/options.rb +73 -0
- data/lib/snooper/options.rb~ +71 -0
- data/lib/snooper/snoop.rb +71 -69
- data/lib/snooper/version.rb +1 -1
- metadata +14 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bf6a2f05350d836af71cda01ebc7a8eec69550dc
|
4
|
+
data.tar.gz: 9750a737010032c0c16550ee5126fe2dd3ca98cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1cae260fd97fed5f5066e0a8c6633fd2a625ba8c3de148cb1dc06b0eb12791ddb25bb3b025b52fc297b18bc89c62afa09bda171b5a9ca0c82b8b0894d7bf75e6
|
7
|
+
data.tar.gz: 6a74486dc5d7ae30ad1284c7daff857dae120c86cdbaac3cfb85b522e025312a43913124b001611275fc99560e1b7f53370ce3a871e55e4ac8eb0c33288b88d7
|
data/bin/snooper
CHANGED
@@ -6,135 +6,33 @@
|
|
6
6
|
|
7
7
|
require 'snooper'
|
8
8
|
require 'colored'
|
9
|
-
require 'optparse'
|
10
|
-
require 'yaml'
|
11
9
|
|
12
10
|
##
|
13
11
|
# Internal: Main program loop
|
14
12
|
#
|
15
|
-
#
|
13
|
+
# config - the hash containing the options.
|
16
14
|
#
|
17
15
|
# Do our stuff, and exit cleanly when interrupted.
|
18
16
|
#
|
19
17
|
# Returns nothing.
|
20
18
|
def test_loop(options)
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
puts # This is where the ^C is on unix
|
26
|
-
puts "Testing over, time for a coffee...".yellow
|
27
|
-
end
|
19
|
+
Snooper.watch options
|
20
|
+
rescue Interrupt
|
21
|
+
puts # This is where the ^C is on unix
|
22
|
+
puts "Testing over, time for a coffee...".yellow
|
28
23
|
end
|
29
24
|
|
30
|
-
|
31
|
-
# Internal: Parse the command line and load the options
|
32
|
-
#
|
33
|
-
# Returns a processed options hash
|
34
|
-
def get_options
|
35
|
-
|
36
|
-
helptext = <<END
|
37
|
-
|
38
|
-
Snooper is a lightweight test automation tool, it monitors files and folders
|
39
|
-
while you work and re-runs your tests when you change something. Snooper
|
40
|
-
doesn't care what language you're using or what framework you are testing with,
|
41
|
-
it's all configureable.
|
42
|
-
|
43
|
-
For more information see snooper(1).
|
44
|
-
END
|
45
|
-
|
46
|
-
config_path = '.snooper.yaml'
|
47
|
-
opts = OptionParser.new do |opts|
|
48
|
-
opts.banner =
|
49
|
-
"Useage: #{File.basename __FILE__} [--config <CONFIG> | --help] " +
|
50
|
-
"[<COMMAND>]*"
|
51
|
-
|
52
|
-
opts.separator helptext
|
53
|
-
|
54
|
-
opts.on '-c', '--config CONFIGFILE', 'YAML configuration file' do |path|
|
55
|
-
config_path = path
|
56
|
-
end
|
57
|
-
|
58
|
-
opts.on("--version", "show version information") do
|
59
|
-
puts "Snooper v#{Snooper::VERSION}"
|
60
|
-
exit
|
61
|
-
end
|
62
|
-
|
63
|
-
opts.on("-h", "--help", "Show this message") do
|
64
|
-
puts opts
|
65
|
-
exit
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# Parse the options
|
70
|
-
begin
|
71
|
-
opts.parse!
|
72
|
-
rescue OptionParser::InvalidOption, \
|
73
|
-
OptionParser::MissingArgument, \
|
74
|
-
OptionParser::InvalidArgument => e
|
75
|
-
puts e
|
76
|
-
puts opts
|
77
|
-
exit 1
|
78
|
-
end
|
79
|
-
|
80
|
-
# Load the config file
|
81
|
-
begin
|
82
|
-
yamopts = YAML.load_file config_path
|
83
|
-
rescue Exception => e
|
84
|
-
puts "Error loading the config: #{e}"
|
85
|
-
exit 1
|
86
|
-
end
|
87
|
-
|
88
|
-
if not yamopts.is_a? Hash
|
89
|
-
puts "Invalid options file"
|
90
|
-
exit 1
|
91
|
-
end
|
92
|
-
|
93
|
-
# default options
|
94
|
-
options = {
|
95
|
-
:base_path => nil,
|
96
|
-
:command => nil,
|
97
|
-
:filters => [],
|
98
|
-
:ignored => [],
|
99
|
-
:paths => [],
|
100
|
-
:hooks => []
|
101
|
-
}
|
102
|
-
|
103
|
-
yamopts.each do |option, argument|
|
104
|
-
case option
|
105
|
-
when 'base_path', 'command'
|
106
|
-
options[option.to_sym] = argument.to_s
|
107
|
-
|
108
|
-
when 'paths', 'filters', 'ignored'
|
109
|
-
argument = argument.split if argument.is_a? String
|
110
|
-
options[option.to_sym] += Array(argument)
|
111
|
-
|
112
|
-
when 'hooks'
|
113
|
-
argument.each do |hook|
|
114
|
-
options[:hooks] << hook
|
115
|
-
end
|
25
|
+
options = Snooper::Options.parse ARGV
|
116
26
|
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
if options[:base_path]
|
123
|
-
base = File.expand_path options[:base_path], File.dirname(config_path)
|
124
|
-
options[:paths].map! { |p| File.expand_path p, base }
|
125
|
-
options[:base_path] = base
|
126
|
-
end
|
127
|
-
|
128
|
-
# Override the command if one was specified
|
129
|
-
options[:command] = ARGV.join " " if not ARGV.empty?
|
130
|
-
|
131
|
-
options
|
27
|
+
begin
|
28
|
+
config = Snooper::Config.load options.config_path
|
29
|
+
rescue Exception => error
|
30
|
+
$stdout.puts "#{$0}: error: couldn't load '#{options.config_path}' (#{error})"
|
31
|
+
exit 1
|
132
32
|
end
|
133
33
|
|
134
|
-
|
34
|
+
# Override the command if one was specified
|
35
|
+
config.command = options.command if options.command
|
135
36
|
|
136
37
|
# Run the tests, pusing the target directory
|
137
|
-
|
138
|
-
Dir.chdir options[:base_path] if options[:base_path]
|
139
|
-
test_loop options
|
140
|
-
Dir.chdir old_dir
|
38
|
+
test_loop config
|
data/lib/snooper.rb
CHANGED
@@ -10,22 +10,21 @@
|
|
10
10
|
# License:: Snoop is open source! See LICENCE.md for more details.
|
11
11
|
#
|
12
12
|
#
|
13
|
-
# For most applications calling the
|
14
|
-
# if Snooper::Snoop objects can be created directly.
|
13
|
+
# For most applications calling the Snooper#watch method should be sufficient
|
14
|
+
# if not Snooper::Snoop objects can be created directly.
|
15
15
|
module Snooper
|
16
16
|
|
17
17
|
require 'snooper/snoop'
|
18
|
-
require 'snooper/
|
18
|
+
require 'snooper/options'
|
19
|
+
require 'snooper/config'
|
19
20
|
|
20
21
|
##
|
21
22
|
# Public: Watch for changes in a directory
|
22
23
|
#
|
23
|
-
#
|
24
|
-
# information
|
24
|
+
# config - The String containing the path to a config or a Config-like object
|
25
25
|
#
|
26
26
|
# Returns the reseult of the run.
|
27
|
-
def self.watch(
|
28
|
-
|
29
|
-
george.run
|
27
|
+
def self.watch(config)
|
28
|
+
Snoop.new(config).run
|
30
29
|
end
|
31
30
|
end
|
@@ -0,0 +1,140 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Author:: Will Speak (@willspeak)
|
3
|
+
# Copyright:: Copyright (c) 2013 Will Speak
|
4
|
+
# License:: Snooper is open source! See LICENCE.md for more details.
|
5
|
+
|
6
|
+
module Snooper
|
7
|
+
|
8
|
+
require 'snooper/hook'
|
9
|
+
require 'yaml'
|
10
|
+
|
11
|
+
##
|
12
|
+
# Public: Snooper Configuration
|
13
|
+
#
|
14
|
+
# This object contains the configuration information that is
|
15
|
+
class Config
|
16
|
+
|
17
|
+
# base_path - The directory from which all path resolution is based
|
18
|
+
attr_accessor :base_path
|
19
|
+
|
20
|
+
# command - The shell command to run when changes are detected
|
21
|
+
attr_accessor :command
|
22
|
+
|
23
|
+
# paths - The Array of paths to watch for changes
|
24
|
+
attr_accessor :paths
|
25
|
+
|
26
|
+
# filters - The Array of Regex containing the inclusion finters
|
27
|
+
attr_accessor :filters
|
28
|
+
|
29
|
+
# ignored = The Array of Regex containing the exclusion filters
|
30
|
+
attr_accessor :ignored
|
31
|
+
|
32
|
+
# hooks - The Array of Hook objects
|
33
|
+
attr_accessor :hooks
|
34
|
+
|
35
|
+
##
|
36
|
+
# Public: create a new config object
|
37
|
+
#
|
38
|
+
# base_path - The String representing the path from which all the other
|
39
|
+
# paths should be resolved. Nil to use the current directory.
|
40
|
+
# command - The command to execute when a change satisfies all the
|
41
|
+
# predicates.
|
42
|
+
# options - The hash containing all of the optinal parameters.
|
43
|
+
# :paths - The Array of the paths to watch, relative to the
|
44
|
+
# base. Nil or empty to watch the whole directory.
|
45
|
+
# :filters - THe Array of Regex-like inclusion filters. Nil or
|
46
|
+
# empty to trigger on all changes.
|
47
|
+
# :ignored - The Array of Regex-like ignore filters. Nil or
|
48
|
+
# empty to ignore no changes.
|
49
|
+
# :hooks - The Array of Hook objects to call when a change
|
50
|
+
# satisifies all the predicates and before the
|
51
|
+
# command is run. Nil or empty for no hooks.
|
52
|
+
def initialize(base_path, command, options={})
|
53
|
+
|
54
|
+
raise ArgumentError, "No command supplied in config" if command == nil
|
55
|
+
|
56
|
+
# use normalised base_path, or CWD if none is given
|
57
|
+
@base_path = (base_path && File.expand_path(base_path)) || Dir.pwd
|
58
|
+
|
59
|
+
# comand is used verbotem
|
60
|
+
@command = command
|
61
|
+
|
62
|
+
# paths are expanded relative to tbe base, otherwise the base is returned
|
63
|
+
base_expand = Proc.new { |p| File.expand_path(p, @base_path) }
|
64
|
+
@paths = (options[:paths] && options[:paths].map(&base_expand))
|
65
|
+
@paths ||= [@base_path]
|
66
|
+
|
67
|
+
# filters all need to be converted to regexes
|
68
|
+
rgx_key = Proc.new do |k|
|
69
|
+
to_regex = Proc.new { |r| Regexp.try_convert(r) || Regexp.new(r) }
|
70
|
+
(options[k] && Array(options[k]).map(&to_regex)) || []
|
71
|
+
end
|
72
|
+
|
73
|
+
@filters = rgx_key.call :filters
|
74
|
+
@ignored = rgx_key.call :ignored
|
75
|
+
|
76
|
+
@hooks = (options[:hooks] && create_hooks(options[:hooks])) || []
|
77
|
+
end
|
78
|
+
|
79
|
+
##
|
80
|
+
# Public: Create Hook Objects
|
81
|
+
#
|
82
|
+
# raw_hooks - The Array of unprocessed hooks. Each item shoudl either be
|
83
|
+
# a map containing the pattern to match and the command to run
|
84
|
+
# or a Hook or Hook-like object.
|
85
|
+
#
|
86
|
+
# Returns an Array of Hooks
|
87
|
+
def create_hooks(raw_hooks)
|
88
|
+
raw_hooks.to_a.map do |hook|
|
89
|
+
case hook
|
90
|
+
when Hash
|
91
|
+
Hook.new hook["pattern"], hook["command"]
|
92
|
+
else
|
93
|
+
hook
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
##
|
99
|
+
# Public: create a new config from a YAML file
|
100
|
+
#
|
101
|
+
# Retuns a new instace of the Config class
|
102
|
+
def self.load(*args)
|
103
|
+
instance = allocate
|
104
|
+
instance.initialize_from_yaml *args
|
105
|
+
instance
|
106
|
+
end
|
107
|
+
|
108
|
+
##
|
109
|
+
# Implementaiton: load and initialise a config from a YAML file
|
110
|
+
#
|
111
|
+
# file_path - The String containing the path to the YAML file.
|
112
|
+
def initialize_from_yaml(file_path)
|
113
|
+
# Load the options file
|
114
|
+
raw_options = YAML.load_file file_path
|
115
|
+
|
116
|
+
base_path = raw_options.delete 'base_path'
|
117
|
+
command = raw_options.delete 'command'
|
118
|
+
|
119
|
+
options = raw_options.each_with_object(Hash.new) do |(key, value), opts|
|
120
|
+
|
121
|
+
case key
|
122
|
+
when 'paths', 'filters', 'ignored'
|
123
|
+
value = value.split if value.is_a? String
|
124
|
+
|
125
|
+
when 'hooks'
|
126
|
+
value.map! do |hook_hash|
|
127
|
+
Hook.new hook_hash["pattern"], hook_hash["command"]
|
128
|
+
end
|
129
|
+
|
130
|
+
else
|
131
|
+
$stderr.puts "warning: ignoring unknown option #{key}"
|
132
|
+
end
|
133
|
+
|
134
|
+
opts[key.to_sym] = value
|
135
|
+
end
|
136
|
+
|
137
|
+
initialize base_path, command, options
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
@@ -0,0 +1,88 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Author:: Will Speak (@willspeak)
|
3
|
+
# Copyright:: Copyright (c) 2013 Will Speak
|
4
|
+
# License:: Snooper is open source! See LICENCE.md for more details.
|
5
|
+
|
6
|
+
module Snooper
|
7
|
+
|
8
|
+
##
|
9
|
+
# Public: Snooper Configuration
|
10
|
+
#
|
11
|
+
# This object contains the configuration information that is
|
12
|
+
class Config
|
13
|
+
|
14
|
+
##
|
15
|
+
# Public: create a new config object
|
16
|
+
#
|
17
|
+
# base_path - The String representing the path from which all the other
|
18
|
+
# paths should be resolved. Nil to use the current directory.
|
19
|
+
# command - The command to execute when a change satisfies all the
|
20
|
+
# predicates.
|
21
|
+
# options - The hash containing all of the optinal parameters.
|
22
|
+
# :paths - The Array of the paths to watch, relative to the
|
23
|
+
# base. Nil or empty to watch the whole directory.
|
24
|
+
# :filters - THe Array of Regex-like inclusion filters. Nil or
|
25
|
+
# empty to trigger on all changes.
|
26
|
+
# :ignored - The Array of Regex-like ignore filters. Nil or
|
27
|
+
# empty to ignore no changes.
|
28
|
+
# :hooks - The Array of Hook objects to call when a change
|
29
|
+
# satisifies all the predicates and before the
|
30
|
+
# command is run. Nil or empty for no hooks.
|
31
|
+
end
|
32
|
+
|
33
|
+
=begin
|
34
|
+
##
|
35
|
+
# Public: Load the config from disk
|
36
|
+
#
|
37
|
+
# path - The String containing the path of the config file
|
38
|
+
#
|
39
|
+
# Returns a new Config.
|
40
|
+
def self.new(path)
|
41
|
+
|
42
|
+
# Load the config file begin yamopts = YAML.load_file path
|
43
|
+
rescue Exception => e puts "Error loading the config: #{e}" exit
|
44
|
+
1 end if not yamopts.is_a? Hash puts "Invalid options file" exit
|
45
|
+
1 end
|
46
|
+
# default config
|
47
|
+
config = {
|
48
|
+
:base_path => '.',
|
49
|
+
:command => nil,
|
50
|
+
:filters => [],
|
51
|
+
:ignored => [],
|
52
|
+
:paths => [],
|
53
|
+
:hooks => []
|
54
|
+
}
|
55
|
+
|
56
|
+
yamopts.each do |option, argument|
|
57
|
+
case option
|
58
|
+
when 'base_path', 'command'
|
59
|
+
config[option.to_sym] = argument.to_s
|
60
|
+
|
61
|
+
when 'paths', 'filters', 'ignored'
|
62
|
+
argument = argument.split if argument.is_a? String
|
63
|
+
config[option.to_sym] += Array(argument)
|
64
|
+
|
65
|
+
when 'hooks'
|
66
|
+
argument.each do |hook|
|
67
|
+
config[:hooks] << hook
|
68
|
+
end
|
69
|
+
|
70
|
+
else
|
71
|
+
puts "Ignoring unknown option #{option}".red
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
[:filters, :ignored].each do |index|
|
76
|
+
config[index].map! { |r| Regexp.try_convert(r) || Regexp.new(r) }
|
77
|
+
end
|
78
|
+
|
79
|
+
if config[:base_path]
|
80
|
+
base = File.expand_path config[:base_path], File.dirname(path)
|
81
|
+
config[:paths].map! { |p| File.expand_path p, base }
|
82
|
+
config[:base_path] = base
|
83
|
+
end
|
84
|
+
|
85
|
+
config
|
86
|
+
end
|
87
|
+
=end
|
88
|
+
end
|
data/lib/snooper/hook.rb
CHANGED
@@ -19,8 +19,12 @@ module Snooper
|
|
19
19
|
#
|
20
20
|
# Returns a new Hook
|
21
21
|
def initialize(pattern, command)
|
22
|
-
|
23
|
-
|
22
|
+
if pattern == nil
|
23
|
+
raise ArgumentError, "No pattern supplied for Hook '#{command}'"
|
24
|
+
end
|
25
|
+
if command == nil
|
26
|
+
raise ArgumentError, "No command supplied for Hook '#{pattern}'"
|
27
|
+
end
|
24
28
|
@command = command
|
25
29
|
@pattern = to_regex pattern
|
26
30
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Author:: Will Speak (@willspeak)
|
3
|
+
# Copyright:: Copyright (c) 2013 Will Speak
|
4
|
+
# License:: Snooper is open source! See LICENCE.md for more details.
|
5
|
+
|
6
|
+
module Snooper
|
7
|
+
|
8
|
+
module Options
|
9
|
+
require 'optparse'
|
10
|
+
|
11
|
+
##
|
12
|
+
# Public: Command Line Options
|
13
|
+
ParsedOptions = Struct.new :config_path, :command
|
14
|
+
|
15
|
+
##
|
16
|
+
# Public: Parse the command line
|
17
|
+
#
|
18
|
+
# arguments - The list of string arguments to be parsed
|
19
|
+
#
|
20
|
+
# Returns an Options struct containing :base_path and :command
|
21
|
+
def self.parse(arguments)
|
22
|
+
|
23
|
+
helptext = <<END
|
24
|
+
|
25
|
+
Snooper is a lightweight test automation tool, it monitors files and folders
|
26
|
+
while you work and re-runs your tests when you change something. Snooper
|
27
|
+
doesn't care what language you're using or what framework you are testing with,
|
28
|
+
it's all configureable.
|
29
|
+
|
30
|
+
For more information see snooper(1).
|
31
|
+
END
|
32
|
+
|
33
|
+
options = ParsedOptions.new
|
34
|
+
options.config_path = '.snooper.yaml'
|
35
|
+
|
36
|
+
parser = OptionParser.new do |parser|
|
37
|
+
parser.banner =
|
38
|
+
"Useage: #{File.basename __FILE__} [--config <CONFIG> | --help] " +
|
39
|
+
"[<COMMAND>]*"
|
40
|
+
|
41
|
+
parser.separator helptext
|
42
|
+
|
43
|
+
parser.on '-c', '--config CONFIGFILE', 'YAML configuration file' do |path|
|
44
|
+
options.config_path = path
|
45
|
+
end
|
46
|
+
|
47
|
+
parser.on("--version", "show version information") do
|
48
|
+
puts "Snooper v#{Snooper::VERSION}"
|
49
|
+
exit
|
50
|
+
end
|
51
|
+
|
52
|
+
parser.on("-h", "--help", "Show this message") do
|
53
|
+
puts parser
|
54
|
+
exit
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# Parse the arguments
|
59
|
+
begin
|
60
|
+
parser.parse! arguments
|
61
|
+
rescue OptionParser::InvalidOption, \
|
62
|
+
OptionParser::MissingArgument, \
|
63
|
+
OptionParser::InvalidArgument => e
|
64
|
+
puts e
|
65
|
+
puts parser
|
66
|
+
exit 1
|
67
|
+
end
|
68
|
+
|
69
|
+
options.command = arguments.join " " if not arguments.empty?
|
70
|
+
options
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# Author:: Will Speak (@willspeak)
|
3
|
+
# Copyright:: Copyright (c) 2013 Will Speak
|
4
|
+
# License:: Snooper is open source! See LICENCE.md for more details.
|
5
|
+
|
6
|
+
module Snooper
|
7
|
+
|
8
|
+
module Options
|
9
|
+
##
|
10
|
+
# Public: Command Line Options
|
11
|
+
ParsedOptions = Struct.new :config_path, :command
|
12
|
+
|
13
|
+
##
|
14
|
+
# Public: Parse the command line
|
15
|
+
#
|
16
|
+
# arguments - The list of string arguments to be parsed
|
17
|
+
#
|
18
|
+
# Returns an Options struct containing :base_path and :command
|
19
|
+
def parse(arguments)
|
20
|
+
|
21
|
+
helptext = <<END
|
22
|
+
|
23
|
+
Snooper is a lightweight test automation tool, it monitors files and folders
|
24
|
+
while you work and re-runs your tests when you change something. Snooper
|
25
|
+
doesn't care what language you're using or what framework you are testing with,
|
26
|
+
it's all configureable.
|
27
|
+
|
28
|
+
For more information see snooper(1).
|
29
|
+
END
|
30
|
+
|
31
|
+
options = ParsedOptions.new
|
32
|
+
options.config_path = '.snooper.yaml'
|
33
|
+
|
34
|
+
parser = OptionParser.new do |parser|
|
35
|
+
parser.banner =
|
36
|
+
"Useage: #{File.basename __FILE__} [--config <CONFIG> | --help] " +
|
37
|
+
"[<COMMAND>]*"
|
38
|
+
|
39
|
+
parser.separator helptext
|
40
|
+
|
41
|
+
parser.on '-c', '--config CONFIGFILE', 'YAML configuration file' do |path|
|
42
|
+
config_path = path
|
43
|
+
end
|
44
|
+
|
45
|
+
parser.on("--version", "show version information") do
|
46
|
+
puts "Snooper v#{Snooper::VERSION}"
|
47
|
+
exit
|
48
|
+
end
|
49
|
+
|
50
|
+
parser.on("-h", "--help", "Show this message") do
|
51
|
+
puts parser
|
52
|
+
exit
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Parse the arguments
|
57
|
+
begin
|
58
|
+
parser.parse! arguments
|
59
|
+
rescue OptionParser::InvalidOption, \
|
60
|
+
OptionParser::MissingArgument, \
|
61
|
+
OptionParser::InvalidArgument => e
|
62
|
+
puts e
|
63
|
+
puts parser
|
64
|
+
exit 1
|
65
|
+
end
|
66
|
+
|
67
|
+
options.command = arguments.join " " if not arguments.empty?
|
68
|
+
options
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/lib/snooper/snoop.rb
CHANGED
@@ -3,7 +3,7 @@
|
|
3
3
|
# Copyright:: Copyright (c) 2013 Will Speak
|
4
4
|
# License:: Snoop is open source! See LICENCE.md for more details.
|
5
5
|
|
6
|
-
require 'snooper/
|
6
|
+
require 'snooper/config'
|
7
7
|
|
8
8
|
module Snooper
|
9
9
|
|
@@ -21,36 +21,15 @@ module Snooper
|
|
21
21
|
##
|
22
22
|
# Public: Create a new source code spy
|
23
23
|
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
to_regex = Proc.new { |r| Regexp.try_convert(r) || Regexp.new(r) }
|
34
|
-
|
35
|
-
@paths = Array(path)
|
36
|
-
@filters = args[:filters]
|
37
|
-
@filters = Array(@filters).map(&to_regex) if @filters
|
38
|
-
@ignored = args[:ignored]
|
39
|
-
@ignored = Array(@ignored).map(&to_regex) if @ignored
|
40
|
-
@command = args[:command]
|
41
|
-
@hooks = create_hooks(args[:hooks])
|
42
|
-
end
|
43
|
-
|
44
|
-
##
|
45
|
-
# Public: Create Hook Objects
|
46
|
-
#
|
47
|
-
# raw_hooks - The Array of maps. Each map should contain the pattern to
|
48
|
-
# match and the command to run.
|
49
|
-
#
|
50
|
-
# Returns an Array of Hooks
|
51
|
-
def create_hooks(raw_hooks)
|
52
|
-
raw_hooks.to_a.map do |hook|
|
53
|
-
Hook.new hook["pattern"], hook["command"]
|
24
|
+
# config - The String containing the path to the config or a Snooper::Config
|
25
|
+
# like object. If the path is a directory and not a file then
|
26
|
+
# default config names are searched for in the direcory.
|
27
|
+
def initialize(config)
|
28
|
+
case config
|
29
|
+
when String
|
30
|
+
@config = Snooper::Config.load config
|
31
|
+
else
|
32
|
+
@config = config
|
54
33
|
end
|
55
34
|
end
|
56
35
|
|
@@ -70,6 +49,21 @@ module Snooper
|
|
70
49
|
return result, after - before
|
71
50
|
end
|
72
51
|
|
52
|
+
##
|
53
|
+
# Internal: Run a block in a dir
|
54
|
+
#
|
55
|
+
# direcotry - The String containing the path to change to
|
56
|
+
# block - The block to run
|
57
|
+
#
|
58
|
+
# Returns the result of the block's execution.
|
59
|
+
def in_dir(directory, &block)
|
60
|
+
old_dir = File.expand_path '.'
|
61
|
+
Dir.chdir directory if directory
|
62
|
+
r = yield block
|
63
|
+
Dir.chdir old_dir
|
64
|
+
r
|
65
|
+
end
|
66
|
+
|
73
67
|
##
|
74
68
|
# Internal: Change callback
|
75
69
|
#
|
@@ -84,38 +78,45 @@ module Snooper
|
|
84
78
|
#
|
85
79
|
# Returns nothing.
|
86
80
|
def on_change(modified, added, removed)
|
87
|
-
|
88
|
-
|
89
|
-
@listener.pause if @listener
|
81
|
+
# Puase the listener to avoid spurious triggers from build output
|
82
|
+
@listener.pause if @listener
|
90
83
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
84
|
+
# summarise the changes made
|
85
|
+
changes = modified + added + removed
|
86
|
+
|
87
|
+
statusline = ('-' * removed.length).red
|
88
|
+
statusline << ('.' * modified.length).blue
|
89
|
+
statusline << ('+' * added.length).green
|
90
|
+
puts "#{statusline} #{changes.length.to_s.magenta.bold} changes"
|
91
|
+
|
92
|
+
@config.hooks.each do |hook|
|
93
|
+
hook.run changes
|
94
|
+
end
|
102
95
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
96
|
+
run_command
|
97
|
+
|
98
|
+
# return to listening
|
99
|
+
@listener.unpause if @listener
|
100
|
+
rescue Exception => e
|
101
|
+
puts e.message
|
102
|
+
puts e.backtrace
|
103
|
+
end
|
104
|
+
|
105
|
+
##
|
106
|
+
# Internal: Run command and print the result
|
107
|
+
#
|
108
|
+
# Return result of the command
|
109
|
+
def run_command
|
110
|
+
# run the test suite and check the result
|
111
|
+
res, time = time_command @config.command
|
112
|
+
if res then
|
113
|
+
puts statusbar "✓ All tests passed", time, &:white_on_green
|
114
|
+
else
|
115
|
+
puts statusbar "✗ Tests failed", time, &:white_on_red
|
116
116
|
end
|
117
|
+
res
|
117
118
|
end
|
118
|
-
|
119
|
+
|
119
120
|
##
|
120
121
|
# Internal: Prettify a status line
|
121
122
|
#
|
@@ -143,17 +144,18 @@ module Snooper
|
|
143
144
|
#
|
144
145
|
# Returns the result of the listener
|
145
146
|
def run
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
147
|
+
in_dir @config.base_path do
|
148
|
+
# Force a change to start with
|
149
|
+
run_command
|
150
|
+
|
151
|
+
callback_helper = Proc.new { |*args| self.on_change *args }
|
152
|
+
|
153
|
+
@listener = Listen.to(*@config.paths, latency: 0.5,
|
154
|
+
filter: @config.filters, ignore: @config.ignored)
|
155
|
+
@listener.change &callback_helper
|
155
156
|
|
156
|
-
|
157
|
+
@listener.start!
|
158
|
+
end
|
157
159
|
end
|
158
160
|
end
|
159
161
|
end
|
data/lib/snooper/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: snooper
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Will Speak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-07-
|
11
|
+
date: 2013-07-20 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: colored
|
@@ -66,22 +66,23 @@ dependencies:
|
|
66
66
|
- - '>='
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: 0.7.3
|
69
|
-
description:
|
70
|
-
|
71
|
-
|
72
|
-
it's all
|
73
|
-
|
69
|
+
description: |
|
70
|
+
Snooper is a lightweight test automation tool, it monitors files and folders
|
71
|
+
while you work and re-runs your tests when you change something. Snooper doesn't
|
72
|
+
care what language you're using or what framework you are testing with, it's all
|
73
|
+
configureable.
|
74
|
+
email: will@willspeak.me
|
74
75
|
executables:
|
75
76
|
- snooper
|
76
77
|
extensions: []
|
77
|
-
extra_rdoc_files:
|
78
|
-
- man/snooper-config.7.ronn
|
79
|
-
- man/snooper.1.ronn
|
80
|
-
- LICENCE.md
|
81
|
-
- README.md
|
78
|
+
extra_rdoc_files: []
|
82
79
|
files:
|
80
|
+
- lib/snooper/config.rb
|
81
|
+
- lib/snooper/config.rb~
|
83
82
|
- lib/snooper/hook.rb
|
84
83
|
- lib/snooper/hook.rb~
|
84
|
+
- lib/snooper/options.rb
|
85
|
+
- lib/snooper/options.rb~
|
85
86
|
- lib/snooper/snoop.rb
|
86
87
|
- lib/snooper/version.rb
|
87
88
|
- lib/snooper.rb
|
@@ -99,9 +100,7 @@ licenses:
|
|
99
100
|
- MIT
|
100
101
|
metadata: {}
|
101
102
|
post_install_message:
|
102
|
-
rdoc_options:
|
103
|
-
- --main
|
104
|
-
- README.md
|
103
|
+
rdoc_options: []
|
105
104
|
require_paths:
|
106
105
|
- lib
|
107
106
|
required_ruby_version: !ruby/object:Gem::Requirement
|