avm-tools 0.75.0 → 0.78.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +4 -4
  2. data/lib/avm/eac_rails_base1/runner/bundle.rb +2 -2
  3. data/lib/avm/eac_rails_base1/runner/code_runner.rb +3 -3
  4. data/lib/avm/eac_webapp_base0/deploy/build.rb +1 -1
  5. data/lib/avm/eac_webapp_base0/runner/deploy.rb +1 -0
  6. data/lib/avm/files/formatter.rb +8 -4
  7. data/lib/avm/git/auto_commit_path.rb +2 -4
  8. data/lib/avm/git/auto_commit_path/ruby.rb +20 -0
  9. data/lib/avm/tools/runner/eac_redmine_base0/project_rename.rb +7 -16
  10. data/lib/avm/tools/runner/files/format.rb +3 -2
  11. data/lib/avm/tools/runner/git/auto_commit.rb +11 -0
  12. data/lib/avm/tools/runner/git/subrepo/clone.rb +84 -0
  13. data/lib/avm/tools/version.rb +1 -1
  14. data/template/avm/eac_redmine_base0/deploy/config/install.sh.template +12 -0
  15. data/vendor/eac_cli/eac_cli.gemspec +1 -1
  16. data/vendor/eac_cli/lib/eac_cli/definition.rb +49 -22
  17. data/vendor/eac_cli/lib/eac_cli/definition/alternative.rb +83 -0
  18. data/vendor/eac_cli/lib/eac_cli/definition/base_option.rb +17 -1
  19. data/vendor/eac_cli/lib/eac_cli/{parser/options_collection.rb → definition/help_formatter.rb} +20 -49
  20. data/vendor/eac_cli/lib/eac_cli/definition/positional_argument.rb +21 -4
  21. data/vendor/eac_cli/lib/eac_cli/docopt/doc_builder.rb +18 -40
  22. data/vendor/eac_cli/lib/eac_cli/docopt/doc_builder/alternative.rb +50 -0
  23. data/vendor/eac_cli/lib/eac_cli/docopt/runner_extension.rb +1 -0
  24. data/vendor/eac_cli/lib/eac_cli/parser.rb +21 -3
  25. data/vendor/eac_cli/lib/eac_cli/parser/alternative.rb +88 -0
  26. data/vendor/eac_cli/lib/eac_cli/parser/alternative/argv.rb +17 -0
  27. data/vendor/eac_cli/lib/eac_cli/parser/alternative/double_dash.rb +24 -0
  28. data/vendor/eac_cli/lib/eac_cli/parser/alternative/options.rb +58 -0
  29. data/vendor/eac_cli/lib/eac_cli/parser/alternative/positionals.rb +30 -0
  30. data/vendor/eac_cli/lib/eac_cli/parser/collector.rb +4 -0
  31. data/vendor/eac_cli/lib/eac_cli/patches/object/runner_with.rb +2 -1
  32. data/vendor/eac_cli/lib/eac_cli/runner.rb +6 -2
  33. data/vendor/eac_cli/lib/eac_cli/runner_with/help.rb +1 -1
  34. data/vendor/eac_cli/lib/eac_cli/runner_with/output_file.rb +5 -1
  35. data/vendor/eac_cli/lib/eac_cli/runner_with/subcommands.rb +96 -0
  36. data/vendor/eac_cli/lib/eac_cli/version.rb +1 -1
  37. data/vendor/eac_cli/spec/lib/eac_cli/definition/alternative_spec.rb +14 -0
  38. data/vendor/eac_cli/spec/lib/eac_cli/docopt/runner_extension_spec.rb +35 -0
  39. data/vendor/eac_cli/spec/lib/eac_cli/parser/alternative_spec.rb +140 -0
  40. data/vendor/eac_cli/spec/lib/eac_cli/runner_spec.rb +57 -40
  41. data/vendor/eac_cli/spec/lib/eac_cli/runner_with/output_file_spec.rb +53 -0
  42. data/vendor/eac_cli/spec/lib/eac_cli/runner_with/subcommands_spec.rb +57 -0
  43. data/vendor/eac_ruby_base0/lib/eac_ruby_base0/application.rb +32 -1
  44. data/vendor/eac_ruby_base0/lib/eac_ruby_base0/runner.rb +1 -1
  45. data/vendor/eac_ruby_base0/lib/eac_ruby_base0/version.rb +1 -1
  46. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/abstract_methods.rb +60 -0
  47. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/common_constructor.rb +53 -0
  48. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/configs.rb +7 -107
  49. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/configs/entry_reader.rb +81 -0
  50. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/configs/password_entry_reader.rb +18 -0
  51. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/configs/read_entry_options.rb +46 -0
  52. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/console/configs/store_passwords_entry_reader.rb +27 -0
  53. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/enumerator.rb +4 -0
  54. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/enumerator/current.rb +9 -0
  55. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/enumerator/stopped.rb +14 -0
  56. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/module/abstract_methods.rb +10 -0
  57. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/patches/object/debug.rb +17 -0
  58. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/version.rb +1 -1
  59. data/vendor/eac_ruby_utils/lib/eac_ruby_utils/yaml.rb +3 -2
  60. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/abstract_methods_spec.rb +28 -0
  61. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/common_constructor_spec.rb +66 -8
  62. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/enumerator/current_spec.rb +26 -0
  63. data/vendor/eac_ruby_utils/spec/lib/eac_ruby_utils/patches/enumerator/stopped_spec.rb +32 -0
  64. metadata +31 -6
  65. data/lib/avm/tools/runner/eac_rails_base0/bundle.rb +0 -14
  66. data/vendor/eac_cli/lib/eac_cli/parser/parse_result.rb +0 -21
  67. data/vendor/eac_cli/lib/eac_cli/parser/positional_collection.rb +0 -49
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: '061861b37a86551104e76e78c988fabd4e421dbdcaf223fd567e36aa725abf49'
4
- data.tar.gz: e5b1a4bcd4cc716e9dfad2527143163a8e97528cabe7fa44ac01ed12a4fdbe6d
3
+ metadata.gz: 31676da0253c7ec8dc92aee2619723858f021faedb659e4f6128a7552eaad975
4
+ data.tar.gz: b6c14df8700750c9e0a39c9b8de6ee78e5864bdbf8ff2c21c7c59f029257437f
5
5
  SHA512:
