rake-commander 0.1.2 → 0.2.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/.gitignore +8 -0
- data/.rubocop.yml +14 -8
- data/CHANGELOG.md +84 -4
- data/Gemfile +1 -1
- data/LICENSE +21 -0
- data/README.md +95 -3
- data/Rakefile +11 -13
- data/examples/01_basic_example.rb +28 -0
- data/examples/02_a_chainer_example.rb +66 -0
- data/examples/02_a_chainer_options_set.rb +8 -0
- data/examples/02_b_chained_example.rb +13 -0
- data/examples/03_a_chainer_plus_example.rb +34 -0
- data/examples/03_b_chained_plus_example.rb +17 -0
- data/examples/Examples.rake +7 -0
- data/examples/README.md +79 -0
- data/examples/libs/shell_helpers.rb +81 -0
- data/lib/rake-commander/base/class_auto_loader.rb +45 -7
- data/lib/rake-commander/base/class_helpers.rb +16 -61
- data/lib/rake-commander/base/class_inheritable.rb +122 -0
- data/lib/rake-commander/base/custom_error.rb +52 -0
- data/lib/rake-commander/base/object_helpers.rb +42 -0
- data/lib/rake-commander/base.rb +16 -2
- data/lib/rake-commander/option.rb +115 -25
- data/lib/rake-commander/options/arguments.rb +206 -94
- data/lib/rake-commander/options/description.rb +17 -0
- data/lib/rake-commander/options/error/base.rb +86 -0
- data/lib/rake-commander/options/error/handling.rb +106 -0
- data/lib/rake-commander/options/error/invalid_argument.rb +21 -0
- data/lib/rake-commander/options/error/invalid_option.rb +9 -0
- data/lib/rake-commander/options/error/missing_argument.rb +10 -0
- data/lib/rake-commander/options/error/missing_option.rb +48 -0
- data/lib/rake-commander/options/error/unknown_argument.rb +32 -0
- data/lib/rake-commander/options/error.rb +75 -10
- data/lib/rake-commander/options/name.rb +67 -23
- data/lib/rake-commander/options/result.rb +107 -0
- data/lib/rake-commander/options/set.rb +7 -1
- data/lib/rake-commander/options.rb +175 -102
- data/lib/rake-commander/patcher/README.md +79 -0
- data/lib/rake-commander/patcher/application/run_method.rb +46 -0
- data/lib/rake-commander/patcher/application/top_level_method.rb +74 -0
- data/lib/rake-commander/patcher/application.rb +16 -0
- data/lib/rake-commander/patcher/base.rb +45 -0
- data/lib/rake-commander/patcher/debug.rb +32 -0
- data/lib/rake-commander/patcher/helpers.rb +44 -0
- data/lib/rake-commander/patcher.rb +26 -0
- data/lib/rake-commander/rake_context/wrapper.rb +2 -0
- data/lib/rake-commander/rake_task.rb +50 -50
- data/lib/rake-commander/version.rb +1 -1
- data/lib/rake-commander.rb +4 -0
- data/rake-commander.gemspec +5 -2
- metadata +75 -7
- data/examples/basic.rb +0 -30
- data/lib/rake-commander/options/error_rely.rb +0 -58
@@ -0,0 +1,81 @@
|
|
1
|
+
module Examples
|
2
|
+
module Libs
|
3
|
+
module ShellHelpers
|
4
|
+
SHELL_METHODS = %I[system back_quotes x spawn exec fork_exec pipe].freeze
|
5
|
+
|
6
|
+
# https://stackoverflow.com/a/37329716/4352306
|
7
|
+
def shell(cmd, method: :system)
|
8
|
+
method = method.to_sym
|
9
|
+
case method
|
10
|
+
when :system
|
11
|
+
success = system(cmd)
|
12
|
+
puts "* #{success ? "Succeded in" : "Failed to"} running '#{cmd}'"
|
13
|
+
when :back_quotes, :x
|
14
|
+
result = `#{cmd}`
|
15
|
+
puts result
|
16
|
+
#%x(#{cmd})
|
17
|
+
when :spawn # like Kernel.system but with no wait
|
18
|
+
pid = Process.spawn(cmd)
|
19
|
+
puts "* new child process (pid: #{pid}). Will wait..."
|
20
|
+
Process.wait(pid)
|
21
|
+
puts "* child process finished (pid: #{pid})"
|
22
|
+
when :exec
|
23
|
+
exec cmd
|
24
|
+
# Flow does not reach here
|
25
|
+
when :fork_exec
|
26
|
+
for_exec(cmd)
|
27
|
+
when :pipe # I/O of new process
|
28
|
+
pipe(cmd)
|
29
|
+
else
|
30
|
+
raise "* unknown shell method '#{method}'"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def fork_exec(cmd)
|
35
|
+
pid = fork do
|
36
|
+
shell(cmd, method: :exec)
|
37
|
+
end
|
38
|
+
puts "* new child process (pid: #{pid})"
|
39
|
+
rescue NotImplementedError => e
|
40
|
+
puts e
|
41
|
+
puts "Redirecting to 'spawn'"
|
42
|
+
shell(cmd, method: :spawn)
|
43
|
+
end
|
44
|
+
|
45
|
+
def pipe(cmd)
|
46
|
+
IO.popen(host_shell_command, 'r+') do |pipe|
|
47
|
+
puts "* new child process (pid: #{pipe.pid})"
|
48
|
+
prompt = pipe_prompt(pipe)
|
49
|
+
pipe.puts cmd
|
50
|
+
pipe.close_write # prevent `gets` to get stuck
|
51
|
+
lines = pipe.readlines
|
52
|
+
if index = lines.index {|ln| ln.include?(cmd)}
|
53
|
+
lines = lines[index+1..]
|
54
|
+
end
|
55
|
+
lines.reject! {|ln| ln.start_with?(prompt)}
|
56
|
+
lines = lines.map {|ln| ">> (pid: #{pipe.pid}) #{ln}"}
|
57
|
+
puts lines
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
# Changes the commandline prompt, so we can discard those.
|
62
|
+
def pipe_prompt(pipe, prompt: ':>$ ')
|
63
|
+
if Gem::Platform.local.os == "mingw32"
|
64
|
+
pipe.puts "function prompt {\"#{prompt}\"}"
|
65
|
+
else
|
66
|
+
pipe.puts "PS1=\"#{prompt}\""
|
67
|
+
end
|
68
|
+
prompt
|
69
|
+
end
|
70
|
+
|
71
|
+
# Command to open a new shell for `pipe`
|
72
|
+
def host_shell_command
|
73
|
+
if Gem::Platform.local.os == "mingw32"
|
74
|
+
"powershell -noprofile -noninteractive"
|
75
|
+
else
|
76
|
+
'sh'
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -25,17 +25,25 @@ class RakeCommander
|
|
25
25
|
end
|
26
26
|
|
27
27
|
# To restrict which namespaces it is allowed to load from
|
28
|
+
# @note this deletes from the `:ignore` namespaces
|
28
29
|
def autoload_namespace(*namespaces)
|
29
30
|
_autoload_namespace(:include, *namespaces)
|
30
31
|
end
|
31
32
|
|
32
33
|
# To ignore certain namespaces this class should not autoload from
|
34
|
+
# @note this deletes from the `:include` namespaces
|
33
35
|
def autoload_namespace_ignore(*namespaces)
|
34
36
|
_autoload_namespace(:ignore, *namespaces)
|
35
37
|
end
|
36
38
|
|
39
|
+
# Applies a change to the `autoloaded_namespaces`
|
37
40
|
def _autoload_namespace(type, *namespaces)
|
38
|
-
autoloaded_namespaces(type).
|
41
|
+
autoloaded_namespaces(type).tap do |target|
|
42
|
+
next if namespaces.empty?
|
43
|
+
other_type = type == :include ? :ignore : :include
|
44
|
+
namespaces.each {|nm_sp| autoloaded_namespace(other_type).delete(nm_sp)}
|
45
|
+
target.concat(namespaces)
|
46
|
+
end
|
39
47
|
end
|
40
48
|
|
41
49
|
# @param constant [Class, String] a class or namespace we want to check auto-load entitlement thereof.
|
@@ -61,14 +69,36 @@ class RakeCommander
|
|
61
69
|
@autoloaded_children ||= []
|
62
70
|
end
|
63
71
|
|
72
|
+
# Keep track on actual children that have been ignored by `autoload_namespace_ignore`.
|
73
|
+
def ignored_children
|
74
|
+
@ignored_children ||= []
|
75
|
+
end
|
76
|
+
|
77
|
+
# Allows to reload
|
78
|
+
# @note it may be handy some times.
|
79
|
+
def clear_autoloaded_children
|
80
|
+
forget_class!(*autoloaded_children, *ignored_children)
|
81
|
+
@ignored_children = []
|
82
|
+
@autoloaded_children = []
|
83
|
+
end
|
84
|
+
|
85
|
+
# Prevents already excluded children to enter into the loop again.
|
86
|
+
def excluded_children
|
87
|
+
@excluded_children ||= []
|
88
|
+
end
|
89
|
+
|
64
90
|
# Children classes of `autoloader_class` that have not been created an instance of.
|
65
91
|
def unloaded_children
|
66
92
|
return [] unless autoloaded_class
|
67
93
|
new_detected = new_classes
|
68
94
|
known_class!(*new_detected)
|
69
95
|
descendants(parent_class: autoloaded_class, scope: new_detected).select do |child_class|
|
70
|
-
!autoloaded_children.include?(child_class) &&
|
71
|
-
|
96
|
+
!autoloaded_children.include?(child_class) && \
|
97
|
+
!excluded_children.include?(child_class) && \
|
98
|
+
autoload_class?(child_class).tap do |ignored|
|
99
|
+
ignored_children.push(child_class) if ignored
|
100
|
+
end
|
101
|
+
end
|
72
102
|
end
|
73
103
|
|
74
104
|
# It loads/creates a new instance of children classes pending to be loaded.
|
@@ -79,14 +109,15 @@ class RakeCommander
|
|
79
109
|
return false if pending_children.empty?
|
80
110
|
@loading_children = true
|
81
111
|
pending_children.each do |klass|
|
82
|
-
|
112
|
+
exclude = false
|
113
|
+
child = object ? klass.new(object) : klass.new
|
83
114
|
yield(child) if block_given?
|
84
|
-
|
85
115
|
rescue TypeError
|
86
116
|
# Can't create from this class (must be the singleton class)
|
87
|
-
|
117
|
+
exclude = true
|
118
|
+
excluded_children.push(klass)
|
88
119
|
ensure
|
89
|
-
autoloaded_children.push(klass)
|
120
|
+
autoloaded_children.push(klass) unless exclude
|
90
121
|
end
|
91
122
|
@loading_children = false
|
92
123
|
true
|
@@ -101,6 +132,13 @@ class RakeCommander
|
|
101
132
|
# Add to known namespaces
|
102
133
|
def known_class!(*classes)
|
103
134
|
known_classes.concat(classes)
|
135
|
+
self
|
136
|
+
end
|
137
|
+
|
138
|
+
# Forget namespaces
|
139
|
+
def forget_class!(*classes)
|
140
|
+
@known_classes = known_classes - classes
|
141
|
+
self
|
104
142
|
end
|
105
143
|
|
106
144
|
# List all new namespaces
|
@@ -1,7 +1,7 @@
|
|
1
1
|
class RakeCommander
|
2
2
|
module Base
|
3
3
|
module ClassHelpers
|
4
|
-
NOT_USED =
|
4
|
+
NOT_USED = :not_used!
|
5
5
|
|
6
6
|
# Helper to determine if a paramter has been used
|
7
7
|
# @note to effectivelly use this helper, you should initialize your target
|
@@ -65,15 +65,6 @@ class RakeCommander
|
|
65
65
|
end.join("")
|
66
66
|
end
|
67
67
|
|
68
|
-
# Helper to create an instance variable `name`
|
69
|
-
# @param [String, Symbol] the name of the variable
|
70
|
-
# @reutrn [String] the name of the created instance variable
|
71
|
-
def instance_variable_name(name)
|
72
|
-
str = name.to_s
|
73
|
-
str = "@#{str}" unless str.start_with?("@")
|
74
|
-
str
|
75
|
-
end
|
76
|
-
|
77
68
|
# If the class for `name` exists, it returns it. Otherwise it generates it.
|
78
69
|
# @param name [String, Symbol] the name of the new class
|
79
70
|
# @param inherits [Class] the parent class to _inherit_ from
|
@@ -95,6 +86,16 @@ class RakeCommander
|
|
95
86
|
end
|
96
87
|
end
|
97
88
|
|
89
|
+
# @param klasses [Arrary<Class>] the classes to sort.
|
90
|
+
# @return [Arrary<Class>] the classes in hierarchy order.
|
91
|
+
def sort_classes(*klasses)
|
92
|
+
klasses.sort do |k_1, k_2|
|
93
|
+
next -1 if k_2 < k_1
|
94
|
+
next 1 if k_1 < k_2
|
95
|
+
0
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
98
99
|
# Finds all child classes of the current class.
|
99
100
|
# @param parent_class [Class] the parent class we want to find children of.
|
100
101
|
# @param direct [Boolean] it will only include direct child classes.
|
@@ -103,18 +104,11 @@ class RakeCommander
|
|
103
104
|
def descendants(parent_class: self, direct: false, scope: nil)
|
104
105
|
scope ||= ObjectSpace.each_object(::Class)
|
105
106
|
return [] if scope.empty?
|
106
|
-
scope.select
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
0
|
112
|
-
end.tap do |siblings|
|
113
|
-
if direct
|
114
|
-
siblings.reject! do |si|
|
115
|
-
siblings.any? {|s| si < s}
|
116
|
-
end
|
117
|
-
end
|
107
|
+
siblings = scope.select {|klass| klass < parent_class}
|
108
|
+
siblings = sort_classes(*siblings)
|
109
|
+
return siblings unless direct
|
110
|
+
siblings.reject! do |si|
|
111
|
+
siblings.any? {|s| si < s}
|
118
112
|
end
|
119
113
|
end
|
120
114
|
|
@@ -124,45 +118,6 @@ class RakeCommander
|
|
124
118
|
def descendants?(parent_class: self, direct: false)
|
125
119
|
!descendants(parent_class: parent_class, direct: direct).empty?
|
126
120
|
end
|
127
|
-
|
128
|
-
# Keeps track on class instance variables that should be inherited by child classes.
|
129
|
-
# @note
|
130
|
-
# - subclasses will inherit the value as is at that moment
|
131
|
-
# - any change afterwards will be only on the specific class (in line with class instance variables)
|
132
|
-
# - adapted from https://stackoverflow.com/a/10729812/4352306
|
133
|
-
# TODO: this separates the logic of the method to the instance var. Think if would be possible to join them somehow.
|
134
|
-
def inheritable_class_vars(*vars)
|
135
|
-
@inheritable_class_vars ||= [:inheritable_class_vars]
|
136
|
-
@inheritable_class_vars += vars
|
137
|
-
end
|
138
|
-
|
139
|
-
# Builds the attr_reader and attr_writer of `attrs` and registers the associated instance variable as inheritable.
|
140
|
-
def inheritable_attrs(*attrs, add_accessors: false)
|
141
|
-
if add_accessors
|
142
|
-
attrs.each do |attr|
|
143
|
-
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
144
|
-
class << self; attr_accessor :#{attr} end
|
145
|
-
RUBY
|
146
|
-
end
|
147
|
-
end
|
148
|
-
inheritable_class_vars(*attrs)
|
149
|
-
end
|
150
|
-
|
151
|
-
# This callback method is called whenever a subclass of the current class is created.
|
152
|
-
# @note
|
153
|
-
# - values of the instance variables are copied as they are (no dups or clones)
|
154
|
-
# - the above means: avoid methods that change the state of the mutable object on it
|
155
|
-
# - mutating methods would reflect the changes on other classes as well
|
156
|
-
# - therefore, `freeze` will be called on the values that are inherited.
|
157
|
-
def inherited(subclass)
|
158
|
-
super.tap do
|
159
|
-
inheritable_class_vars.each do |var|
|
160
|
-
instance_var = instance_variable_name(var)
|
161
|
-
value = instance_variable_get(instance_var)
|
162
|
-
subclass.instance_variable_set(instance_var, value.freeze)
|
163
|
-
end
|
164
|
-
end
|
165
|
-
end
|
166
121
|
end
|
167
122
|
end
|
168
123
|
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
class RakeCommander
|
2
|
+
module Base
|
3
|
+
module ClassInheritable
|
4
|
+
include RakeCommander::Base::ObjectHelpers
|
5
|
+
|
6
|
+
# Builds the attr_reader and attr_writer of `attrs` and registers the associated
|
7
|
+
# instance variable as inheritable.
|
8
|
+
# @yield [value]
|
9
|
+
# @yieldparam value [Variant] the value of the parent class
|
10
|
+
# @yieldreturn the value that will be inherited by the child class
|
11
|
+
# @param attrs [Array <Symbol>] the variable names that should be inheritable.
|
12
|
+
# @param add_accessors [Boolean] whether attr_accessor should be invoked
|
13
|
+
# @param deep_dup [Boolean] whether the value of the instance var should be `deep_dup`ed.
|
14
|
+
def attr_inheritable(*attrs, add_accessors: false, deep_dup: true, &block)
|
15
|
+
attrs = attrs.map(&:to_sym)
|
16
|
+
inheritable_class_var(*attrs, deep_dup: deep_dup, &block)
|
17
|
+
return unless add_accessors
|
18
|
+
attrs.each do |attr|
|
19
|
+
class_eval <<-RUBY, __FILE__, __LINE__ + 1
|
20
|
+
class << self; attr_accessor :#{attr} end
|
21
|
+
RUBY
|
22
|
+
end
|
23
|
+
self
|
24
|
+
end
|
25
|
+
|
26
|
+
# @return [Boolean] whether an `var` has been declared as inheritable
|
27
|
+
def inheritable_class_var?(var)
|
28
|
+
inheritable_class_var.any? do |_method, definitions|
|
29
|
+
definitions.key?(var.to_sym)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Removes from the inheritance some class variables.
|
34
|
+
# @param attrs [Array <Symbol>] the instance variable names of the class
|
35
|
+
# that should NOT be inheritable.
|
36
|
+
def attr_not_inheritable(*attrs)
|
37
|
+
attrs.each do |attr|
|
38
|
+
next unless method = inheritable_class_var_method(attr)
|
39
|
+
inheritable_class_var[method].delete(attr)
|
40
|
+
end
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# This callback method is called whenever a subclass of the current class is created.
|
47
|
+
def inherited(subclass)
|
48
|
+
super.tap do
|
49
|
+
inheritable_class_var.each do |method, definitions|
|
50
|
+
definitions.each do |var, action|
|
51
|
+
instance_var = instance_variable_name(var)
|
52
|
+
value = instance_variable_get(instance_var)
|
53
|
+
child_value = inherited_class_value(value, method, action)
|
54
|
+
subclass.instance_variable_set(instance_var, child_value)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
# @return [Variant] the value that the child class will inherit
|
61
|
+
def inherited_class_value(value, method, action)
|
62
|
+
case method
|
63
|
+
when :mirror
|
64
|
+
value
|
65
|
+
when :deep_dup
|
66
|
+
case action
|
67
|
+
when Proc
|
68
|
+
action.call(value)
|
69
|
+
when :default
|
70
|
+
custom_deep_dup(value)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
# Keeps track on class instance variables that should be inherited by child classes.
|
76
|
+
# @note
|
77
|
+
# - adapted from https://stackoverflow.com/a/10729812/4352306
|
78
|
+
# - subclasses will inherit the value depending on `depep_dup` and `block` if enabled or given (respectivelly)
|
79
|
+
# - any change afterwards will be only on the specific class (in line with class instance variables)
|
80
|
+
# @param see `#attr_inheritable`
|
81
|
+
# @return [Hash] methods and variables to be inherited.
|
82
|
+
def inheritable_class_var(*vars, deep_dup: true, &block)
|
83
|
+
@inheritable_class_var ||= {
|
84
|
+
mirror: {},
|
85
|
+
deep_dup: {}
|
86
|
+
}.tap do |hash|
|
87
|
+
hash[:deep_dup][:inheritable_class_var] = :default
|
88
|
+
end
|
89
|
+
@inheritable_class_var.tap do |_methods|
|
90
|
+
vars.each {|var| inheritable_class_var_add(var, deep_dup: deep_dup, &block)}
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
# Adds var to the `inheritable_class_var`
|
95
|
+
# @param var [Symbol] the name of an instance variable of this class that should be inherited.
|
96
|
+
def inheritable_class_var_add(var, deep_dup: true, &block)
|
97
|
+
# Remove previous definition if present
|
98
|
+
attr_not_inheritable(var)
|
99
|
+
method = deep_dup || block ? :deep_dup : :mirror
|
100
|
+
inheritable_class_var[method][var] = block || :default
|
101
|
+
self
|
102
|
+
end
|
103
|
+
|
104
|
+
# @return [Symbol, NilClass]
|
105
|
+
def inheritable_class_var_method(var)
|
106
|
+
inheritable_class_var.each do |method, definitions|
|
107
|
+
return method if definitions.key?(var.to_sym)
|
108
|
+
end
|
109
|
+
nil
|
110
|
+
end
|
111
|
+
|
112
|
+
# Helper to create an instance variable `name`
|
113
|
+
# @param [String, Symbol] the name of the variable
|
114
|
+
# @return [String] the name of the created instance variable
|
115
|
+
def instance_variable_name(name)
|
116
|
+
str = name.to_s
|
117
|
+
str = "@#{str}" unless str.start_with?("@")
|
118
|
+
str
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
class RakeCommander
|
2
|
+
module Base
|
3
|
+
# This class allows to use both method calls to `raise` by using additional parameters.
|
4
|
+
# @note Although not clearly explained, this is somehow captured here https://stackoverflow.com/a/32481520/4352306
|
5
|
+
class CustomError < StandardError
|
6
|
+
def initialize(value = nil)
|
7
|
+
super(@message = to_message(value)) if @value = value
|
8
|
+
end
|
9
|
+
|
10
|
+
# If @value was already set, ignore the latest message and
|
11
|
+
# just return @message
|
12
|
+
def to_s
|
13
|
+
return @message if @message
|
14
|
+
unclassed(super)
|
15
|
+
end
|
16
|
+
|
17
|
+
# If @value was already set, ignore the latest message
|
18
|
+
# just return @message
|
19
|
+
def message
|
20
|
+
return @message if @message
|
21
|
+
to_message(unclassed(super))
|
22
|
+
end
|
23
|
+
|
24
|
+
protected
|
25
|
+
|
26
|
+
# Any **children classes** that want to extend how `value` is transformed
|
27
|
+
# into a `message` **should extend this method**.
|
28
|
+
# @return [String] `message`
|
29
|
+
def to_message(value)
|
30
|
+
case value
|
31
|
+
when StandardError
|
32
|
+
to_message(value.message)
|
33
|
+
when String
|
34
|
+
value
|
35
|
+
when NilClass
|
36
|
+
value
|
37
|
+
else
|
38
|
+
raise ArgumentError, "Expecting String, StandardError or NilClass. Given: #{value.class}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
# When `value` is `nil` **methods** `to_s` and `message` return the error class of `self`.
|
45
|
+
# This helper allows to remove that part to know if the error was raised with `nil`
|
46
|
+
# @return [String]
|
47
|
+
def unclassed(str)
|
48
|
+
str.to_s.gsub(self.class.to_s, '').strip
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
class RakeCommander
|
2
|
+
module Base
|
3
|
+
module ObjectHelpers
|
4
|
+
private
|
5
|
+
|
6
|
+
# Custom Object#deep_dup for rake commander
|
7
|
+
def custom_deep_dup(value, dup_objects: true, &dup_block)
|
8
|
+
case value
|
9
|
+
when Hash
|
10
|
+
custom_hash_deep_dup(value, dup_objects: dup_objects, &dup_block)
|
11
|
+
when Array
|
12
|
+
value.map {|v| custom_deep_dup(v, dup_objects: dup_objects, &dup_block)}
|
13
|
+
else
|
14
|
+
custom_object_deep_dup(value, dup_objects: true, &dup_block)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Does the copy of the final object
|
19
|
+
def custom_object_deep_dup(value, dup_objects: true)
|
20
|
+
return yield(value) if block_given?
|
21
|
+
return value unless dup_objects
|
22
|
+
return value.deep_dup if value.respond_to?(:deep_dup)
|
23
|
+
value.dup
|
24
|
+
end
|
25
|
+
|
26
|
+
# Custom Hash#deep_dup for rake commander
|
27
|
+
def custom_hash_deep_dup(original, dup_objects: true, &dup_block)
|
28
|
+
raise ArgumentError, "Expecting Hash. Given: #{original.class}" unless original.is_a?(Hash)
|
29
|
+
hash = original.dup
|
30
|
+
original.each_pair do |key, value|
|
31
|
+
unless key.frozen? && key.is_a?(::String)
|
32
|
+
hash.delete(key)
|
33
|
+
key = custom_deep_dup(key, dup_objects: dup_objects, &dup_block) if dup_objects
|
34
|
+
end
|
35
|
+
value = dup_objects ? custom_deep_dup(value, dup_objects: dup_objects, &dup_block) : value
|
36
|
+
hash[key] = value
|
37
|
+
end
|
38
|
+
hash
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/rake-commander/base.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
|
+
require_relative 'base/object_helpers'
|
1
2
|
require_relative 'base/class_helpers'
|
3
|
+
require_relative 'base/class_inheritable'
|
2
4
|
require_relative 'base/class_auto_loader'
|
5
|
+
require_relative 'base/custom_error'
|
3
6
|
require_relative 'rake_task'
|
4
7
|
require_relative 'options'
|
5
8
|
|
@@ -8,22 +11,33 @@ class RakeCommander
|
|
8
11
|
class << self
|
9
12
|
def included(base)
|
10
13
|
super(base)
|
11
|
-
base.extend RakeCommander::Base::ClassHelpers
|
12
14
|
base.extend RakeCommander::Base::ClassAutoLoader
|
13
15
|
base.autoloads_children_of RakeCommander
|
14
16
|
|
15
17
|
base.extend ClassMethods
|
16
18
|
base.send :include, RakeTask
|
17
|
-
|
18
19
|
base.send :include, Options
|
19
20
|
#autoload_namespace_ignore "RakeCommander::Samples"
|
20
21
|
end
|
21
22
|
end
|
22
23
|
|
23
24
|
module ClassMethods
|
25
|
+
# Loads children classes by keeping a cache.
|
24
26
|
def self_load
|
25
27
|
autoload_children
|
26
28
|
end
|
29
|
+
|
30
|
+
# Clears track on any auto-loaded children
|
31
|
+
# @note required for reload.
|
32
|
+
def self_load_reset
|
33
|
+
clear_autoloaded_children
|
34
|
+
end
|
35
|
+
|
36
|
+
# Clears the cache of autoloaded children classes and loads them again.
|
37
|
+
def self_reload
|
38
|
+
self_load_reset
|
39
|
+
autoload_children
|
40
|
+
end
|
27
41
|
end
|
28
42
|
end
|
29
43
|
end
|