git_toolbox 0.7.1 → 0.8.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.
@@ -18,15 +18,14 @@
18
18
  # frozen_string_literal: true
19
19
 
20
20
  require 'highline'
21
- require 'get/commons/git'
21
+ require_relative '../../commons/git'
22
22
 
23
- # Module for asking to the user informations about a commit message.
23
+ # Module for asking to the user information about a commit message.
24
24
  module PromptHandler
25
- @@cli = HighLine.new
26
-
27
- @@custom_values_initialized = nil
28
- @@custom_types = []
29
- @@custom_scopes = []
25
+ Common.module_instance_value(self, 'cli', 'HighLine.new')
26
+ Common.module_instance_attr(self, 'custom_values_initialized', false)
27
+ Common.module_instance_value(self, 'custom_types', [])
28
+ Common.module_instance_value(self, 'custom_scopes', [])
30
29
 
31
30
  STRING_VALUE_VALIDATOR = /\s*\S+\s*/
32
31
  BODY_END_DELIMITER = "\n\n\n"
@@ -46,14 +45,15 @@ module PromptHandler
46
45
 
47
46
  def ask_for_type
48
47
  extract_types_and_scopes
49
- @@cli.choose do |menu|
48
+
49
+ MOD_REF.cli.choose do |menu|
50
50
  menu.flow = :columns_down
51
51
  menu.prompt = 'Choose the type of your commit: '
52
- DEFAULT_TYPES.union(@@custom_types).each do |type|
52
+ DEFAULT_TYPES.union(MOD_REF.custom_types).each do |type|
53
53
  menu.choice(type.to_sym)
54
54
  end
55
55
  menu.choice('Create a new type (rarely needed)') do |_|
56
- @@cli.ask('Write the new type to use', String) do |question|
56
+ MOD_REF.cli.ask('Write the new type to use', String) do |question|
57
57
  question.verify_match = true
58
58
  question.validate = STRING_VALUE_VALIDATOR
59
59
  end
@@ -63,14 +63,14 @@ module PromptHandler
63
63
 
64
64
  def ask_for_scope
65
65
  extract_types_and_scopes
66
- @@cli.choose do |menu|
66
+ MOD_REF.cli.choose do |menu|
67
67
  menu.flow = :columns_down
68
68
  menu.prompt = 'Choose the scope of your commit: '
69
- @@custom_scopes.each do |scope|
69
+ MOD_REF.custom_scopes.each do |scope|
70
70
  menu.choice(scope.to_sym)
71
71
  end
72
72
  menu.choice('Create a new scope') do |_|
73
- @@cli.ask('Write the new scope to use', String) do |question|
73
+ MOD_REF.cli.ask('Write the new scope to use', String) do |question|
74
74
  question.verify_match = true
75
75
  question.validate = STRING_VALUE_VALIDATOR
76
76
  end
@@ -80,13 +80,13 @@ module PromptHandler
80
80
  end
81
81
 
82
82
  def ask_for_breaking
83
- @@cli.agree('Does the commit contain a breaking change? (yes/no) ') do |question|
83
+ MOD_REF.cli.agree('Does the commit contain a breaking change? (yes/no) ') do |question|
84
84
  question.default = false
85
85
  end
86
86
  end
87
87
 
88
88
  def ask_for_summary
89
- @@cli.ask('The summary of the commit:') do |question|
89
+ MOD_REF.cli.ask('The summary of the commit:') do |question|
90
90
  question.verify_match = true
91
91
  question.validate = STRING_VALUE_VALIDATOR
92
92
  end
@@ -94,31 +94,33 @@ module PromptHandler
94
94
 
95
95
  def ask_for_message
96
96
  # This method needs a special implementation as the body message can span multiple lines.
97
- @@cli.puts('The body of the commit (ends after 3 new lines):')
98
- @@cli.input.gets(BODY_END_DELIMITER)
97
+ MOD_REF.cli.puts('The body of the commit (ends after 3 new lines):')
98
+ MOD_REF.cli.input.gets(BODY_END_DELIMITER)
99
99
  end
100
100
 
101
101
  private
102
102
 
103
103
  FIRST_COMMIT = nil
104
104
 
105
+ Common.add_module_self_reference(self)
106
+
105
107
  # This method tries to optimize input parsing by performing multiple operations in one go.
106
108
  # So its complexity is a bit higher as it needs to make multiple checks.
107
109
  # rubocop:disable Metrics/CyclomaticComplexity
108
110
  def extract_types_and_scopes