6
- metadata.gz: 83feb6ab0a6519f2319650eac3a15305fbc46d088a80d7521e14347fda3db9ea3503fe0c5a474d8899f9359f0807685ff7e4a33ccac0c610ac08406a33e137fa
7
- data.tar.gz: cb4f4ff1b6f0b7dad60530111f60a20acbef410a9edb2e6c865cfd0589808e5847bf21afc9e954f33092ab8faa1cefd084905fc1206d54c18d117c8bd5efbaec
6
+ metadata.gz: 989f01a3eb81d88b99186f3471f7437cdd00d7f6d182a68cb2f1080461f08cbadb84bb30782e8bab731eecd75782cc7728d175920cb28f8544e31f88e435ef02
7
+ data.tar.gz: 2b51fd22a6aec3d7955f75c3f4d1c68fc5a60c2c8c2dbc13e25cdaff6396df1ba655e1ef5183ab3081e18f17b642a5cf832f7583e80997c6bfb121c90fd0c0a4
@@ -8,7 +8,7 @@ require 'shellwords'
8
8
  module Avm
9
9
  module EacRailsBase1
10
10
  class Runner < ::Avm::EacWebappBase0::Runner
11
- class Bundle < ::EacRubyUtils::Console::DocoptRunner
11
+ class Bundle
12
12
  runner_with ::Avm::EacRailsBase1::RunnerWith::Bundle
13
13
  runner_definition do
14
14
  desc 'Runs "bundle ...".'
@@ -20,7 +20,7 @@ module Avm
20
20
  end
21
21
 
22
22
  def bundle_args
23
- options.fetch('<bundle-args>').reject { |arg| arg == '--' }
23
+ parsed.bundle_args.reject { |arg| arg == '--' }
24
24
  end
25
25
  end
26
26
  end
