rake-commander 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +8 -0
- data/.rubocop.yml +12 -8
- data/CHANGELOG.md +69 -4
- data/LICENSE +21 -0
- data/README.md +94 -2
- 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 -98
- 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 +49 -54
- data/lib/rake-commander/version.rb +1 -1
- data/lib/rake-commander.rb +4 -0
- data/rake-commander.gemspec +4 -1
- metadata +74 -6
- data/examples/basic.rb +0 -30
- data/lib/rake-commander/options/error_rely.rb +0 -58
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ce1bfcde79ef608b7e13c440c626ee3ace47ec5adf3088e6fc969bf85502cc59
|
4
|
+
data.tar.gz: f785888cff61578247dfb1fdfed6c4e44fd076180d8be0dd1e00bf14ac0f1700
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5d998c21f52d117ff59e5eb066a43cd0c5a0939a4187af2c5ee1dc3cbaead328b65d71ad67e333adf426ab465926fd56fc5830e4e7a3a7b048602f02dea39344
|
7
|
+
data.tar.gz: 2afaaa3bb046e6de18b13fe4b0e762dead4ace9a14b3d097c2b6c37142e7e0e0d111f5eecd9846647e50a64f13cbf8491b291d7572fafaada91cdc408400d064
|
data/.gitignore
CHANGED
data/.rubocop.yml
CHANGED
@@ -22,14 +22,16 @@ Metrics/ModuleLength:
|
|
22
22
|
Metrics/AbcSize:
|
23
23
|
Max: 50
|
24
24
|
Metrics/CyclomaticComplexity:
|
25
|
-
Max:
|
25
|
+
Max: 10
|
26
26
|
Metrics/PerceivedComplexity:
|
27
|
-
Max:
|
27
|
+
Max: 10
|
28
28
|
|
29
29
|
ParameterLists:
|
30
30
|
Max: 5
|
31
31
|
CountKeywordArgs: false
|
32
32
|
|
33
|
+
Style/Alias:
|
34
|
+
EnforcedStyle: prefer_alias_method
|
33
35
|
Style/StringLiterals:
|
34
36
|
Enabled: false
|
35
37
|
Style/FrozenStringLiteralComment:
|
@@ -51,12 +53,8 @@ Style/ClassAndModuleChildren:
|
|
51
53
|
Style/OptionalBooleanParameter:
|
52
54
|
Enabled: false
|
53
55
|
|
54
|
-
Layout/
|
55
|
-
|
56
|
-
Layout/SpaceInsideBlockBraces:
|
57
|
-
Enabled: false
|
58
|
-
Layout/SpaceAroundOperators:
|
59
|
-
Enabled: false
|
56
|
+
Layout/HashAlignment:
|
57
|
+
EnforcedColonStyle: table
|
60
58
|
Layout/ExtraSpacing:
|
61
59
|
AllowForAlignment: true
|
62
60
|
Layout/AccessModifierIndentation:
|
@@ -65,6 +63,12 @@ Layout/DotPosition:
|
|
65
63
|
EnforcedStyle: trailing
|
66
64
|
Layout/MultilineMethodCallIndentation:
|
67
65
|
EnforcedStyle: indented
|
66
|
+
Layout/SpaceInsideHashLiteralBraces:
|
67
|
+
Enabled: false
|
68
|
+
Layout/SpaceInsideBlockBraces:
|
69
|
+
Enabled: false
|
70
|
+
Layout/SpaceAroundOperators:
|
71
|
+
Enabled: false
|
68
72
|
Layout/FirstHashElementIndentation:
|
69
73
|
Enabled: false
|
70
74
|
Layout/EmptyLineAfterGuardClause:
|
data/CHANGELOG.md
CHANGED
@@ -2,16 +2,81 @@
|
|
2
2
|
All notable changes to this project will be documented in this file.
|
3
3
|
|
4
4
|
## TO DO
|
5
|
-
-
|
6
|
-
|
7
|
-
-
|
5
|
+
- Option results
|
6
|
+
- Include the symbol name keys (configurable). Note that dash will be replaced by underscore.
|
7
|
+
- Type Coertions
|
8
|
+
- Add a way to define/redefine a set and use them.
|
9
|
+
- Add more supported type_coertions as native to the gem (i.e. `Symbol`)
|
10
|
+
- Add support [for `ActiveRecord::Enum`](https://apidock.com/rails/ActiveRecord/Enum)
|
11
|
+
- Option definitions
|
12
|
+
- Order: `where: [:tail, :top]` and `[after, before]: :option_name`
|
13
|
+
- Configuration: allow to define option override behaviour and whether it should trigger an exception
|
14
|
+
- Error handlers
|
15
|
+
- See if it would be possible to parse all the valid options so we get all the valid results before some error is raised. Although this can be achieved with `OptionParser#order!`, it destroys switches; which would require to give it two parsing shots whenever there is an error.
|
16
|
+
- It should be ensured that the parsed options results object is remains the same.
|
17
|
+
- Think about options that modify other options. Technically this should be hold only at behaviour level
|
18
|
+
- This would allow to make the order of the options irrelevant when it comes to modify error handling behaviour via options themselves.
|
19
|
+
- Rake task parameters (see: https://stackoverflow.com/a/825832/4352306 & https://stackoverflow.com/a/825832/4352306)
|
20
|
+
- Add `enhance` functionality (when a task is invoked it runs before it; declared with `task` as well)
|
21
|
+
- Add `no_short` option (which should give the result of that option with the option name key)
|
22
|
+
- Add `on_option` handler at instance level, so within a `task` definition, we can decide certain things, such as if the functionality should be active when the `self.class` does not have that option.
|
23
|
+
* This is specially useful to be able to extend through inheritance chain, where we extend `task` (rather than redefining it), but we don't want options we removed (with `option_remove`) to throw unexpected results.
|
24
|
+
* Example: `on_option(:t, defined: true) {|option| do-stuff}` <- block to be called only if the option is defined in the class (alternative: `defined: :only`)
|
25
|
+
* Example: `on_option(:t, defined: false) {|option| do-stuff}` <- block to be called regardless the option exists (alternative: `defined: :ignore`)
|
26
|
+
* Example: `on_options(:t, :s, present: true) {|options| do-stuff}` <- block to be called only when the option `:t` and `:s` are both present in the parsed `options` result.
|
27
|
+
- Once this has been done, think about it being a hash-alike object with methods for the option names (i.e. `options.debug?`)
|
8
28
|
|
9
|
-
##
|
29
|
+
## DISCARDED IMPROVENTS
|
30
|
+
- Option to globally enable/disable the 2nd patch?
|
31
|
+
* That would make this gem completely useless.
|
32
|
+
|
33
|
+
## [0.2.1] - 2023-04-xx
|
10
34
|
|
11
35
|
### Added
|
12
36
|
### Fixed
|
13
37
|
### Changed
|
14
38
|
|
39
|
+
|
40
|
+
## [0.2.0] - 2023-04-28
|
41
|
+
|
42
|
+
### Added
|
43
|
+
- Better support for `RakeCommander::Options::Set`
|
44
|
+
- `RakeCommander::Options::options_use` accepts it as a parameter.
|
45
|
+
- Added `override` parameter to specify if this should override clashed option names.
|
46
|
+
- `RakeCommander::Options::class_resolver` to define the `RakeCommander::Option` class.
|
47
|
+
- Serves the purpose to ease class extension through inheritance.
|
48
|
+
- Ability to reopen options without changing the order.
|
49
|
+
- `RakeCommander::Options::option_reopen` which upserts (adds if not existing).
|
50
|
+
- New parameter `reopen` to `RakeCommander::Options::option` (redirects to the above method).
|
51
|
+
- Automatic option shortcuts (`implicit_shorts`) show in help and only when applicable.
|
52
|
+
- These are added automatically by `OptionParser`
|
53
|
+
- `OptionParser` leftovers trigger an error by default.
|
54
|
+
- This behaviour can be disabled or modified via callback/block by using `RakeCommander::Options:Error::error_on_leftovers`.
|
55
|
+
- Description auto **multi-line**
|
56
|
+
- Currently based on `RakeCommander::Options::Description::DESC_MAX_LENGTH`
|
57
|
+
- `RakeCommander::Options#remove_option`
|
58
|
+
- `RakeCommander::Options::Error::Base` and children can be raised using different methods (see `RakeCommander::Options::Error` for examples).
|
59
|
+
- The **task** `name` that raised the error is included in the message.
|
60
|
+
- `RakeCommander::Options::Error::Handling` which provides **configurability** around actions on specific option errors with a default to a general options parsing error.
|
61
|
+
|
62
|
+
### Fixed
|
63
|
+
- `RakeCommander::Base::ClassAutoLoader`
|
64
|
+
- Register excluded child classes (singleton classes) into their own property,
|
65
|
+
rather than in the `autoloaded_children` (they are not autoloaded).
|
66
|
+
- Missing `rake` dependency in gemspec file.
|
67
|
+
- Boolean switch detection (pre-parse arguments) and parsing
|
68
|
+
- It adds support for boolean option names such as `--[no-]verbose`
|
69
|
+
- Error messaging. There were missing cases, specially with implicit short options.
|
70
|
+
- `RakeCommander::Options`
|
71
|
+
- `#option_reopen` fixed
|
72
|
+
- **Inheritance fixed**
|
73
|
+
|
74
|
+
### Changed
|
75
|
+
- Development: examples invokation via `Rake`
|
76
|
+
- Refactored `RakeCommander::Options` to acquire functionality through extension.
|
77
|
+
- `attr_inheritable` and `inheritable_class_var` are the new names of previous methods
|
78
|
+
- Behaviour has been changed, so you define if it should `dup` the variables, and you can pass a `block` to do the `dup` yourself. They won **NOT** `freeze` anymore, as we are mostly working at class level.
|
79
|
+
|
15
80
|
## [0.1.4] - 2023-04-20
|
16
81
|
|
17
82
|
### Fixed
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2023 Oscar Segura
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
# RakeCommander
|
2
2
|
|
3
|
-
|
3
|
+
Classing rake tasks with options. Creating re-usable tasks, options and samples thereof.
|
4
|
+
|
5
|
+
## Introduction
|
6
|
+
|
7
|
+
Rake commander is a way to declare **rake tasks** with re-usable classes. It enhances the command line syntax, as tasks can come with their own **options**, inherit them, re-use declared options sets, modify/re-open or even remove them.
|
8
|
+
|
9
|
+
Although the `OptionParser` ruby native class is used for parsing the options, the declaration of options, additionally to the ones of `OptionParser` comes with some **opinionated improvements** and amendments:
|
10
|
+
|
11
|
+
1. It is possible to declare options as `required`
|
12
|
+
* This is additional to required option arguments.
|
13
|
+
* Options are inheritable (they get a custom `deep_dup`)
|
14
|
+
2. An option can have a `default` value.
|
15
|
+
* Which can optionally be automatically used when the option accepts or requires an argument.
|
16
|
+
3. Options parsing raises specific option errors. For a given task/class, each error type can have its own handler or preferred action.
|
17
|
+
* Defined error handling is inheritable and can be redefined.
|
4
18
|
|
5
19
|
## Installation
|
6
20
|
|
@@ -20,9 +34,87 @@ Or install it yourself as:
|
|
20
34
|
|
21
35
|
## Usage
|
22
36
|
|
37
|
+
See [**the `examples`**](https://github.com/rellampec/rake-commander/tree/main/examples).
|
38
|
+
|
39
|
+
```
|
40
|
+
rake -T examples
|
41
|
+
```
|
42
|
+
|
43
|
+
Go through the [basic example](https://github.com/rellampec/rake-commander/blob/main/examples/01_basic_example.rb).
|
44
|
+
|
45
|
+
```
|
46
|
+
rake examples:basic -- -h
|
47
|
+
rake examples:basic -- -z -e prod
|
48
|
+
```
|
49
|
+
* The double dash `--` is used to tell to rake-commander where the options section starts.
|
50
|
+
|
51
|
+
At the same time the double dash delimiter seems to make rake ignore anything that comes afterwards. Without loading rake commander, you could try:
|
52
|
+
|
53
|
+
```
|
54
|
+
$ rake --trace rspec
|
55
|
+
** Invoke spec (first_time)
|
56
|
+
** Execute spec
|
57
|
+
rspec logging and results
|
58
|
+
```
|
59
|
+
|
60
|
+
And then re-try with
|
61
|
+
|
62
|
+
```
|
63
|
+
$ rake rspec -- --trace
|
64
|
+
rspec logging and results
|
65
|
+
```
|
66
|
+
|
67
|
+
* The `--trace` option is being natively ignored by `rake` due to the preceding double dash (` -- `).
|
68
|
+
|
69
|
+
|
70
|
+
### Syntax
|
71
|
+
|
72
|
+
### Declaring and using Task Options
|
73
|
+
|
74
|
+
It supports most of options syntax of the native `OptionParser` but for a couple of exceptions perhaps:
|
75
|
+
1. It does **NOT** support definitions or parsing of shortcuts with **embedded argument** (i.e. `-nNAME`).
|
76
|
+
2. It does **NOT** support definitions that include equal sign (i.e. `name=NAME`, `n=NAME`)
|
77
|
+
|
78
|
+
An argument should be explicitly declared in the `name` part:
|
79
|
+
|
80
|
+
```
|
81
|
+
option :n, '--name NAME'
|
82
|
+
```
|
83
|
+
|
84
|
+
### Command Line
|
85
|
+
|
86
|
+
Although it is planned to extend the syntax, the current version shares the options through all tasks (declared as `RakeCommander` classes) that are invoked in the same command line.
|
87
|
+
|
88
|
+
```
|
89
|
+
rake [rake-options] task1 task2 -- [shared-task-options]
|
90
|
+
```
|
91
|
+
|
92
|
+
The double dash ` -- ` delimiter allows to modify the `ARGV` parsing behaviour of `rake`, giving room for **opinionated enhanced syntax**. Anything that comes before the double dash is feed to standard `rake`, and anything after `--` are parsed as option tasks via `rake commander`.
|
93
|
+
|
94
|
+
```
|
95
|
+
<rake part> -- [tasks options part]
|
96
|
+
```
|
97
|
+
|
98
|
+
## `rake` full support
|
99
|
+
|
100
|
+
Work has been done with the aim of providing a full patch on `rake`, provided that the main invocation command remains as `rake`.
|
101
|
+
|
102
|
+
To preserve `rake` as invocation command, though, the patch needs to relaunch the rake application when it has already started. The reason is that `rake` has already pre-parsed `ARGV` when `rake-commander` is loaded (i.e. from a `Rakefile`) and has identified as tasks things that are part of the task options.
|
103
|
+
|
104
|
+
* For compatibility with tasks declared using `RakeCommander`, the rake application is always relaunched. Anything that does not belong to task options should not be feed to rake tasks declared with rake commander classes.
|
105
|
+
|
106
|
+
### Patching `Rake`
|
107
|
+
|
108
|
+
The two patches:
|
109
|
+
|
110
|
+
1. Rake commander does come with a neat patch to the [`Rake::Application#run` method](https://github.com/ruby/rake/blob/48e798484babf725b0562cc417986da513e5d0ae/lib/rake/application.rb#L79) to clean up the `ARGV` before the rake application starts. But it kicks in too late...
|
111
|
+
2. For this reason a more arguable patch has been applied to [`Rake::Application#top_level` method](https://github.com/ruby/rake/blob/48e798484babf725b0562cc417986da513e5d0ae/lib/rake/application.rb#L131), where the rake application is relaunched.
|
112
|
+
|
113
|
+
For further details please see [`RakeCommander::Patcher`](https://github.com/rellampec/rake-commander/blob/main/lib/rake-commander/patcher).
|
114
|
+
|
23
115
|
|
24
116
|
## Development
|
25
117
|
|
26
118
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
27
119
|
|
28
|
-
For more info on available `Rake` tasks: `rake -T`
|
120
|
+
For more info on available `Rake` tasks: `rake -T` (or `bin/raked -T`)
|
data/Rakefile
CHANGED
@@ -1,32 +1,30 @@
|
|
1
|
-
require
|
2
|
-
require
|
3
|
-
require
|
4
|
-
require
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
require 'rspec/core/rake_task'
|
3
|
+
require 'yard'
|
4
|
+
require 'redcarpet'
|
5
5
|
|
6
|
-
|
6
|
+
# Install examples and load `rake-commander`
|
7
|
+
Rake.add_rakelib 'examples'
|
8
|
+
|
9
|
+
desc 'run the specs'
|
7
10
|
RSpec::Core::RakeTask.new(:spec)
|
8
11
|
|
9
|
-
desc
|
12
|
+
desc 'run rspec showing backtrace'
|
10
13
|
RSpec::Core::RakeTask.new(:spec_trace) do |task|
|
11
14
|
task.rspec_opts = ['--backtrace']
|
12
15
|
end
|
13
16
|
|
14
|
-
desc
|
17
|
+
desc 'run rspec stopping on first fail, and show backtrace'
|
15
18
|
RSpec::Core::RakeTask.new(:spec_fast) do |task|
|
16
19
|
task.rspec_opts = ['--fail-fast', '--backtrace']
|
17
20
|
end
|
18
21
|
|
19
22
|
# default task name is yard
|
20
|
-
desc
|
23
|
+
desc 'Yard: generate all the documentation'
|
21
24
|
YARD::Rake::YardocTask.new(:doc) do |t|
|
22
25
|
#t.files = ['lib/**/*.rb']
|
23
26
|
end
|
24
27
|
|
25
|
-
desc "Examples: Run examples (rake examples[basic] -- -h)"
|
26
|
-
task :examples, [:sample] do |_t, args|
|
27
|
-
require_relative "examples/#{args[:sample]}"
|
28
|
-
end
|
29
|
-
|
30
28
|
task default: [:spec]
|
31
29
|
task rspec_trace: :spec_trace
|
32
30
|
task rspec_fast: :spec_fast
|
@@ -0,0 +1,28 @@
|
|
1
|
+
class RakeCommander::Custom::BasicExample < RakeCommander
|
2
|
+
namespace :examples
|
3
|
+
|
4
|
+
desc 'A simple example to get started'
|
5
|
+
task :basic
|
6
|
+
|
7
|
+
#banner "Usage: basic:example -- [options]"
|
8
|
+
option '-w', :show_time, TrueClass, desc: 'Displays the local time'
|
9
|
+
option :z, '--timezone', TrueClass, default: false, required: true
|
10
|
+
option :o, '--hello NAME', String, desc: 'It greets.'
|
11
|
+
option '-s', '--say [SOMETHING]', "It says 'something'", default: %q(I don't know what to "say"...)
|
12
|
+
option :d, '--folder NAME', default: '.', desc: 'Source local folder', required: true
|
13
|
+
option '-e', :'--enviro ENV', 'The target environment to run this task', required: true
|
14
|
+
option :v, :debug, TrueClass, 'Shows the parsed options'
|
15
|
+
option :V, '[no-]verbose', 'Verbosity', TrueClass
|
16
|
+
#option :f, :folder, required: false, reopen: true
|
17
|
+
|
18
|
+
def task(*_args)
|
19
|
+
puts "Hello #{options[:o]}!!" if options[:o]
|
20
|
+
if options[:v]
|
21
|
+
puts 'We got these options:'
|
22
|
+
pp options
|
23
|
+
end
|
24
|
+
puts Time.now.strftime('%d %b at %H:%M') if options[:w]
|
25
|
+
puts Time.now.zone if options[:z]
|
26
|
+
puts options[:s] if options.key?(:s)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require_relative 'libs/shell_helpers'
|
2
|
+
require_relative '02_a_chainer_options_set'
|
3
|
+
|
4
|
+
class RakeCommander::Custom::Chainer < RakeCommander
|
5
|
+
include Examples::Libs::ShellHelpers
|
6
|
+
TARGET_TASK = 'examples:chained'.freeze
|
7
|
+
|
8
|
+
namespace :examples
|
9
|
+
|
10
|
+
task :chainer
|
11
|
+
desc "Uses rake (or raked) to invoke #{TARGET_TASK}"
|
12
|
+
|
13
|
+
# When an option as a default value defined, it is added to `options` result
|
14
|
+
# even when the option was not invoked
|
15
|
+
options_with_defaults true
|
16
|
+
|
17
|
+
# Loads the otions from a pre-defined options set
|
18
|
+
options_use RakeCommander::Custom::ChainerOptionsSet
|
19
|
+
# Redefines the description of the option `:chain`
|
20
|
+
option_reopen :chain, desc: "Calls: '< rake|raked > #{TARGET_TASK} task'"
|
21
|
+
# Adds some option of its own
|
22
|
+
str_desc = "The method used to shell the call to examples:chained."
|
23
|
+
str_desc << " Options: #{SHELL_METHODS.join(', ')}"
|
24
|
+
option '-m', 'method [METHOD]', default: 'system', desc: str_desc
|
25
|
+
|
26
|
+
def task(*_args)
|
27
|
+
if options[:c]
|
28
|
+
cmd = "#{subcommand_base} -- #{subcommand_arguments.join(' ')}"
|
29
|
+
puts "Calling --> '#{cmd}'"
|
30
|
+
shell(cmd, method: options[:m])
|
31
|
+
else
|
32
|
+
puts "Nothing to do :|"
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def subcommand_base
|
37
|
+
with = options[:w] == 'raked' ? 'bin\raked' : 'rake'
|
38
|
+
"#{with} #{self.class::TARGET_TASK}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def subcommand_arguments
|
42
|
+
[].tap do |args|
|
43
|
+
if options.key?(:s)
|
44
|
+
str_opt = "--say"
|
45
|
+
str_opt << " \"#{options[:s]}\"" if options[:s]
|
46
|
+
args << str_opt
|
47
|
+
end
|
48
|
+
args << "--debug" if options[:b]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def puts(str)
|
55
|
+
return super unless options[:b]
|
56
|
+
super "#{app_id} #{str} #{thread_id}"
|
57
|
+
end
|
58
|
+
|
59
|
+
def app_id
|
60
|
+
"(#{self.class.task_fullname}: #{Rake.application.object_id})"
|
61
|
+
end
|
62
|
+
|
63
|
+
def thread_id
|
64
|
+
"(PID: #{Process.pid} ++ Thread: #{Thread.current.object_id})"
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,8 @@
|
|
1
|
+
class RakeCommander::Custom::ChainerOptionsSet < RakeCommander::Options::Set
|
2
|
+
name :chainer_options
|
3
|
+
|
4
|
+
option :c, :chain, TrueClass, desc: "Calls: '< rake|raked > chained-task task'"
|
5
|
+
option :w, '--with CALLER', default: 'rake', desc: "Specifies if should invoke with 'rake' or 'raked'"
|
6
|
+
option '-s', "It makes the chained-task say 'something'", name: '--say [SOMETHING]'
|
7
|
+
option '-b', '--debug', TrueClass, 'Whether to add additional context information to messages'
|
8
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class RakeCommander::Custom::Chained < RakeCommander::Custom::Chainer
|
2
|
+
#namespace :examples # <-- inherited
|
3
|
+
desc 'A task you want to chain to'
|
4
|
+
task :chained
|
5
|
+
|
6
|
+
option_reopen :s, "It says 'something'", default: %q(I don't know what to "say"...)
|
7
|
+
option_remove :c, :w, :method
|
8
|
+
|
9
|
+
def task(*_args)
|
10
|
+
puts "Called !!"
|
11
|
+
puts options[:s] if options[:s]
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class RakeCommander::Custom::ChainerPlus < RakeCommander::Custom::Chainer
|
2
|
+
TARGET_TASK = 'examples:chained_plus'.freeze
|
3
|
+
|
4
|
+
desc "Uses rake (or raked) to invoke #{TARGET_TASK}"
|
5
|
+
task :chainer_plus
|
6
|
+
|
7
|
+
# Disable using defaults when options are not invoked.
|
8
|
+
options_with_defaults false
|
9
|
+
|
10
|
+
# Update option description
|
11
|
+
option_reopen :chain, desc: "Calls: '< rake|raked > #{TARGET_TASK} task'"
|
12
|
+
# Extend with new options
|
13
|
+
option :e, '--exit-on-error', TrueClass, \
|
14
|
+
desc: "Whether #{TARGET_TASK} should just exit on 'missing argument' error (or raise an exception)"
|
15
|
+
option :o, '--hello NAME', String, desc: 'It greets.'
|
16
|
+
|
17
|
+
# Make it default to `exit 1` when there are errors
|
18
|
+
error_on_options false
|
19
|
+
# Let it trigger/raise the error when an unknown option is used!
|
20
|
+
error_on_options true, error: RakeCommander::Options::Error::InvalidArgument
|
21
|
+
|
22
|
+
def task(*_args)
|
23
|
+
puts "Hello #{options[:o]}!!" if options[:o]
|
24
|
+
options[:m] = :system unless options[:m]
|
25
|
+
super
|
26
|
+
end
|
27
|
+
|
28
|
+
# We add the extended arguments at the beginning
|
29
|
+
def subcommand_arguments
|
30
|
+
[].tap do |args|
|
31
|
+
args << '--exit-on-error' if options[:e]
|
32
|
+
end.concat(super)
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'pp'
|
2
|
+
class RakeCommander::Custom::ChainedPlus < RakeCommander::Custom::Chained
|
3
|
+
desc 'A task+ you want to chain to'
|
4
|
+
task :chained_plus
|
5
|
+
|
6
|
+
option_remove :say
|
7
|
+
option :e, '--exit-on-error', TrueClass, desc: 'If it should just exit on "missing argument" error or raise an exception'
|
8
|
+
# Move option to the end, make **required** the argument (SOMETHING) as well as the option itself.
|
9
|
+
option :s, '--say SOMETHING', "It says 'something'", required: true
|
10
|
+
|
11
|
+
error_on_options error: RakeCommander::Options::Error::MissingArgument do |err, _argv, results, _leftovers|
|
12
|
+
msg = "Parsed results when 'missing argument' error was raised"
|
13
|
+
msg << "\non option '#{err.option.name_full}'" if err.option
|
14
|
+
puts "#{msg} => #{results.pretty_inspect}"
|
15
|
+
!results[:e]
|
16
|
+
end
|
17
|
+
end
|
data/examples/README.md
ADDED
@@ -0,0 +1,79 @@
|
|
1
|
+
## Examples
|
2
|
+
|
3
|
+
* `RakeCommander` is loaded from the repo branch you are checked out.
|
4
|
+
|
5
|
+
The Rakefile `Examples.rake` has three lines that can serve as a guide. One were we require `rake-commander`, another where we define our `RakeCommander` classes, and one where we load them as actual `Rake` tasks.
|
6
|
+
|
7
|
+
```ruby
|
8
|
+
require_relative '../lib/rake-commander'
|
9
|
+
RakeCommander::Patcher.debug = ENV['COMMANDER_DEBUG'] == "true"
|
10
|
+
Dir["#{__dir__}/*_example.rb"].sort.each {|file| require_relative file }
|
11
|
+
RakeCommander.self_load
|
12
|
+
```
|
13
|
+
|
14
|
+
* To see the patches in action, you can add `COMMANDER_DEBUG=true` to a `.env` file
|
15
|
+
|
16
|
+
```
|
17
|
+
rake -T examples
|
18
|
+
```
|
19
|
+
|
20
|
+
### Basic Example
|
21
|
+
|
22
|
+
```
|
23
|
+
rake examples:basic -- -h
|
24
|
+
rake examples:basic -- -z -e prod
|
25
|
+
```
|
26
|
+
|
27
|
+
### Chainer && Chained Example
|
28
|
+
|
29
|
+
Two tasks where chainer calls chained through **a `shell` call to `rake`**.
|
30
|
+
|
31
|
+
* Read well the example before running it.
|
32
|
+
|
33
|
+
```
|
34
|
+
rake examples:chainer -- -h
|
35
|
+
rake examples:chained -- -h
|
36
|
+
```
|
37
|
+
|
38
|
+
### Chainer Plus and Chained Plus Example
|
39
|
+
|
40
|
+
Same as the previous example but these tasks inherit from the previous example, extending their behaviour and changing the options.
|
41
|
+
|
42
|
+
|
43
|
+
```
|
44
|
+
rake examples:chainer_plus -- -h
|
45
|
+
rake examples:chained_plus -- -h
|
46
|
+
```
|
47
|
+
|
48
|
+
#### Error handling mixed with options
|
49
|
+
|
50
|
+
The option `--exit-on-error` allows the error handler defined in `chained_plus` to decide if it should raise the error or just do an `exit 1`
|
51
|
+
|
52
|
+
* This is possible because the order that the options have been declared. Observe that they `--say` option has been removed and redefined **after** the option `--exit-on-error` has been defined.
|
53
|
+
* `OptionParser` **switches are processed in order** and, therefore, the error on `--say` only pops up after the `--exit on-error` option has been already parsed.
|
54
|
+
|
55
|
+
While this will raise the error (with a trace):
|
56
|
+
|
57
|
+
```
|
58
|
+
$ rake examples:chainer_plus -- --chain --say
|
59
|
+
Calling --> 'rake examples:chained_plus -- --say'
|
60
|
+
Parsed results when 'missing argument' error was raised
|
61
|
+
on option '--say SOMETHING' => {}
|
62
|
+
rake aborted!
|
63
|
+
RakeCommander::Options::Error::MissingArgument: (examples:chained_plus) missing required argument in option: --say SOMETHING (-s)
|
64
|
+
< here back trace>
|
65
|
+
Tasks: TOP => examples:chained_plus
|
66
|
+
(See full trace by running task with --trace)
|
67
|
+
* Failed to running 'rake examples:chained_plus -- --say'
|
68
|
+
```
|
69
|
+
|
70
|
+
This will only print the error with an `exit 1`:
|
71
|
+
|
72
|
+
```
|
73
|
+
$ rake examples:chainer_plus -- --chain --say --exit-on-error
|
74
|
+
Calling --> 'rake examples:chained_plus -- --exit-on-error --say'
|
75
|
+
Parsed results when 'missing argument' error was raised
|
76
|
+
on option '--say SOMETHING' => {:e=>true}
|
77
|
+
(examples:chained_plus) missing required argument in option: --say SOMETHING (-s)
|
78
|
+
* Failed to running 'rake examples:chained_plus -- --exit-on-error --say'
|
79
|
+
```
|