109
- return unless @@custom_values_initialized.nil?
111
+ return if MOD_REF.custom_values_initialized
110
112
 
111
113
  Git.with_commit_list_from(FIRST_COMMIT) do |commit_list|
112
- commit_list.map do |element|
114
+ commit_list.reverse.map do |element|
113
115
  match = Git::CONVENTIONAL_COMMIT_REGEX.match(element)
114
116
  next if match.nil?
115
117
 
116
- type_already_added = DEFAULT_TYPES.include?(match[1].to_sym) || @@custom_types.include?(match[1])
117
- @@custom_types.append(match[1]) unless type_already_added
118
- @@custom_scopes.append(match[3]) unless match[3].nil? || @@custom_scopes.include?(match[3])
118
+ type_already_added = DEFAULT_TYPES.include?(match[1].to_sym) || MOD_REF.custom_types.include?(match[1])
119
+ MOD_REF.custom_types.append(match[1]) unless type_already_added
120
+ MOD_REF.custom_scopes.append(match[3]) unless match[3].nil? || MOD_REF.custom_scopes.include?(match[3])
119
121
  end
120
122
  end
121
- @@custom_values_initialized = true
123
+ MOD_REF.custom_values_initialized = true
122
124
  end
123
125
  # rubocop:enable Metrics/CyclomaticComplexity
124
126
  end
@@ -22,7 +22,7 @@ module BashCompletion
22
22
  def bash_completion(main_module, command_name)
23
23
  generate_functions(main_module, command_name, INITIAL_LEVEL)
24
24
 
25
- "#{HEADER}\n#{@@function_stack.reverse.join("\n")}"
25
+ "#{HEADER}\n#{MOD_REF.function_stack.reverse.join("\n")}"
26
26
  end
27
27
 
28
28
  private
@@ -37,7 +37,8 @@ module BashCompletion
37
37
  #
38
38
  HEADER
39
39
 
40
- @@function_stack = []
40
+ Common.add_module_self_reference(self)
41
+ Common.module_instance_value(self, 'function_stack', [])
41
42
 
42
43
  def full_subcommand_name(base, name)
43
44
  "#{base}_#{name}"
@@ -74,18 +75,18 @@ module BashCompletion
74
75
  short_options = []
75
76
  subcommands = []
76
77
 
77
- command_class.class_variable_get(:@@option_parser).specs.each_value do |option|
78
+ command_class.instance.option_parser.specs.each_value do |option|
78
79
  long_options.push("--#{option.long}")
79
80
  short_options.push("-#{option.short.nil? ? option.long[0] : option.short}") if option.short != :none
80
81
  end
81
82
 
82
- command_class.class_variable_get(:@@subcommands).each_key do |subcommand|
83
+ command_class.instance.subcommands.each_key do |subcommand|
83
84
  subcommands.push(subcommand.to_s)
84
85
  end
85
86
 
86
- @@function_stack.push(completion_function_definition(name, level, long_options, short_options, subcommands))
87
+ MOD_REF.function_stack.push(completion_function_definition(name, level, long_options, short_options, subcommands))
87
88
 
88
- command_class.class_variable_get(:@@subcommands).each do |element|
89
+ command_class.instance.subcommands.each do |element|
89
90
  generate_functions(element[1].class, full_subcommand_name(name, element[0].to_s), level + 1)
90
91
  end
91
92
  end
@@ -17,54 +17,49 @@
17
17
 
18
18
  # frozen_string_literal: true
19
19
 
20
- require 'English'
21
- require 'get/commons/common'
22
- require 'get/subcommand/command'
23
- require 'get/subcommand/complete/bash_completion'
24
- require 'get'
20
+ require_relative '../../commons/common'
21
+ require_relative '../command'
22
+ require_relative './bash_completion'
23
+ require_relative '../../../get'
25
24
 
26
25
  # Class length is disabled as most of its length is given by formatting.
27
26
  # rubocop:disable Metrics/ClassLength
28
27
  # Subcommand, prints the bash completion script.
29
28
  class Complete < Command
30
- def self.command
31
- @@command ||= new
32
- @@command
33
- end
34
-
35
- private_class_method :new
36
-
37
29
  private
38
30
 
39
31
  include BashCompletion
40
32
 
41
- @@command = nil
33
+ def initialize
34
+ super() do
35
+ @usage = 'complete -h|(<subcommand> [<subcommand-options])'
36
+ @description = 'Print the shell completion script.'
37
+ @subcommands = {}
38
+ end
39
+ end
42
40
 