@@ -7,7 +7,7 @@ require 'eac_ruby_utils/console/docopt_runner'
7
7
  module Avm
8
8
  module EacRailsBase1
9
9
  class Runner < ::Avm::EacWebappBase0::Runner
10
- class CodeRunner < ::EacRubyUtils::Console::DocoptRunner
10
+ class CodeRunner
11
11
  runner_with ::Avm::EacRailsBase1::RunnerWith::Bundle
12
12
  runner_definition do
13
13
  desc 'Runs a Ruby code with "rails runner".'
@@ -15,12 +15,12 @@ module Avm
15
15
  end
16
16
 
17
17
  def run
18
- infov 'Environment', context(:instance).host_env
18
+ infov 'Environment', runner_context.call(:instance).host_env
19
19
  bundle_run
20
20
  end
21
21
 
22
22
  def bundle_args
23
- %w[exec rails runner] + [options.fetch('<code>')]
23
+ %w[exec rails runner] + [parsed.code]
24
24
  end
25
25
  end
26
26
  end
@@ -17,7 +17,7 @@ module Avm
17
17
  ::Avm::Files::Appender
18
18
  .new
19
19
  .variables_source_set(variables_source)
20
- .append_directory(template.path)
20
+ .append_templatized_directory(template.path)
21
21
  .append_templatized_directories(appended_directories)
22
22
  .append_file_content(version_target_path, version)
23
23
  .write_appended_on(build_dir)
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'avm/instances/runner'
3
4
  require 'avm/path_string'
4
5
  require 'eac_ruby_utils/console/docopt_runner'
5
6
  require 'eac_ruby_utils/console/speaker'
@@ -10,7 +10,11 @@ module Avm
10
10
  require_sub __FILE__
11
11
  enable_simple_cache
12
12
  enable_console_speaker
13
- common_constructor :source_paths, :options
13
+ enable_listable
14
+ lists.add_symbol :option, :apply, :recursive, :verbose
15
+ common_constructor :source_paths, :options, default: [{}] do
16
+ options.assert_valid_keys(self.class.lists.option.values)
17
+ end
14
18
 
15
19
  FORMATS = %w[ruby php html python xml json generic_plain].freeze
16
20
 
@@ -27,7 +31,7 @@ module Avm
27
31
  infom "Applying #{@formats_files.count} format(s)... "
28
32
  @formats_files.each do |format, files|
29
33
  infom "Applying format #{format.name} (Files matched: #{files.count})..."
30
- next unless options.fetch(:apply)
34
+ next unless options[OPTION_APPLY]
31
35
 
32
36
  @result += format.apply(files)
33
37
  end
@@ -35,7 +39,7 @@ module Avm
35
39
 
36
40
  def traverser_check_file(file)
37
41
  format = find_format(file)
38
- infov file, format ? format.class : '-' if options.fetch(:verbose)
42
+ infov file, format ? format.class : '-' if options[OPTION_VERBOSE]
39
43
  return unless format
40
44
 
41
45
  @formats_files[format] ||= []
@@ -79,7 +83,7 @@ module Avm
79
83
  end
80
84
 
81
85
  def traverser_recursive
82
- options.fetch(:recursive)
86
+ options[OPTION_RECURSIVE]
83
87
  end
84
88
  end
85
89
  end
@@ -5,6 +5,7 @@ require 'eac_ruby_utils/core_ext'
5
5
  module Avm
6
6
  module Git
7
7
  class AutoCommitPath
8
+ require_sub __FILE__, include_modules: true
8
9
  enable_console_speaker
9
10
  common_constructor :git, :path do
10
11
  self.path = path.to_pathname
@@ -31,10 +32,7 @@ module Avm
31
32
  end
32
33
 
33
34
  def class_name
34
- CLASS_NAME_PATTERNS.each do |pattern|
35
- pattern.if_match(relative_path.to_path, false) { |m| return m[1].camelize }
36
- end
37
- raise "No pattern matched \"#{relative_path}\""
35
+ ruby_class_name || relative_path.to_path
38
36
  end
39
37
 
