snooper 1.0.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|