43
- @@usage = 'complete -h|(<subcommand> [<subcommand-options])'
44
- @@description = 'Print the shell completion script.'
45
- @@subcommands = {}
46
- # This block is Optimist configuration. It is as long as the number of options of the command.
47
- # rubocop:disable Metrics/BlockLength
48
- @@option_parser = Optimist::Parser.new do
49
- subcommand_max_length = @@subcommands.keys.map { |k| k.to_s.length }.max
50
- subcommand_section = <<~SUBCOMMANDS unless @@subcommands.empty?
51
- Subcommands:
52
- #{@@subcommands.keys.map { |k| " #{k.to_s.ljust(subcommand_max_length)} => #{@@subcommands[k].description}" }.join("\n")}
53
- SUBCOMMANDS
54
- usage @@usage
55
- synopsis @@description + (subcommand_section.nil? ? '' : "\n") + subcommand_section.to_s
56
- opt :shell,
57
- 'Select the type of shell of which the completion will be generated.',
58
- { type: :string, default: 'bash' }
59
- educate_on_error
60
- stop_on @@subcommands.keys.map(&:to_s)
41
+ protected
42
+
43
+ def setup_option_parser
44
+ @option_parser = Optimist::Parser.new(
45
+ @usage,
46
+ full_description,
47
+ stop_condition
48
+ ) do |usage_header, description, stop_condition|
49
+ usage usage_header
50
+ synopsis description
51
+ opt :shell,
52
+ 'Select the type of shell of which the completion will be generated.',
53
+ { type: :string, default: 'bash' }
54
+ educate_on_error
55
+ stop_on stop_condition
56
+ end
61
57
  end
62
- # rubocop:enable Metrics/BlockLength
63
58
 
64
- def initialize
65
- super(@@usage, @@description) do
66
- @options = Common.with_subcommand_exception_handling @@option_parser do
67
- @@option_parser.parse
59
+ def setup_action
60
+ @action = lambda do
61
+ @options = Common.with_subcommand_exception_handling @option_parser do
62
+ @option_parser.parse
68
63
  end
69
64
 