40
38
  def commit_message
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_ruby_utils/core_ext'
4
+
5
+ module Avm
6
+ module Git
7
+ class AutoCommitPath
8
+ module Ruby
9
+ RUBY_CLASS_NAME_PATTERNS = [%r{lib/((?!.*/lib/).+)\.rb\z}, %r{app/[^/]+/(.+)\.rb\z}].freeze
10
+
11
+ def ruby_class_name
12
+ RUBY_CLASS_NAME_PATTERNS.each do |pattern|
13
+ pattern.if_match(relative_path.to_path, false) { |m| return m[1].camelize }
14
+ end
15
+ nil
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,23 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'eac_cli/core_ext'
3
4
  require 'avm/eac_rails_base1/runner/code_runner'
4
- require 'eac_cli/default_runner'
5
5
 
6
6
  module Avm
7
7
  module Tools
8
8
  class Runner < ::EacRubyUtils::Console::DocoptRunner
9
9
  class EacRedmineBase0 < ::Avm::EacRailsBase1::Runner
10
- class ProjectRename < ::Avm::EacRailsBase1::Runner::CodeRunner
11
- include ::EacCli::DefaultRunner
12
-
13
- runner_definition do
10
+ class ProjectRename
11
+ runner_with ::Avm::EacRailsBase1::RunnerWith::Bundle do
14
12
  pos_arg :from
15
13
  pos_arg :to
16
14
  end
17
15
 
18
16
  def run
19
- start_banner
20
- command.system!
17
+ bundle_run
21
18
  end
22
19
 
23
20
  def start_banner
@@ -25,16 +22,10 @@ module Avm
25
22
  infov 'To', to
26
23
  end
27
24
 
28
- def from
29
- options.fetch('<from>')
30
- end
31
-
32
- def to
33
- options.fetch('<to>')
34
- end
25
+ delegate :from, :to, to: :parsed
35
26
 
36
- def command
37
- context(:instance).bundle('exec', 'rails', 'runner', code)
27
+ def bundle_args
28
+ %w[exec rails runner] + [code]
38
29
  end
39
30
 
40
31
  def code
@@ -32,8 +32,9 @@ module Avm
32
32
  end
33
33
 
34
34
  def formatter_options
35
- { apply: options.fetch('--apply'), recursive: !options.fetch('--no-recursive'),
36
- verbose: options.fetch('--verbose') }
35
+ { ::Avm::Files::Formatter::OPTION_APPLY => options.fetch('--apply'),
36
+ ::Avm::Files::Formatter::OPTION_RECURSIVE => !options.fetch('--no-recursive'),
37
+ ::Avm::Files::Formatter::OPTION_VERBOSE => options.fetch('--verbose') }
37
38
  end
38
39
 
39
40
  def git
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'avm/git/auto_commit_path'
4
+ require 'avm/files/formatter'
4
5
  require 'eac_cli/default_runner'
5
6
 
6
7
  module Avm
@@ -13,12 +14,14 @@ module Avm
13
14
  runner_definition do
14
15
  desc 'Commit with message based in content commited.'
15
16
  bool_opt '-d', '--dirty', 'Select dirty files.'
17
+ bool_opt '-f', '--format', 'Format files before commit.'
16
18
  pos_arg 'paths', repeat: true, optional: true
17
19
  end
18
20
 
19
21
  def run
20
22
  clear_stage
21
23
  banner
24
+ format_files
22
25
  run_paths
23
26
  end
24
27
 
@@ -39,6 +42,14 @@ module Avm
39
42
  context(:git).dirty_files.map { |d| context(:git).root_path.join / d.path }
40
43
  end
41
44
 
45
+ def format_files
46
+ return unless options.fetch('--format')
47
+
48
+ infom 'Formating files...'
49
+ ::Avm::Files::Formatter.new(paths.map(&:path),
50
+ ::Avm::Files::Formatter::OPTION_APPLY => true).run
51
+ end
52
+
42
53
  def paths_uncached
