guard 2.10.2 → 2.10.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,93 +0,0 @@
1
- module Guard
2
- # @private api
3
- module Internals
4
- class Environment
5
- class Error < ArgumentError
6
- end
7
-
8
- class MethodError < Error
9
- def initialize(meth)
10
- @meth = meth
11
- end
12
- end
13
-
14
- class NoMethodError < MethodError
15
- def message
16
- format("No such method %s", @meth.inspect)
17
- end
18
- end
19
-
20
- class AlreadyExistsError < MethodError
21
- def message
22
- format("Method %s already exists", @meth.inspect)
23
- end
24
- end
25
-
26
- class Loader
27
- def initialize(meth)
28
- @bool = meth.to_s.end_with?("?")
29
- end
30
-
31
- def load(raw_value, &callback)
32
- return callback.call(raw_value) if callback
33
- @bool ? _to_bool(raw_value) : raw_value
34
- end
35
-
36
- private
37
-
38
- def _to_bool(raw_value)
39
- case raw_value
40
- when nil
41
- nil
42
- when ""
43
- fail ArgumentError, "Can't convert empty string into Bool"
44
- when "0", "false"
45
- false
46
- else
47
- true
48
- end
49
- end
50
- end
51
-
52
- class Dumper
53
- def initialize
54
- end
55
-
56
- def dump(raw_value, &callback)
57
- return callback.call(raw_value) if callback
58
- raw_value.nil? ? nil : raw_value.to_s
59
- end
60
- end
61
-
62
- def initialize(namespace)
63
- @namespace = namespace
64
- @methods = {}
65
- end
66
-
67
- def create_method(meth, &block)
68
- fail AlreadyExistsError, meth if @methods.key?(meth)
69
- @methods[meth] = block
70
- end
71
-
72
- def method_missing(*args)
73
- meth, raw_value = *args
74
- fail NoMethodError, meth unless @methods.key?(meth)
75
-
76
- callback = @methods[meth]
77
- env_name = format("%s_%s", @namespace, _sanitize(meth))
78
-
79
- if args.size == 2
80
- ENV[env_name] = Dumper.new.dump(raw_value, &callback)
81
- else
82
- Loader.new(meth).load(ENV[env_name], &callback)
83
- end
84
- end
85
-
86
- private
87
-
88
- def _sanitize(meth)
89
- meth[/^([^=?]*)[=?]?$/, 1].upcase
90
- end
91
- end
92
- end
93
- end
@@ -1,148 +0,0 @@
1
- require "guard/internals/plugins"
2
- require "guard/internals/groups"
3
-
4
- require "guard/options"
5
-
6
- module Guard
7
- # @private api
8
- module Internals
9
- # TODO: split into a commandline class and session (plugins, groups)
10
- # TODO: swap session and metadata
11
- # This class contains variables set during
12
- # evaluation of the guardfile (and are reset
13
- # before reevaluation)
14
- class Session
15
- attr_reader :options
16
- attr_reader :plugins
17
- attr_reader :groups
18
-
19
- DEFAULT_OPTIONS = {
20
- clear: false,
21
- debug: false,
22
- no_bundler_warning: false,
23
-
24
- # User defined scopes
25
- group: [],
26
- plugin: [],
27
-
28
- # Notifier
29
- notify: true,
30
-
31
- # Interactor
32
- no_interactions: false,
33
-
34
- # Guardfile options:
35
- # guardfile_contents
36
- guardfile: nil,
37
-
38
- # Listener options
39
- # TODO: rename to watchdirs?
40
- watchdir: Dir.pwd,
41
- latency: nil,
42
- force_polling: false,
43
- wait_for_delay: nil,
44
- listen_on: nil
45
- }
46
-
47
- def cmdline_groups
48
- @cmdline_groups.dup.freeze
49
- end
50
-
51
- def cmdline_plugins
52
- @cmdline_plugins.dup.freeze
53
- end
54
-
55
- def initialize(new_options)
56
- @options = Options.new(new_options, DEFAULT_OPTIONS)
57
-
58
- @plugins = Internals::Plugins.new
59
- @groups = Internals::Groups.new
60
-
61
- @cmdline_groups = @options[:group]
62
- @cmdline_plugins = @options[:plugin]
63
-
64
- @clear = @options[:clear]
65
- @debug = @options[:debug]
66
- @watchdirs = Array(@options[:watchdir])
67
- @notify = @options[:notify]
68
- @interactor_name = @options[:no_interactions] ? :sleep : :pry_wrapper
69
-
70
- @guardfile_plugin_scope = []
71
- @guardfile_group_scope = []
72
- end
73
-
74
- def guardfile_scope(scope)
75
- opts = scope.dup
76
- @guardfile_plugin_scope = Array(opts.delete(:plugins))
77
- @guardfile_group_scope = Array(opts.delete(:groups))
78
- fail "Unknown options: #{opts.inspect}" unless opts.empty?
79
- end
80
-
81
- attr_reader :guardfile_group_scope
82
- attr_reader :guardfile_plugin_scope
83
-
84
- def guardfile_ignore
85
- fail NotImplementedError
86
- end
87
-
88
- def guardfile_ignore_bang
89
- fail NotImplementedError
90
- end
91
-
92
- def clearing(on)
93
- @clear = on
94
- end
95
-
96
- def clearing?
97
- @clear
98
- end
99
-
100
- alias :clear? :clearing?
101
-
102
- def debug?
103
- @debug
104
- end
105
-
106
- def watchdirs
107
- @watchdirs_from_guardfile ||= nil
108
- @watchdirs_from_guardfile || @watchdirs
109
- end
110
-
111
- # set by Dsl with :directories() command
112
- def watchdirs=(dirs)
113
- dirs = [Dir.pwd] if dirs.empty?
114
- @watchdirs_from_guardfile = dirs.map { |dir| File.expand_path dir }
115
- end
116
-
117
- def listener_args
118
- if options[:listen_on]
119
- [:on, options[:listen_on]]
120
- else
121
- listener_options = {}
122
- [:latency, :force_polling, :wait_for_delay].each do |option|
123
- listener_options[option] = options[option] if options[option]
124
- end
125
- expanded_watchdirs = watchdirs.map { |dir| File.expand_path dir }
126
- [:to, *expanded_watchdirs, listener_options]
127
- end
128
- end
129
-
130
- def evaluator_options
131
- opts = { guardfile: options[:guardfile] }
132
- # TODO: deprecate :guardfile_contents
133
- if options[:guardfile_contents]
134
- opts[:contents] = options[:guardfile_contents]
135
- end
136
- opts
137
- end
138
-
139
- def notify_options
140
- { notify: @options[:notify] }
141
- end
142
-
143
- def interactor_name
144
- @interactor_name
145
- end
146
- end
147
- end
148
- end
@@ -1,182 +0,0 @@
1
- require "guard/ui"
2
-
3
- module Guard
4
- # This class contains useful methods to:
5
- #
6
- # * Fetch all the Guard plugins names;
7
- # * Initialize a plugin, get its location;
8
- # * Return its class name;
9
- # * Add its template to the Guardfile.
10
- #
11
- class PluginUtil
12
- ERROR_NO_GUARD_OR_CLASS = "Could not load 'guard/%s' or'\
13
- ' find class Guard::%s"
14
-
15
- INFO_ADDED_GUARD_TO_GUARDFILE = "%s guard added to Guardfile,"\
16
- " feel free to edit it"
17
-
18
- attr_accessor :name
19
-
20
- # Returns a list of Guard plugin Gem names installed locally.
21
- #
22
- # @return [Array<String>] a list of Guard plugin gem names
23
- #
24
- def self.plugin_names
25
- valid = Gem::Specification.find_all.select do |gem|
26
- _gem_valid?(gem)
27
- end
28
-
29
- valid.map { |x| x.name.sub(/^guard-/, "") }.uniq
30
- end
31
-
32
- # Initializes a new `Guard::PluginUtil` object.
33
- #
34
- # @param [String] name the name of the Guard plugin
35
- #
36
- def initialize(name)
37
- @name = name.to_s.sub(/^guard-/, "")
38
- end
39
-
40
- # Initializes a new `Guard::Plugin` with the given `options` hash. This
41
- # methods handles plugins that inherit from the deprecated `Guard::Guard`
42
- # class as well as plugins that inherit from `Guard::Plugin`.
43
- #
44
- # @see Guard::Plugin
45
- # @see https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0 How to
46
- # upgrade for Guard 2.0
47
- #
48
- # @return [Guard::Plugin] the initialized plugin
49
- # @return [Guard::Guard] the initialized plugin. This return type is
50
- # deprecated and the plugin's maintainer should update it to be
51
- # compatible with Guard 2.0. For more information on how to upgrade for
52
- # Guard 2.0, please head over to:
53
- # https://github.com/guard/guard/wiki/Upgrading-to-Guard-2.0
54
- #
55
- def initialize_plugin(options)
56
- klass = plugin_class
57
- fail "Could not load class: #{_constant_name.inspect}" unless klass
58
- if klass.superclass.to_s == "Guard::Guard"
59
- klass.new(options.delete(:watchers), options)
60
- else
61
- begin
62
- klass.new(options)
63
- rescue ArgumentError => e
64
- fail "Failed to call #{klass}.new(options): #{e}"
65
- end
66
- end
67
- end
68
-
69
- # Locates a path to a Guard plugin gem.
70
- #
71
- # @return [String] the full path to the plugin gem
72
- #
73
- def plugin_location
74
- @plugin_location ||= _full_gem_path("guard-#{name}")
75
- rescue Gem::LoadError
76
- ::Guard::UI.error "Could not find 'guard-#{ name }' gem path."
77
- end
78
-
79
- # Tries to load the Guard plugin main class. This transforms the supplied
80
- # plugin name into a class name:
81
- #
82
- # * `guardname` will become `Guard::Guardname`
83
- # * `dashed-guard-name` will become `Guard::DashedGuardName`
84
- # * `underscore_guard_name` will become `Guard::UnderscoreGuardName`
85
- #
86
- # When no class is found with the strict case sensitive rules, another
87
- # try is made to locate the class without matching case:
88
- #
89
- # * `rspec` will find a class `Guard::RSpec`
90
- #
91
- # @option options [Boolean] fail_gracefully whether error messages should
92
- # not be printed
93
- #
94
- # @return [Class, nil] the loaded class
95
- #
96
- def plugin_class(options = {})
97
- options = { fail_gracefully: false }.merge(options)
98
-
99
- const = _plugin_constant
100
- fail TypeError, "no constant: #{_constant_name}" unless const
101
- @plugin_class ||= Guard.const_get(const)
102
-
103
- rescue TypeError
104
- begin
105
- require "guard/#{ name.downcase }"
106
- const = _plugin_constant
107
- @plugin_class ||= Guard.const_get(const)
108
-
109
- rescue TypeError => error
110
- UI.error "Could not find class Guard::#{ _constant_name }"
111
- UI.error error.backtrace.join("\n")
112
- rescue LoadError => error
113
- unless options[:fail_gracefully]
114
- UI.error ERROR_NO_GUARD_OR_CLASS % [name.downcase, _constant_name]
115
- UI.error "Error is: #{error}"
116
- UI.error error.backtrace.join("\n")
117
- end
118
- end
119
- end
120
-
121
- # Adds a plugin's template to the Guardfile.
122
- #
123
- def add_to_guardfile
124
- klass = plugin_class # call here to avoid failing later
125
-
126
- require "guard/guardfile/evaluator"
127
- # TODO: move this to Generator?
128
- options = Guard.state.session.evaluator_options
129
- evaluator = Guardfile::Evaluator.new(options)
130
- evaluator.evaluate
131
- if evaluator.guardfile_include?(name)
132
- UI.info "Guardfile already includes #{ name } guard"
133
- else
134
- content = File.read("Guardfile")
135
- File.open("Guardfile", "wb") do |f|
136
- f.puts(content)
137
- f.puts("")
138
- f.puts(klass.template(plugin_location))
139
- end
140
-
141
- UI.info INFO_ADDED_GUARD_TO_GUARDFILE % name
142
- end
143
- end
144
-
145
- private
146
-
147
- # Returns the constant for the current plugin.
148
- #
149
- # @example Returns the constant for a plugin
150
- # > Guard::PluginUtil.new('rspec').send(:_plugin_constant)
151
- # => Guard::RSpec
152
- #
153
- def _plugin_constant
154
- @_plugin_constant ||= Guard.constants.detect do |c|
155
- c.to_s.downcase == _constant_name.downcase
156
- end
157
- end
158
-
159
- # Guesses the most probable name for the current plugin based on its name.
160
- #
161
- # @example Returns the most probable name for a plugin
162
- # > Guard::PluginUtil.new('rspec').send(:_constant_name)
163
- # => "Rspec"
164
- #
165
- def _constant_name
166
- @_constant_name ||= name.gsub(/\/(.?)/) { "::#{ $1.upcase }" }.
167
- gsub(/(?:^|[_-])(.)/) { $1.upcase }
168
- end
169
-
170
- def self._gem_valid?(gem)
171
- return false if gem.name == 'guard-compat'
172
- return true if gem.name =~ /^guard-/
173
- full_path = gem.full_gem_path
174
- file = File.join(full_path, "lib", "guard", "#{gem.name}.rb")
175
- File.exist?(file)
176
- end
177
-
178
- def _full_gem_path(name)
179
- Gem::Specification.find_by_name(name).full_gem_path
180
- end
181
- end
182
- end
@@ -1,61 +0,0 @@
1
- require "guard/plugin"
2
- require "guard/guardfile/evaluator"
3
- require "guard/runner"
4
- require "guard/internals/helpers"
5
-
6
- module Guard
7
- class Reevaluator < Plugin
8
- include Internals::Helpers
9
-
10
- def run_on_modifications(files)
11
- # TODO: this is messed up, because reevaluator adds itself
12
- # anyway, so it know what the path is
13
- evaluator = _evaluator
14
- path = evaluator.path
15
- return unless files.any? { |file| path == Pathname(file) }
16
- reevaluate
17
- rescue Dsl::Error, Guardfile::Evaluator::Error => e
18
- UI.warning("Failed to reevaluate file: #{e}")
19
- _add_self_to_plugins
20
- throw :task_has_failed
21
- end
22
-
23
- def reevaluate
24
- evaluator = _evaluator
25
- return if evaluator.inline?
26
-
27
- Runner.new.run(:stop)
28
-
29
- Guard.state.reset_session
30
-
31
- Notifier.disconnect
32
- evaluator.evaluate
33
- Notifier.connect(Guard.state.session.notify_options)
34
-
35
- if Guard.send(:_pluginless_guardfile?)
36
- Notifier.notify(
37
- "No plugins found in Guardfile, please add at least one.",
38
- title: "Guard re-evaluate",
39
- image: :failed)
40
- else
41
- msg = "Guardfile has been re-evaluated."
42
- UI.info(msg)
43
- Notifier.notify(msg, title: "Guard re-evaluate")
44
- Runner.new.run(:start)
45
- end
46
- end
47
-
48
- private
49
-
50
- def _evaluator
51
- Guardfile::Evaluator.new(Guard.state.session.evaluator_options)
52
- end
53
-
54
- def _add_self_to_plugins
55
- # TODO: do this on reload as well
56
- pattern = _relative_pathname(_evaluator.path).to_s
57
- options = { watchers: [Watcher.new(pattern)], group: :common }
58
- Guard.state.session.plugins.add(:reevaluator, options)
59
- end
60
- end
61
- end