70
65
  @completions = {
@@ -22,50 +22,48 @@ module ChangeHandler
22
22
  # Array with change types in ascending order of importance.
23
23
  CHANGE_TYPE = %i[NONE PATCH MINOR MAJOR].freeze
24
24
 
25
- @@major_trigger = 'is_breaking'
26
- @@minor_trigger = "type == 'feat'"
27
- @@patch_trigger = "type == 'fix'"
25
+ DEFAULT_MAJOR_TRIGGER = 'is_breaking'
26
+ DEFAULT_MINOR_TRIGGER = "type == 'feat'"
27
+ DEFAULT_PATCH_TRIGGER = "type == 'fix'"
28
28
 
29
- module_function
29
+ Common.module_instance_attr(self, 'major_trigger', :DEFAULT_MAJOR_TRIGGER)
30
+ Common.module_instance_attr(self, 'minor_trigger', :DEFAULT_MINOR_TRIGGER)
31
+ Common.module_instance_attr(self, 'patch_trigger', :DEFAULT_PATCH_TRIGGER)
32
+
33
+ def greatest_change_in(commit_list)
34
+ commit_list
35
+ .grep(Git::CONVENTIONAL_COMMIT_REGEX)
36
+ .map { |commit| to_change(commit) }
37
+ .max { |a, b| CHANGE_TYPE.index(a) <=> CHANGE_TYPE.index(b) }
38
+ end
39
+
40
+ private
30
41
 
31
42
  # In this block method arguments can be used by user.
32
43
  # Also `eval` is needed to allow users to define their custom triggers.
33
44
  # rubocop:disable Lint/UnusedMethodArgument
34
45
  # rubocop:disable Security/Eval
35
46
  def triggers_major?(type, scope, is_breaking)
36
- eval(@@major_trigger)
47
+ eval(ChangeHandler.major_trigger)
37
48
  end
38
49
 
39
50
  def triggers_minor?(type, scope)
40
- eval(@@minor_trigger)
51
+ eval(ChangeHandler.minor_trigger)
41
52
  end
42
53
 
43
54
  def triggers_patch?(type, scope)
44
- eval(@@patch_trigger)
55
+ eval(ChangeHandler.patch_trigger)
45
56
  end
46
57
  # rubocop:enable Lint/UnusedMethodArgument
47
58
  # rubocop:enable Security/Eval
48
59
 
49
- # Open String class to inject method to convert a (commit) string into
50
- # a change.
51
- class ::String
52
- # Convert the string (as a conventional commit string) into a change type.
53
- def to_change
54
- groups = Git::CONVENTIONAL_COMMIT_REGEX.match(self)
55
- return :MAJOR if ChangeHandler.triggers_major?(groups[1], groups[3], !groups[4].nil?)
56
- return :MINOR if ChangeHandler.triggers_minor?(groups[1], groups[2])
57
- return :PATCH if ChangeHandler.triggers_patch?(groups[1], groups[2])
60
+ # Convert the string (as a conventional commit string) into a change type.
61
+ def to_change(commit_message)
62
+ groups = Git::CONVENTIONAL_COMMIT_REGEX.match(commit_message)
63
+ return :MAJOR if triggers_major?(groups[1], groups[3], !groups[4].nil?)
64
+ return :MINOR if triggers_minor?(groups[1], groups[2])
65
+ return :PATCH if triggers_patch?(groups[1], groups[2])
58
66
 
59
- :NONE
60
- end
61
- end
62
-
63
- public
64
-
65
- def greatest_change_in(commit_list)
66
- commit_list
67
- .grep(Git::CONVENTIONAL_COMMIT_REGEX)
68
- .map(&:to_change)
69
- .max { |a, b| CHANGE_TYPE.index(a) <=> CHANGE_TYPE.index(b) }
67
+ :NONE
70
68
  end
71
69
  end
@@ -17,24 +17,20 @@
17
17
 
18
18
  # frozen_string_literal: true
19
19
 
20
- require 'get/commons/common'
21
- require 'get/commons/git'
22
- require 'get/subcommand/command'
23
- require 'get/subcommand/describe/change'
24
- require 'get/subcommand/describe/prerelease'
25
- require 'get/subcommand/describe/metadata'
26
- require 'get/subcommand/describe/docker/docker'
20
+ require_relative '../../commons/common'
21
+ require_relative '../../commons/git'
22
+ require_relative '../command'
23
+ require_relative './change'
24
+ require_relative './prerelease'
25
+ require_relative './metadata'
26
+ require_relative './docker/docker'
27
27
 
28
28
  # Class length is disabled as most of its length is given by formatting.
29
29
  # rubocop:disable Metrics/ClassLength
30
30
  # Subcommand, it manages the description of the current git repository using semantic version.
31
+ # All its subcommands should have a method named "describe_current_commit" as it will be called.
31
32
  class Describe < Command
32
- def self.command
33
- @@command ||= new
34
- @@command
35
- end
36
-
37
- private_class_method :new
33
+ include Singleton
38
34
 
39
35
  private
40
36
 
@@ -42,8 +38,6 @@ class Describe < Command
42
38
  include PrereleaseHandler
43
39
  include MetadataHandler
44
40
 
45
- @@command = nil
46
-
47
41
  DEFAULT_RELEASE_VERSION = '0.1.0'
48
42
  FULL_SEMANTIC_VERSION_REGEX = /
49
43
  ^((0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)) # Stable version, major, minor, patch
@@ -51,107 +45,41 @@ class Describe < Command
51
45
  (?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$ # metadata
52
46
  /x
53
47
 
54
- @@usage = 'describe -h|(<subcommand> [<subcommand-options])'
55
- @@description = 'Describe the current git repository with semantic version.'
56
- @@subcommands = {
57
- docker: DescribeDocker.command,
58
- }
59
- # This block is Optimist configuration. It is as long as the number of options of the command.
60
- # rubocop:disable Metrics/BlockLength
61
- @@option_parser = Optimist::Parser.new do
62
- subcommand_max_length = @@subcommands.keys.map { |k| k.to_s.length }.max
63
- subcommand_section = <<~SUBCOMMANDS unless @@subcommands.empty?
64
- Subcommands:
65
- #{@@subcommands.keys.map { |k| " #{k.to_s.ljust(subcommand_max_length)} => #{@@subcommands[k].description}" }.join("\n")}
66
- SUBCOMMANDS
67
- usage @@usage
68
- synopsis @@description + (subcommand_section.nil? ? '' : "\n") + subcommand_section.to_s
69
- opt :prerelease,
70
- 'Describe a prerelease rather than a release',
71
- short: :none
72
- opt :exclude_metadata,
73
- 'Do not include metadata in version.'
74
- opt :metadata,
75
- 'Set which metadata to include in the string. ' \
76
- 'Multiple value can be specified by separating the with a comma \',\'.',
77
- { type: :string, default: 'sha' }
78
- opt :major_trigger,
79
- 'Set the trigger for a major release. ' \
80
- 'This must be a valid Ruby expression. ' \
81
- 'In this expression the string values "type" and "scope" ' \
82
- 'and the boolean value "is_breaking" can be used.',
83
- { short: :none, type: :string, default: 'is_breaking' }
84
- opt :minor_trigger,
85
- 'Set the trigger for a minor release. ' \
86
- 'This must be a valid Ruby expression. ' \
87
- 'In this expression the string values "type" and "scope" can be used.',
88
- { short: :none, type: :string, default: "type == 'feat'" }
89
- opt :patch_trigger,
90
- 'Set the trigger for a patch release. ' \
91
- 'This must be a valid Ruby expression. ' \
92
- 'In this expression the string values "type" and "scope" can be used.',
93
- { short: :none, type: :string, default: "type == 'fix'" }
94
- opt :prerelease_pattern,
95
- 'Set the pattern of the prerelease. This must contain the placeholder "(p)".',
96
- { short: :none, type: :string, default: 'dev(p)' }
97
- opt :old_prerelease_pattern,
98
- 'Set the pattern of the old prerelease. It is useful for changing prerelease pattern.',
99
- { short: :none, type: :string, default: 'prerelease-pattern value' }
100
- opt :diff,
101
- 'Print also the last version.'
102
- opt :create_tag,
103
- 'Create a signed tag with the computed version.',
104
- { short: :none }
105
- opt :tag_message,
106
- 'Add the given message to the tag. Requires "--create-tag".',
107
- { short: :none, type: :string }
108
- educate_on_error
109
- stop_on @@subcommands.keys.map(&:to_s)
110
- end
111
- # rubocop:enable Metrics/BlockLength
112
-
113
48
  def initialize
114
- super(@@usage, @@description) do
115
- @options = Common.with_subcommand_exception_handling @@option_parser do
116
- @@option_parser.parse
117
- end
118
- Common.error 'describe need to be run inside a git repository' unless Git.in_repo?
119
- set_options
120
-
121
- if ARGV.length.positive?
122
- subcommand = ARGV.shift.to_sym
123
- if @@subcommands.include?(subcommand)
124
- @@subcommands[subcommand].action.call(describe_current_commit)
125
- else
126
- # This error should not be disabled by -W0
127
- # rubocop:disable Style/StderrPuts
128
- $stderr.puts "Error: subcommand '#{subcommand}' unknown."
129
- # rubocop:enable Style/StderrPuts
130
- exit 1
131
- end
132
- else
133
- puts describe_current_commit
134
- end
49
+ super() do
50
+ @usage = 'describe -h|(<subcommand> [<subcommand-options])'
51
+ @description = 'Describe the current git repository with semantic version.'
52
+ @subcommands = {
53
+ docker: DescribeDocker.instance,
54
+ }
135
55
  end
136
56
  end
137
57
 
138
58
  def set_options
139
- @@major_trigger = @options[:major_trigger] if @options[:major_trigger_given]
140
- @@minor_trigger = @options[:minor_trigger] if @options[:minor_trigger_given]
141
- @@patch_trigger = @options[:patch_trigger] if @options[:patch_trigger_given]
142
- @@old_prerelease_pattern = @options[:old_prerelease_pattern] if @options[:old_prerelease_pattern_given]
143
- @@prerelease_pattern = @options[:prerelease_pattern] if @options[:prerelease_pattern_given]
59
+ ChangeHandler.major_trigger = @options[:major_trigger] if @options[:major_trigger_given]
60
+ ChangeHandler.minor_trigger = @options[:minor_trigger] if @options[:minor_trigger_given]
61
+ ChangeHandler.patch_trigger = @options[:patch_trigger] if @options[:patch_trigger_given]
62
+ if @options[:old_prerelease_pattern_given]
63
+ PrereleaseHandler.old_prerelease_pattern = @options[:old_prerelease_pattern]
64
+ end
65
+ PrereleaseHandler.prerelease_pattern = @options[:prerelease_pattern] if @options[:prerelease_pattern_given]
144
66
  end
145
67
 
146
68
  def describe_current_commit
147
- return Git.last_version if Git.with_commit_list_from(Git.last_version, &:empty?)
148
-
149
- puts "Last version: #{Git.last_version}" if @options[:diff]
69
+ if Git.with_commit_list_from(Git.last_version, &:empty?)
70
+ if Git.last_version.nil?
71
+ Common.error('Cannot describe an empty repository.')
72
+ else
73
+ Git.last_version
74
+ end
75
+ else
76
+ puts "Last version: #{Git.last_version}" if @options[:diff]
150
77
 
151
- current_commit_version = next_release
152
- create_signed_tag(current_commit_version) if @options[:create_tag]
78
+ current_commit_version = next_release
79
+ create_signed_tag(current_commit_version) if @options[:create_tag]
153
80
 
154
- current_commit_version
81
+ current_commit_version
82
+ end
155
83
  end
156
84
 
157
85
  def next_release
@@ -207,17 +135,87 @@ class Describe < Command
207
135
  end
208
136
 
209
137
  def create_signed_tag(computed_version)
210
- system(
211
- 'git tag -s ' \
212
- "#{
213
- if @options[:tag_message_given]
214
- "-m #{@options[:tag_message]}"
138
+ tag_message_cli = if @options[:tag_message_given]
139
+ "\"#{@options[:tag_message].gsub('"', '\"')}\""
140
+ else
141
+ '""'
142
+ end
143
+ CommandIssuer.run('git', 'tag', '-s', '-m', tag_message_cli, "'#{computed_version}'")
144
+ end
145
+
146
+ protected
147
+
148
+ def setup_option_parser
149
+ @option_parser = Optimist::Parser.new(
150
+ @usage,
151
+ full_description,
152
+ stop_condition
153
+ ) do |usage_header, description, stop_condition|
154
+ usage usage_header
155
+ synopsis description
156
+ opt :prerelease,
157
+ 'Describe a prerelease rather than a release',
158
+ short: :none
159
+ opt :exclude_metadata,
160
+ 'Do not include metadata in version.'
161
+ opt :metadata,
162
+ 'Set which metadata to include in the string. ' \
163
+ 'Multiple value can be specified by separating the with a comma \',\'.',
164
+ { type: :string, default: 'sha' }
165
+ opt :major_trigger,
166
+ 'Set the trigger for a major release. ' \
167
+ 'This must be a valid Ruby expression. ' \
168
+ 'In this expression the string values "type" and "scope" ' \
169
+ 'and the boolean value "is_breaking" can be used.',
170
+ { short: :none, type: :string, default: 'is_breaking' }
171
+ opt :minor_trigger,
172
+ 'Set the trigger for a minor release. ' \
173
+ 'This must be a valid Ruby expression. ' \
174
+ 'In this expression the string values "type" and "scope" can be used.',
175
+ { short: :none, type: :string, default: "type == 'feat'" }
176
+ opt :patch_trigger,
177
+ 'Set the trigger for a patch release. ' \
178
+ 'This must be a valid Ruby expression. ' \
179
+ 'In this expression the string values "type" and "scope" can be used.',
180
+ { short: :none, type: :string, default: "type == 'fix'" }
181
+ opt :prerelease_pattern,
182
+ 'Set the pattern of the prerelease. This must contain the placeholder "(p)".',
183
+ { short: :none, type: :string, default: 'dev(p)' }
184
+ opt :old_prerelease_pattern,
185
+ 'Set the pattern of the old prerelease. It is useful for changing prerelease pattern.',
186
+ { short: :none, type: :string, default: 'prerelease-pattern value' }
187
+ opt :diff,
188
+ 'Print also the last version.'
189
+ opt :create_tag,
190
+ 'Create a signed tag with the computed version.',
191
+ { short: :none }
192
+ opt :tag_message,
193
+ 'Add the given message to the tag. Requires "--create-tag".',
194
+ { short: :none, type: :string }
195
+ educate_on_error
196
+ stop_on stop_condition
197
+ end
198
+ end
199
+
200
+ def setup_action
201
+ @action = lambda do
202
+ @options = Common.with_subcommand_exception_handling @option_parser do
203
+ @option_parser.parse
204
+ end
205
+ Common.error 'describe need to be run inside a git repository' unless Git.in_repo?
206
+ set_options
207
+
208
+ if ARGV.length.positive?
209
+ subcommand = ARGV.shift.to_sym
210
+ if @subcommands.include?(subcommand)
211
+ @subcommands[subcommand].action.call(describe_current_commit)
215
212
  else
216
- ''
213
+ Common.error "subcommand '#{subcommand}' unknown."
217
214
  end
218
- } " \
219
- "'#{computed_version}'"
220
- )
215
+ else
216
+ puts describe_current_commit
217
+ end
218
+ end
221
219
  end
222
220
  end
223
221
  # rubocop:enable Metrics/ClassLength