43
54
  (options.fetch('<paths>')
44
55
  .map { |p| p.to_pathname.expand_path } + dirty_paths)
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'eac_cli/core_ext'
4
+ require 'eac_git/local'
5
+ require 'eac_ruby_utils/console/docopt_runner'
6
+
7
+ module Avm
8
+ module Tools
9
+ class Runner < ::EacRubyUtils::Console::DocoptRunner
10
+ class Git < ::EacRubyUtils::Console::DocoptRunner
11
+ class Subrepo < ::EacRubyUtils::Console::DocoptRunner
12
+ class Clone
13
+ runner_with :help do
14
+ desc 'Clone git-subrepo repositories.'
15
+ arg_opt '-b', '--branch', 'Branch.'
16
+ arg_opt '-d', '--parent-dir', 'Target path\'s parent directory.'
17
+ pos_arg :url
18
+ pos_arg :target_path, optional: true
19
+ end
20
+
21
+ def run
22
+ start_banner
23
+ clean
24
+ clone
25
+ end
26
+
27
+ private
28
+
29
+ def start_banner
30
+ infov 'URL', url
31
+ infov 'Subpath', target_path
32
+ infov 'Branch', branch
33
+ end
34
+
35
+ def clean
36
+ infom 'Cleaning...'
37
+ git.command('subrepo', 'clean', '--all', '--force').system!
38
+ end
39
+
40
+ def clone
41
+ infom 'Cloning...'
42
+ infov 'Clone arguments', clone_args
43
+ git.command(*clone_args).system!
44
+ end
45
+
46
+ delegate :branch, :url, to: :parsed
47
+
48
+ def git_uncached
49
+ ::EacGit::Local.new('.')
50
+ end
51
+
52
+ def clone_args
53
+ ['subrepo'] + branch.if_present([]) { |v| ['--branch', v] } +
54
+ if ::File.exist?(target_path)
55
+ ['init', target_path, '--remote', url]
56
+ else
57
+ ['clone', url, target_path, '--message', clone_message, '--force']
58
+ end
59
+ end
60
+
61
+ def clone_message
62
+ "Subrepo \"#{target_path}\" (#{url})."
63
+ end
64
+
65
+ def repos_name_from_url
66
+ %r{/([^/]+)\z}.if_match(url, false) { |m| m[1].gsub(/\.git\z/, '') }
67
+ end
68
+
69
+ def target_path
70
+ parsed.target_path || target_path_from_parent_dir ||
71
+ fatal_error('No target path specified')
72
+ end
73
+
74
+ def target_path_from_parent_dir
75
+ return nil unless parsed.parent_dir && repos_name_from_url
76
+
77
+ ::File.join(parsed.parent_dir, repos_name_from_url)
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Avm
4
4
  module Tools
5
- VERSION = '0.75.0'
5
+ VERSION = '0.78.0'
6
6
  end
7
7
  end
@@ -12,3 +12,15 @@ fi
12
12
  export address_host='%%WEB.AUTHORITY%%'
13
13
  export address_path='%%WEB.PATH%%'
14
14
  export git_repositories_hierarchical_organisation=false
15
+
16
+ # Mail settings
17
+ export smtp_server='%%MAILER.SMTP.ADDRESS%%'
18
+ export smtp_port='%%MAILER.SMTP.PORT%%'
19
+ export smtp_domain='%%MAILER.SMTP.DOMAIN%%'
20
+ export smtp_tls='%%MAILER_SMTP_TLS%%'
21
+ export smtp_enable_starttls_auto='%%MAILER_SMTP_STARTTLS_AUTO%%'
22
+ export smtp_openssl_verify_mode='%%MAILER_SMTP_OPENSSL_VERIFY_MODE%%'
23
+ export smtp_authentication='%%MAILER.SMTP.AUTHENTICATION%%'
24
+ export smtp_username='%%MAILER.SMTP.USERNAME%%'
25
+ export smtp_password='%%MAILER.SMTP.PASSWORD%%'
26
+ export mail_from='%%MAILER.FROM%%'
@@ -12,7 +12,7 @@ Gem::Specification.new do |s|
12
12
 
13
13
  s.files = Dir['{lib}/**/*', 'Gemfile']
14
14
 
15
- s.add_dependency 'eac_ruby_utils', '~> 0.45'
15
+ s.add_dependency 'eac_ruby_utils', '~> 0.50'
16
16
 
17
17
  s.add_development_dependency 'eac_ruby_gem_support', '~> 0.1', '>= 0.1.2'
18
18
  end
@@ -8,57 +8,66 @@ require 'eac_ruby_utils/core_ext'
8
8
  module EacCli
9
9
  class Definition
10
10
  require_sub __FILE__
11
+
12
+ MAIN_ALTERNATIVE_KEY = :main
13
+ SUBCOMMAND_NAME_ARG = 'subcommand'
14
+ SUBCOMMAND_ARGS_ARG = 'subcommand_args'
15
+
11
16
  attr_accessor :description
12
- attr_accessor :options_argument
13
17
 
14
18
  def initialize
15
19
  self.description = '-- NO DESCRIPTION SET --'
16
- self.options_argument = true
20
+ alternatives_set[MAIN_ALTERNATIVE_KEY] = main_alternative
17
21
  end
18
22
 
19
23
  def alt(&block)
20
- r = ::EacCli::Definition.new
24
+ r = ::EacCli::Definition::Alternative.new
21
25
  r.instance_eval(&block)
22
- alternatives << r
26
+ alternatives_set[new_alternative_key] = r
23
27
  r
24
28
  end
25
29
 
26
30
  def alternatives
27
- @alternatives ||= []
28
- end
29
-
30
- def arg_opt(short, long, description, option_options = {})
31
- options << ::EacCli::Definition::ArgumentOption.new(
32
- short, long, description, option_options
33
- )
31
+ alternatives_set.values
34
32
  end
35
33
 
36
- def bool_opt(short, long, description, option_options = {})
37
- options << ::EacCli::Definition::BooleanOption.new(short, long, description, option_options)
34
+ def alternative(key)
35
+ alternatives_set.fetch(key)
38
36
  end
39
37
 
40
38
  def desc(description)
41
39
  self.description = description
42
40
  end
43
41
 
42
+ def help_formatter
43
+ @help_formatter ||= ::EacCli::Definition::HelpFormatter.new(self)
44
+ end
45
+
46
+ def main_alternative
47
+ @main_alternative ||= begin
48
+ r = ::EacCli::Definition::Alternative.new
49
+ r.options_argument(true)
50
+ r
51
+ end
52
+ end
53
+
44
54
  def options_arg(options_argument)
45
55
  self.options_argument = options_argument
46
56
  end
47
57
 
48
- def options
49
- @options ||= []
58
+ def options_argument
59
+ main_alternative.options_argument?
50
60
  end
51
61
 
52
- def pos_arg(name, arg_options = {})
53
- positional << ::EacCli::Definition::PositionalArgument.new(name, arg_options)
62
+ def options_argument=(enable)
63
+ main_alternative.options_argument(enable)
54
64
  end
55
65
 
56
- def positional
57
- @positional ||= []
58
- end
66
+ delegate :arg_opt, :bool_opt, :options, :pos_arg,
67
+ :positional, :subcommands, to: :main_alternative
59
68
 
60
- def subcommands
61
- positional << ::EacCli::Definition::PositionalArgument.new('subcommand', subcommand: true)
69
+ def subcommands?
70
+ alternatives.any?(&:subcommands?)
62
71
  end
63
72
 
64
73
  def options_first(enable = true)
@@ -68,5 +77,23 @@ module EacCli
68
77
  def options_first?
69
78
  @options_first ? true : false
70
79
  end
80
+
81
+ private
82
+
83
+ def alternatives_set
84
+ @alternatives_set ||= ::ActiveSupport::HashWithIndifferentAccess.new
85
+ end
86
+
87
+ def new_alternative_key
88
+ @last_key ||= 0
89
+ loop do
90
+ @last_key += 1
91
+ break @last_key unless alternatives_set.key?(@last_key)
92
+ end
93
+ end
94
+
95
+ def pos_set
96
+ @pos_set ||= []
97
+ end
71
98
  end
72
99
  end