rubygems-update 3.4.20 → 3.4.22

Sign up to get free protection for your applications and to get access to all the features.
Files changed (227) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +55 -0
  3. data/Manifest.txt +6 -0
  4. data/bundler/CHANGELOG.md +55 -3
  5. data/bundler/README.md +1 -2
  6. data/bundler/lib/bundler/build_metadata.rb +3 -3
  7. data/bundler/lib/bundler/cli/check.rb +1 -1
  8. data/bundler/lib/bundler/cli/gem.rb +4 -3
  9. data/bundler/lib/bundler/cli/install.rb +2 -2
  10. data/bundler/lib/bundler/cli/lock.rb +26 -23
  11. data/bundler/lib/bundler/cli/open.rb +5 -7
  12. data/bundler/lib/bundler/definition.rb +43 -26
  13. data/bundler/lib/bundler/endpoint_specification.rb +1 -1
  14. data/bundler/lib/bundler/env.rb +2 -2
  15. data/bundler/lib/bundler/errors.rb +15 -0
  16. data/bundler/lib/bundler/gem_helpers.rb +7 -0
  17. data/bundler/lib/bundler/gem_version_promoter.rb +2 -2
  18. data/bundler/lib/bundler/injector.rb +1 -1
  19. data/bundler/lib/bundler/installer/gem_installer.rb +5 -5
  20. data/bundler/lib/bundler/installer/parallel_installer.rb +0 -26
  21. data/bundler/lib/bundler/installer/standalone.rb +13 -6
  22. data/bundler/lib/bundler/lazy_specification.rb +4 -0
  23. data/bundler/lib/bundler/lockfile_parser.rb +29 -24
  24. data/bundler/lib/bundler/man/bundle-add.1 +1 -1
  25. data/bundler/lib/bundler/man/bundle-binstubs.1 +1 -1
  26. data/bundler/lib/bundler/man/bundle-cache.1 +1 -1
  27. data/bundler/lib/bundler/man/bundle-check.1 +1 -1
  28. data/bundler/lib/bundler/man/bundle-clean.1 +1 -1
  29. data/bundler/lib/bundler/man/bundle-config.1 +1 -1
  30. data/bundler/lib/bundler/man/bundle-console.1 +1 -1
  31. data/bundler/lib/bundler/man/bundle-doctor.1 +1 -1
  32. data/bundler/lib/bundler/man/bundle-exec.1 +2 -2
  33. data/bundler/lib/bundler/man/bundle-exec.1.ronn +2 -3
  34. data/bundler/lib/bundler/man/bundle-gem.1 +1 -1
  35. data/bundler/lib/bundler/man/bundle-help.1 +1 -1
  36. data/bundler/lib/bundler/man/bundle-info.1 +1 -1
  37. data/bundler/lib/bundler/man/bundle-init.1 +1 -1
  38. data/bundler/lib/bundler/man/bundle-inject.1 +1 -1
  39. data/bundler/lib/bundler/man/bundle-install.1 +1 -1
  40. data/bundler/lib/bundler/man/bundle-list.1 +1 -1
  41. data/bundler/lib/bundler/man/bundle-lock.1 +1 -1
  42. data/bundler/lib/bundler/man/bundle-open.1 +1 -1
  43. data/bundler/lib/bundler/man/bundle-outdated.1 +1 -1
  44. data/bundler/lib/bundler/man/bundle-platform.1 +1 -1
  45. data/bundler/lib/bundler/man/bundle-plugin.1 +17 -17
  46. data/bundler/lib/bundler/man/bundle-plugin.1.ronn +5 -5
  47. data/bundler/lib/bundler/man/bundle-pristine.1 +1 -1
  48. data/bundler/lib/bundler/man/bundle-remove.1 +1 -1
  49. data/bundler/lib/bundler/man/bundle-show.1 +1 -1
  50. data/bundler/lib/bundler/man/bundle-update.1 +1 -1
  51. data/bundler/lib/bundler/man/bundle-version.1 +1 -1
  52. data/bundler/lib/bundler/man/bundle-viz.1 +1 -1
  53. data/bundler/lib/bundler/man/bundle.1 +1 -1
  54. data/bundler/lib/bundler/man/gemfile.5 +1 -1
  55. data/bundler/lib/bundler/plugin/index.rb +8 -0
  56. data/bundler/lib/bundler/plugin.rb +9 -2
  57. data/bundler/lib/bundler/resolver/package.rb +5 -0
  58. data/bundler/lib/bundler/resolver.rb +27 -7
  59. data/bundler/lib/bundler/ruby_version.rb +8 -1
  60. data/bundler/lib/bundler/rubygems_ext.rb +3 -4
  61. data/bundler/lib/bundler/rubygems_gem_installer.rb +23 -8
  62. data/bundler/lib/bundler/settings.rb +53 -16
  63. data/bundler/lib/bundler/shared_helpers.rb +16 -1
  64. data/bundler/lib/bundler/source/git/git_proxy.rb +21 -4
  65. data/bundler/lib/bundler/source/metadata.rb +1 -1
  66. data/bundler/lib/bundler/spec_set.rb +7 -4
  67. data/bundler/lib/bundler/stub_specification.rb +4 -2
  68. data/bundler/lib/bundler/templates/newgem/Rakefile.tt +6 -2
  69. data/bundler/lib/bundler/templates/newgem/newgem.gemspec.tt +1 -1
  70. data/bundler/lib/bundler/ui/shell.rb +1 -1
  71. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/connection.rb +1 -0
  72. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent/pool.rb +21 -9
  73. data/bundler/lib/bundler/vendor/net-http-persistent/lib/net/http/persistent.rb +1 -1
  74. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/create_file.rb +3 -2
  75. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/directory.rb +1 -1
  76. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/empty_directory.rb +1 -1
  77. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/file_manipulation.rb +8 -10
  78. data/bundler/lib/bundler/vendor/thor/lib/thor/actions/inject_into_file.rb +15 -4
  79. data/bundler/lib/bundler/vendor/thor/lib/thor/actions.rb +15 -15
  80. data/bundler/lib/bundler/vendor/thor/lib/thor/base.rb +140 -14
  81. data/bundler/lib/bundler/vendor/thor/lib/thor/command.rb +13 -4
  82. data/bundler/lib/bundler/vendor/thor/lib/thor/core_ext/hash_with_indifferent_access.rb +4 -0
  83. data/bundler/lib/bundler/vendor/thor/lib/thor/error.rb +16 -25
  84. data/bundler/lib/bundler/vendor/thor/lib/thor/group.rb +1 -1
  85. data/bundler/lib/bundler/vendor/thor/lib/thor/invocation.rb +1 -1
  86. data/bundler/lib/bundler/vendor/thor/lib/thor/nested_context.rb +2 -2
  87. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/argument.rb +20 -1
  88. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/arguments.rb +33 -17
  89. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/option.rb +27 -8
  90. data/bundler/lib/bundler/vendor/thor/lib/thor/parser/options.rb +44 -6
  91. data/bundler/lib/bundler/vendor/thor/lib/thor/rake_compat.rb +2 -2
  92. data/bundler/lib/bundler/vendor/thor/lib/thor/runner.rb +40 -30
  93. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/basic.rb +26 -150
  94. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/color.rb +4 -46
  95. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/column_printer.rb +29 -0
  96. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/html.rb +3 -45
  97. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/lcs_diff.rb +49 -0
  98. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/table_printer.rb +134 -0
  99. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/terminal.rb +42 -0
  100. data/bundler/lib/bundler/vendor/thor/lib/thor/shell/wrapped_printer.rb +38 -0
  101. data/bundler/lib/bundler/vendor/thor/lib/thor/shell.rb +1 -1
  102. data/bundler/lib/bundler/vendor/thor/lib/thor/util.rb +8 -7
  103. data/bundler/lib/bundler/vendor/thor/lib/thor/version.rb +1 -1
  104. data/bundler/lib/bundler/vendor/thor/lib/thor.rb +155 -8
  105. data/bundler/lib/bundler/version.rb +1 -1
  106. data/bundler/lib/bundler/yaml_serializer.rb +12 -8
  107. data/bundler/lib/bundler.rb +0 -8
  108. data/lib/rubygems/basic_specification.rb +1 -1
  109. data/lib/rubygems/command.rb +5 -5
  110. data/lib/rubygems/command_manager.rb +1 -1
  111. data/lib/rubygems/commands/cert_command.rb +3 -3
  112. data/lib/rubygems/commands/check_command.rb +5 -1
  113. data/lib/rubygems/commands/cleanup_command.rb +1 -1
  114. data/lib/rubygems/commands/contents_command.rb +2 -2
  115. data/lib/rubygems/commands/environment_command.rb +2 -2
  116. data/lib/rubygems/commands/help_command.rb +3 -3
  117. data/lib/rubygems/commands/open_command.rb +1 -3
  118. data/lib/rubygems/commands/owner_command.rb +1 -1
  119. data/lib/rubygems/commands/setup_command.rb +10 -10
  120. data/lib/rubygems/commands/specification_command.rb +5 -1
  121. data/lib/rubygems/commands/stale_command.rb +1 -1
  122. data/lib/rubygems/commands/uninstall_command.rb +4 -4
  123. data/lib/rubygems/commands/unpack_command.rb +3 -3
  124. data/lib/rubygems/commands/update_command.rb +4 -4
  125. data/lib/rubygems/commands/yank_command.rb +1 -1
  126. data/lib/rubygems/config_file.rb +63 -16
  127. data/lib/rubygems/core_ext/kernel_gem.rb +1 -1
  128. data/lib/rubygems/core_ext/kernel_require.rb +2 -2
  129. data/lib/rubygems/defaults.rb +6 -2
  130. data/lib/rubygems/dependency_installer.rb +4 -4
  131. data/lib/rubygems/deprecate.rb +2 -1
  132. data/lib/rubygems/doctor.rb +2 -2
  133. data/lib/rubygems/errors.rb +1 -1
  134. data/lib/rubygems/exceptions.rb +1 -1
  135. data/lib/rubygems/ext/builder.rb +5 -4
  136. data/lib/rubygems/ext/cargo_builder.rb +2 -2
  137. data/lib/rubygems/ext/ext_conf_builder.rb +1 -1
  138. data/lib/rubygems/ext/rake_builder.rb +1 -1
  139. data/lib/rubygems/gem_runner.rb +5 -1
  140. data/lib/rubygems/gemcutter_utilities.rb +2 -2
  141. data/lib/rubygems/indexer.rb +1 -1
  142. data/lib/rubygems/install_update_options.rb +1 -1
  143. data/lib/rubygems/installer.rb +15 -20
  144. data/lib/rubygems/local_remote_options.rb +1 -1
  145. data/lib/rubygems/package/digest_io.rb +1 -1
  146. data/lib/rubygems/package/old.rb +1 -1
  147. data/lib/rubygems/package/tar_header.rb +2 -2
  148. data/lib/rubygems/package/tar_reader.rb +9 -2
  149. data/lib/rubygems/package/tar_writer.rb +2 -2
  150. data/lib/rubygems/package.rb +9 -9
  151. data/lib/rubygems/path_support.rb +1 -1
  152. data/lib/rubygems/platform.rb +12 -6
  153. data/lib/rubygems/query_utils.rb +4 -4
  154. data/lib/rubygems/remote_fetcher.rb +12 -4
  155. data/lib/rubygems/request.rb +1 -1
  156. data/lib/rubygems/request_set/gem_dependency_api.rb +1 -1
  157. data/lib/rubygems/request_set.rb +2 -1
  158. data/lib/rubygems/requirement.rb +1 -1
  159. data/lib/rubygems/resolver/api_set.rb +2 -1
  160. data/lib/rubygems/resolver/api_specification.rb +1 -1
  161. data/lib/rubygems/resolver.rb +3 -3
  162. data/lib/rubygems/security/signer.rb +10 -2
  163. data/lib/rubygems/security/trust_dir.rb +5 -5
  164. data/lib/rubygems/security.rb +1 -1
  165. data/lib/rubygems/security_option.rb +1 -1
  166. data/lib/rubygems/source/local.rb +2 -1
  167. data/lib/rubygems/source.rb +5 -1
  168. data/lib/rubygems/source_list.rb +1 -1
  169. data/lib/rubygems/spec_fetcher.rb +2 -2
  170. data/lib/rubygems/specification.rb +30 -23
  171. data/lib/rubygems/specification_policy.rb +11 -11
  172. data/lib/rubygems/uninstaller.rb +3 -3
  173. data/lib/rubygems/update_suggestion.rb +1 -1
  174. data/lib/rubygems/user_interaction.rb +2 -2
  175. data/lib/rubygems/util/licenses.rb +48 -0
  176. data/lib/rubygems/util.rb +5 -1
  177. data/lib/rubygems/validator.rb +1 -1
  178. data/lib/rubygems/version.rb +6 -5
  179. data/lib/rubygems/yaml_serializer.rb +93 -0
  180. data/lib/rubygems.rb +9 -9
  181. data/rubygems-update.gemspec +1 -1
  182. data/setup.rb +2 -0
  183. data/test/rubygems/bundler_test_gem.rb +6 -3
  184. data/test/rubygems/helper.rb +29 -21
  185. data/test/rubygems/package/tar_test_case.rb +2 -2
  186. data/test/rubygems/test_gem.rb +51 -26
  187. data/test/rubygems/test_gem_command.rb +3 -1
  188. data/test/rubygems/test_gem_command_manager.rb +6 -6
  189. data/test/rubygems/test_gem_commands_cert_command.rb +23 -23
  190. data/test/rubygems/test_gem_commands_cleanup_command.rb +2 -2
  191. data/test/rubygems/test_gem_commands_environment_command.rb +2 -1
  192. data/test/rubygems/test_gem_commands_exec_command.rb +5 -1
  193. data/test/rubygems/test_gem_commands_install_command.rb +5 -5
  194. data/test/rubygems/test_gem_commands_open_command.rb +5 -2
  195. data/test/rubygems/test_gem_commands_pristine_command.rb +2 -2
  196. data/test/rubygems/test_gem_commands_push_command.rb +7 -6
  197. data/test/rubygems/test_gem_commands_signin_command.rb +8 -8
  198. data/test/rubygems/test_gem_commands_uninstall_command.rb +21 -1
  199. data/test/rubygems/test_gem_commands_unpack_command.rb +2 -2
  200. data/test/rubygems/test_gem_config_file.rb +46 -12
  201. data/test/rubygems/test_gem_ext_builder.rb +1 -1
  202. data/test/rubygems/test_gem_ext_cargo_builder.rb +2 -2
  203. data/test/rubygems/test_gem_gemcutter_utilities.rb +8 -5
  204. data/test/rubygems/test_gem_install_update_options.rb +3 -3
  205. data/test/rubygems/test_gem_installer.rb +16 -16
  206. data/test/rubygems/test_gem_package.rb +35 -34
  207. data/test/rubygems/test_gem_package_old.rb +1 -1
  208. data/test/rubygems/test_gem_package_tar_header.rb +3 -3
  209. data/test/rubygems/test_gem_package_tar_reader.rb +19 -4
  210. data/test/rubygems/test_gem_package_tar_writer.rb +28 -28
  211. data/test/rubygems/test_gem_rdoc.rb +2 -2
  212. data/test/rubygems/test_gem_remote_fetcher.rb +13 -9
  213. data/test/rubygems/test_gem_request.rb +5 -5
  214. data/test/rubygems/test_gem_request_connection_pools.rb +2 -1
  215. data/test/rubygems/test_gem_request_set_gem_dependency_api.rb +14 -7
  216. data/test/rubygems/test_gem_security.rb +2 -2
  217. data/test/rubygems/test_gem_security_policy.rb +2 -2
  218. data/test/rubygems/test_gem_security_signer.rb +2 -2
  219. data/test/rubygems/test_gem_security_trust_dir.rb +6 -6
  220. data/test/rubygems/test_gem_spec_fetcher.rb +2 -2
  221. data/test/rubygems/test_gem_specification.rb +29 -29
  222. data/test/rubygems/test_gem_stream_ui.rb +1 -1
  223. data/test/rubygems/test_gem_update_suggestion.rb +12 -6
  224. data/test/rubygems/test_gem_util.rb +2 -2
  225. data/test/rubygems/test_gem_version.rb +4 -2
  226. data/test/rubygems/utilities.rb +4 -3
  227. metadata +9 -3
@@ -1,5 +1,5 @@
1
1
  class Bundler::Thor
2
- class Arguments #:nodoc: # rubocop:disable ClassLength
2
+ class Arguments #:nodoc:
3
3
  NUMERIC = /[-+]?(\d*\.\d+|\d+)/
4
4
 
5
5
  # Receives an array of args and returns two arrays, one with arguments
@@ -30,11 +30,7 @@ class Bundler::Thor
30
30
 
31
31
  arguments.each do |argument|
32
32
  if !argument.default.nil?
33
- begin
34
- @assigns[argument.human_name] = argument.default.dup
35
- rescue TypeError # Compatibility shim for un-dup-able Fixnum in Ruby < 2.4
36
- @assigns[argument.human_name] = argument.default
37
- end
33
+ @assigns[argument.human_name] = argument.default.dup
38
34
  elsif argument.required?
39
35
  @non_assigned_required << argument
40
36
  end
@@ -121,8 +117,18 @@ class Bundler::Thor
121
117
  #
122
118
  def parse_array(name)
123
119
  return shift if peek.is_a?(Array)
120
+
124
121
  array = []
125
- array << shift while current_is_value?
122
+
123
+ while current_is_value?
124
+ value = shift
125
+
126
+ if !value.empty?
127
+ validate_enum_value!(name, value, "Expected all values of '%s' to be one of %s; got %s")
128
+ end
129
+
130
+ array << value
131
+ end
126
132
  array
127
133
  end
128
134
 
@@ -138,11 +144,9 @@ class Bundler::Thor
138
144
  end
139
145
 
140
146
  value = $&.index(".") ? shift.to_f : shift.to_i
141
- if @switches.is_a?(Hash) && switch = @switches[name]
142
- if switch.enum && !switch.enum.include?(value)
143
- raise MalformattedArgumentError, "Expected '#{name}' to be one of #{switch.enum.join(', ')}; got #{value}"
144
- end
145
- end
147
+
148
+ validate_enum_value!(name, value, "Expected '%s' to be one of %s; got %s")
149
+
146
150
  value
147
151
  end
148
152
 
@@ -156,15 +160,27 @@ class Bundler::Thor
156
160
  nil
157
161
  else
158
162
  value = shift
159
- if @switches.is_a?(Hash) && switch = @switches[name]
160
- if switch.enum && !switch.enum.include?(value)
161
- raise MalformattedArgumentError, "Expected '#{name}' to be one of #{switch.enum.join(', ')}; got #{value}"
162
- end
163
- end
163
+
164
+ validate_enum_value!(name, value, "Expected '%s' to be one of %s; got %s")
165
+
164
166
  value
165
167
  end
166
168
  end
167
169
 
170
+ # Raises an error if the switch is an enum and the values aren't included on it.
171
+ #
172
+ def validate_enum_value!(name, value, message)
173
+ return unless @switches.is_a?(Hash)
174
+
175
+ switch = @switches[name]
176
+
177
+ return unless switch
178
+
179
+ if switch.enum && !switch.enum.include?(value)
180
+ raise MalformattedArgumentError, message % [name, switch.enum_to_s, value]
181
+ end
182
+ end
183
+
168
184
  # Raises an error if @non_assigned_required array is not empty.
169
185
  #
170
186
  def check_requirement!
@@ -11,7 +11,7 @@ class Bundler::Thor
11
11
  super
12
12
  @lazy_default = options[:lazy_default]
13
13
  @group = options[:group].to_s.capitalize if options[:group]
14
- @aliases = Array(options[:aliases])
14
+ @aliases = normalize_aliases(options[:aliases])
15
15
  @hide = options[:hide]
16
16
  end
17
17
 
@@ -58,7 +58,7 @@ class Bundler::Thor
58
58
  default = nil
59
59
  if VALID_TYPES.include?(value)
60
60
  value
61
- elsif required = (value == :required) # rubocop:disable AssignmentInCondition
61
+ elsif required = (value == :required) # rubocop:disable Lint/AssignmentInCondition
62
62
  :string
63
63
  end
64
64
  when TrueClass, FalseClass
@@ -69,7 +69,7 @@ class Bundler::Thor
69
69
  value.class.name.downcase.to_sym
70
70
  end
71
71
 
72
- new(name.to_s, :required => required, :type => type, :default => default, :aliases => aliases)
72
+ new(name.to_s, required: required, type: type, default: default, aliases: aliases)
73
73
  end
74
74
 
75
75
  def switch_name
@@ -90,13 +90,26 @@ class Bundler::Thor
90
90
  sample = "[#{sample}]".dup unless required?
91
91
 
92
92
  if boolean?
93
- sample << ", [#{dasherize('no-' + human_name)}]" unless (name == "force") || name.start_with?("no-")
93
+ sample << ", [#{dasherize('no-' + human_name)}]" unless (name == "force") || name.match(/\Ano[\-_]/)
94
94
  end
95
95
 
96
+ aliases_for_usage.ljust(padding) + sample
97
+ end
98
+
99
+ def aliases_for_usage
96
100
  if aliases.empty?
97
- (" " * padding) << sample
101
+ ""
102
+ else
103
+ "#{aliases.join(', ')}, "
104
+ end
105
+ end
106
+
107
+ def show_default?
108
+ case default
109
+ when TrueClass, FalseClass
110
+ true
98
111
  else
99
- "#{aliases.join(', ')}, #{sample}"
112
+ super
100
113
  end
101
114
  end
102
115
 
@@ -138,8 +151,8 @@ class Bundler::Thor
138
151
  raise ArgumentError, err
139
152
  elsif @check_default_type == nil
140
153
  Bundler::Thor.deprecation_warning "#{err}.\n" +
141
- 'This will be rejected in the future unless you explicitly pass the options `check_default_type: false`' +
142
- ' or call `allow_incompatible_default_type!` in your code'
154
+ "This will be rejected in the future unless you explicitly pass the options `check_default_type: false`" +
155
+ " or call `allow_incompatible_default_type!` in your code"
143
156
  end
144
157
  end
145
158
  end
@@ -155,5 +168,11 @@ class Bundler::Thor
155
168
  def dasherize(str)
156
169
  (str.length > 1 ? "--" : "-") + str.tr("_", "-")
157
170
  end
171
+
172
+ private
173
+
174
+ def normalize_aliases(aliases)
175
+ Array(aliases).map { |short| short.to_s.sub(/^(?!\-)/, "-") }
176
+ end
158
177
  end
159
178
  end
@@ -1,5 +1,5 @@
1
1
  class Bundler::Thor
2
- class Options < Arguments #:nodoc: # rubocop:disable ClassLength
2
+ class Options < Arguments #:nodoc:
3
3
  LONG_RE = /^(--\w+(?:-\w+)*)$/
4
4
  SHORT_RE = /^(-[a-z])$/i
5
5
  EQ_RE = /^(--\w+(?:-\w+)*|-[a-z])=(.*)$/i
@@ -29,8 +29,10 @@ class Bundler::Thor
29
29
  #
30
30
  # If +stop_on_unknown+ is true, #parse will stop as soon as it encounters
31
31
  # an unknown option or a regular argument.
32
- def initialize(hash_options = {}, defaults = {}, stop_on_unknown = false, disable_required_check = false)
32
+ def initialize(hash_options = {}, defaults = {}, stop_on_unknown = false, disable_required_check = false, relations = {})
33
33
  @stop_on_unknown = stop_on_unknown
34
+ @exclusives = (relations[:exclusive_option_names] || []).select{|array| !array.empty?}
35
+ @at_least_ones = (relations[:at_least_one_option_names] || []).select{|array| !array.empty?}
34
36
  @disable_required_check = disable_required_check
35
37
  options = hash_options.values
36
38
  super(options)
@@ -50,8 +52,7 @@ class Bundler::Thor
50
52
  options.each do |option|
51
53
  @switches[option.switch_name] = option
52
54
 
53
- option.aliases.each do |short|
54
- name = short.to_s.sub(/^(?!\-)/, "-")
55
+ option.aliases.each do |name|
55
56
  @shorts[name] ||= option.switch_name
56
57
  end
57
58
  end
@@ -85,7 +86,7 @@ class Bundler::Thor
85
86
  super(arg)
86
87
  end
87
88
 
88
- def parse(args) # rubocop:disable MethodLength
89
+ def parse(args) # rubocop:disable Metrics/MethodLength
89
90
  @pile = args.dup
90
91
  @is_treated_as_value = false
91
92
  @parsing_options = true
@@ -132,12 +133,38 @@ class Bundler::Thor
132
133
  end
133
134
 
134
135
  check_requirement! unless @disable_required_check
136
+ check_exclusive!
137
+ check_at_least_one!
135
138
 
136
139
  assigns = Bundler::Thor::CoreExt::HashWithIndifferentAccess.new(@assigns)
137
140
  assigns.freeze
138
141
  assigns
139
142
  end
140
143
 
144
+ def check_exclusive!
145
+ opts = @assigns.keys
146
+ # When option A and B are exclusive, if A and B are given at the same time,
147
+ # the diffrence of argument array size will decrease.
148
+ found = @exclusives.find{ |ex| (ex - opts).size < ex.size - 1 }
149
+ if found
150
+ names = names_to_switch_names(found & opts).map{|n| "'#{n}'"}
151
+ class_name = self.class.name.split("::").last.downcase
152
+ fail ExclusiveArgumentError, "Found exclusive #{class_name} #{names.join(", ")}"
153
+ end
154
+ end
155
+
156
+ def check_at_least_one!
157
+ opts = @assigns.keys
158
+ # When at least one is required of the options A and B,
159
+ # if the both options were not given, none? would be true.
160
+ found = @at_least_ones.find{ |one_reqs| one_reqs.none?{ |o| opts.include? o} }
161
+ if found
162
+ names = names_to_switch_names(found).map{|n| "'#{n}'"}
163
+ class_name = self.class.name.split("::").last.downcase
164
+ fail AtLeastOneRequiredArgumentError, "Not found at least one of required #{class_name} #{names.join(", ")}"
165
+ end
166
+ end
167
+
141
168
  def check_unknown!
142
169
  to_check = @stopped_parsing_after_extra_index ? @extra[0...@stopped_parsing_after_extra_index] : @extra
143
170
 
@@ -148,6 +175,17 @@ class Bundler::Thor
148
175
 
149
176
  protected
150
177
 
178
+ # Option names changes to swith name or human name
179
+ def names_to_switch_names(names = [])
180
+ @switches.map do |_, o|
181
+ if names.include? o.name
182
+ o.respond_to?(:switch_name) ? o.switch_name : o.human_name
183
+ else
184
+ nil
185
+ end
186
+ end.compact
187
+ end
188
+
151
189
  def assign_result!(option, result)
152
190
  if option.repeatable && option.type == :hash
153
191
  (@assigns[option.human_name] ||= {}).merge!(result)
@@ -194,7 +232,7 @@ class Bundler::Thor
194
232
  end
195
233
 
196
234
  def switch_option(arg)
197
- if match = no_or_skip?(arg) # rubocop:disable AssignmentInCondition
235
+ if match = no_or_skip?(arg) # rubocop:disable Lint/AssignmentInCondition
198
236
  @switches[arg] || @switches["--#{match}"]
199
237
  else
200
238
  @switches[arg]
@@ -41,7 +41,7 @@ instance_eval do
41
41
  def task(*)
42
42
  task = super
43
43
 
44
- if klass = Bundler::Thor::RakeCompat.rake_classes.last # rubocop:disable AssignmentInCondition
44
+ if klass = Bundler::Thor::RakeCompat.rake_classes.last # rubocop:disable Lint/AssignmentInCondition
45
45
  non_namespaced_name = task.name.split(":").last
46
46
 
47
47
  description = non_namespaced_name
@@ -59,7 +59,7 @@ instance_eval do
59
59
  end
60
60
 
61
61
  def namespace(name)
62
- if klass = Bundler::Thor::RakeCompat.rake_classes.last # rubocop:disable AssignmentInCondition
62
+ if klass = Bundler::Thor::RakeCompat.rake_classes.last # rubocop:disable Lint/AssignmentInCondition
63
63
  const_name = Bundler::Thor::Util.camel_case(name.to_s).to_sym
64
64
  klass.const_set(const_name, Class.new(Bundler::Thor))
65
65
  new_klass = klass.const_get(const_name)
@@ -2,12 +2,10 @@ require_relative "../thor"
2
2
  require_relative "group"
3
3
 
4
4
  require "yaml"
5
- require "digest/md5"
5
+ require "digest/sha2"
6
6
  require "pathname"
7
7
 
8
- class Bundler::Thor::Runner < Bundler::Thor #:nodoc: # rubocop:disable ClassLength
9
- autoload :OpenURI, "open-uri"
10
-
8
+ class Bundler::Thor::Runner < Bundler::Thor #:nodoc:
11
9
  map "-T" => :list, "-i" => :install, "-u" => :update, "-v" => :version
12
10
 
13
11
  def self.banner(command, all = false, subcommand = false)
@@ -25,7 +23,7 @@ class Bundler::Thor::Runner < Bundler::Thor #:nodoc: # rubocop:disable ClassLeng
25
23
  initialize_thorfiles(meth)
26
24
  klass, command = Bundler::Thor::Util.find_class_and_command_by_namespace(meth)
27
25
  self.class.handle_no_command_error(command, false) if klass.nil?
28
- klass.start(["-h", command].compact, :shell => shell)
26
+ klass.start(["-h", command].compact, shell: shell)
29
27
  else
30
28
  super
31
29
  end
@@ -40,30 +38,42 @@ class Bundler::Thor::Runner < Bundler::Thor #:nodoc: # rubocop:disable ClassLeng
40
38
  klass, command = Bundler::Thor::Util.find_class_and_command_by_namespace(meth)
41
39
  self.class.handle_no_command_error(command, false) if klass.nil?
42
40
  args.unshift(command) if command
43
- klass.start(args, :shell => shell)
41
+ klass.start(args, shell: shell)
44
42
  end
45
43
 
46
44
  desc "install NAME", "Install an optionally named Bundler::Thor file into your system commands"
47
- method_options :as => :string, :relative => :boolean, :force => :boolean
48
- def install(name) # rubocop:disable MethodLength
45
+ method_options as: :string, relative: :boolean, force: :boolean
46
+ def install(name) # rubocop:disable Metrics/MethodLength
49
47
  initialize_thorfiles
50
48
 
51
- # If a directory name is provided as the argument, look for a 'main.thor'
52
- # command in said directory.
53
- begin
54
- if File.directory?(File.expand_path(name))
55
- base = File.join(name, "main.thor")
56
- package = :directory
57
- contents = open(base, &:read)
58
- else
59
- base = name
60
- package = :file
61
- contents = open(name, &:read)
49
+ is_uri = name =~ %r{^https?\://}
50
+
51
+ if is_uri
52
+ base = name
53
+ package = :file
54
+ require "open-uri"
55
+ begin
56
+ contents = URI.open(name, &:read)
57
+ rescue OpenURI::HTTPError
58
+ raise Error, "Error opening URI '#{name}'"
59
+ end
60
+ else
61
+ # If a directory name is provided as the argument, look for a 'main.thor'
62
+ # command in said directory.
63
+ begin
64
+ if File.directory?(File.expand_path(name))
65
+ base = File.join(name, "main.thor")
66
+ package = :directory
67
+ contents = File.open(base, &:read)
68
+ else
69
+ base = name
70
+ package = :file
71
+ require "open-uri"
72
+ contents = URI.open(name, &:read)
73
+ end
74
+ rescue Errno::ENOENT
75
+ raise Error, "Error opening file '#{name}'"
62
76
  end
63
- rescue OpenURI::HTTPError
64
- raise Error, "Error opening URI '#{name}'"
65
- rescue Errno::ENOENT
66
- raise Error, "Error opening file '#{name}'"
67
77
  end
68
78
 
69
79
  say "Your Thorfile contains:"
@@ -84,16 +94,16 @@ class Bundler::Thor::Runner < Bundler::Thor #:nodoc: # rubocop:disable ClassLeng
84
94
  as = basename if as.empty?
85
95
  end
86
96
 
87
- location = if options[:relative] || name =~ %r{^https?://}
97
+ location = if options[:relative] || is_uri
88
98
  name
89
99
  else
90
100
  File.expand_path(name)
91
101
  end
92
102
 
93
103
  thor_yaml[as] = {
94
- :filename => Digest::MD5.hexdigest(name + as),
95
- :location => location,
96
- :namespaces => Bundler::Thor::Util.namespaces_in_content(contents, base)
104
+ filename: Digest::SHA256.hexdigest(name + as),
105
+ location: location,
106
+ namespaces: Bundler::Thor::Util.namespaces_in_content(contents, base)
97
107
  }
98
108
 
99
109
  save_yaml(thor_yaml)
@@ -154,14 +164,14 @@ class Bundler::Thor::Runner < Bundler::Thor #:nodoc: # rubocop:disable ClassLeng
154
164
  end
155
165
 
156
166
  desc "installed", "List the installed Bundler::Thor modules and commands"
157
- method_options :internal => :boolean
167
+ method_options internal: :boolean
158
168
  def installed
159
169
  initialize_thorfiles(nil, true)
160
170
  display_klasses(true, options["internal"])
161
171
  end
162
172
 
163
173
  desc "list [SEARCH]", "List the available thor commands (--substring means .*SEARCH)"
164
- method_options :substring => :boolean, :group => :string, :all => :boolean, :debug => :boolean
174
+ method_options substring: :boolean, group: :string, all: :boolean, debug: :boolean
165
175
  def list(search = "")
166
176
  initialize_thorfiles
167
177
 
@@ -303,7 +313,7 @@ private
303
313
  say shell.set_color(namespace, :blue, true)
304
314
  say "-" * namespace.size
305
315
 
306
- print_table(list, :truncate => true)
316
+ print_table(list, truncate: true)
307
317
  say
308
318
  end
309
319
  alias_method :display_tasks, :display_commands
@@ -1,8 +1,10 @@
1
+ require_relative "column_printer"
2
+ require_relative "table_printer"
3
+ require_relative "wrapped_printer"
4
+
1
5
  class Bundler::Thor
2
6
  module Shell
3
7
  class Basic
4
- DEFAULT_TERMINAL_WIDTH = 80
5
-
6
8
  attr_accessor :base
7
9
  attr_reader :padding
8
10
 
@@ -145,14 +147,14 @@ class Bundler::Thor
145
147
  # "yes".
146
148
  #
147
149
  def yes?(statement, color = nil)
148
- !!(ask(statement, color, :add_to_history => false) =~ is?(:yes))
150
+ !!(ask(statement, color, add_to_history: false) =~ is?(:yes))
149
151
  end
150
152
 
151
153
  # Make a question the to user and returns true if the user replies "n" or
152
154
  # "no".
153
155
  #
154
156
  def no?(statement, color = nil)
155
- !!(ask(statement, color, :add_to_history => false) =~ is?(:no))
157
+ !!(ask(statement, color, add_to_history: false) =~ is?(:no))
156
158
  end
157
159
 
158
160
  # Prints values in columns
@@ -161,16 +163,8 @@ class Bundler::Thor
161
163
  # Array[String, String, ...]
162
164
  #
163
165
  def print_in_columns(array)
164
- return if array.empty?
165
- colwidth = (array.map { |el| el.to_s.size }.max || 0) + 2
166
- array.each_with_index do |value, index|
167
- # Don't output trailing spaces when printing the last column
168
- if ((((index + 1) % (terminal_width / colwidth))).zero? && !index.zero?) || index + 1 == array.length
169
- stdout.puts value
170
- else
171
- stdout.printf("%-#{colwidth}s", value)
172
- end
173
- end
166
+ printer = ColumnPrinter.new(stdout)
167
+ printer.print(array)
174
168
  end
175
169
 
176
170
  # Prints a table.
@@ -181,58 +175,11 @@ class Bundler::Thor
181
175
  # ==== Options
182
176
  # indent<Integer>:: Indent the first column by indent value.
183
177
  # colwidth<Integer>:: Force the first column to colwidth spaces wide.
178
+ # borders<Boolean>:: Adds ascii borders.
184
179
  #
185
- def print_table(array, options = {}) # rubocop:disable MethodLength
186
- return if array.empty?
187
-
188
- formats = []
189
- indent = options[:indent].to_i
190
- colwidth = options[:colwidth]
191
- options[:truncate] = terminal_width if options[:truncate] == true
192
-
193
- formats << "%-#{colwidth + 2}s".dup if colwidth
194
- start = colwidth ? 1 : 0
195
-
196
- colcount = array.max { |a, b| a.size <=> b.size }.size
197
-
198
- maximas = []
199
-
200
- start.upto(colcount - 1) do |index|
201
- maxima = array.map { |row| row[index] ? row[index].to_s.size : 0 }.max
202
- maximas << maxima
203
- formats << if index == colcount - 1
204
- # Don't output 2 trailing spaces when printing the last column
205
- "%-s".dup
206
- else
207
- "%-#{maxima + 2}s".dup
208
- end
209
- end
210
-
211
- formats[0] = formats[0].insert(0, " " * indent)
212
- formats << "%s"
213
-
214
- array.each do |row|
215
- sentence = "".dup
216
-
217
- row.each_with_index do |column, index|
218
- maxima = maximas[index]
219
-
220
- f = if column.is_a?(Numeric)
221
- if index == row.size - 1
222
- # Don't output 2 trailing spaces when printing the last column
223
- "%#{maxima}s"
224
- else
225
- "%#{maxima}s "
226
- end
227
- else
228
- formats[index]
229
- end
230
- sentence << f % column.to_s
231
- end
232
-
233
- sentence = truncate(sentence, options[:truncate]) if options[:truncate]
234
- stdout.puts sentence
235
- end
180
+ def print_table(array, options = {}) # rubocop:disable Metrics/MethodLength
181
+ printer = TablePrinter.new(stdout, options)
182
+ printer.print(array)
236
183
  end
237
184
 
238
185
  # Prints a long string, word-wrapping the text to the current width of the
@@ -245,33 +192,8 @@ class Bundler::Thor
245
192
  # indent<Integer>:: Indent each line of the printed paragraph by indent value.
246
193
  #
247
194
  def print_wrapped(message, options = {})
248
- indent = options[:indent] || 0
249
- width = terminal_width - indent
250
- paras = message.split("\n\n")
251
-
252
- paras.map! do |unwrapped|
253
- words = unwrapped.split(" ")
254
- counter = words.first.length
255
- words.inject do |memo, word|
256
- word = word.gsub(/\n\005/, "\n").gsub(/\005/, "\n")
257
- counter = 0 if word.include? "\n"
258
- if (counter + word.length + 1) < width
259
- memo = "#{memo} #{word}"
260
- counter += (word.length + 1)
261
- else
262
- memo = "#{memo}\n#{word}"
263
- counter = word.length
264
- end
265
- memo
266
- end
267
- end.compact!
268
-
269
- paras.each do |para|
270
- para.split("\n").each do |line|
271
- stdout.puts line.insert(0, " " * indent)
272
- end
273
- stdout.puts unless para == paras.last
274
- end
195
+ printer = WrappedPrinter.new(stdout, options)
196
+ printer.print(message)
275
197
  end
276
198
 
277
199
  # Deals with file collision and returns true if the file should be
@@ -289,7 +211,7 @@ class Bundler::Thor
289
211
  loop do
290
212
  answer = ask(
291
213
  %[Overwrite #{destination}? (enter "h" for help) #{options}],
292
- :add_to_history => false
214
+ add_to_history: false
293
215
  )
294
216
 
295
217
  case answer
@@ -316,24 +238,11 @@ class Bundler::Thor
316
238
 
317
239
  say "Please specify merge tool to `THOR_MERGE` env."
318
240
  else
319
- say file_collision_help
241
+ say file_collision_help(block_given?)
320
242
  end
321
243
  end
322
244
  end
323
245
 
324
- # This code was copied from Rake, available under MIT-LICENSE
325
- # Copyright (c) 2003, 2004 Jim Weirich
326
- def terminal_width
327
- result = if ENV["THOR_COLUMNS"]
328
- ENV["THOR_COLUMNS"].to_i
329
- else
330
- unix? ? dynamic_width : DEFAULT_TERMINAL_WIDTH
331
- end
332
- result < 10 ? DEFAULT_TERMINAL_WIDTH : result
333
- rescue
334
- DEFAULT_TERMINAL_WIDTH
335
- end
336
-
337
246
  # Called if something goes wrong during the execution. This is used by Bundler::Thor
338
247
  # internally and should not be used inside your scripts. If something went
339
248
  # wrong, you can always raise an exception. If you raise a Bundler::Thor::Error, it
@@ -384,16 +293,21 @@ class Bundler::Thor
384
293
  end
385
294
  end
386
295
 
387
- def file_collision_help #:nodoc:
388
- <<-HELP
296
+ def file_collision_help(block_given) #:nodoc:
297
+ help = <<-HELP
389
298
  Y - yes, overwrite
390
299
  n - no, do not overwrite
391
300
  a - all, overwrite this and all others
392
301
  q - quit, abort
393
- d - diff, show the differences between the old and the new
394
302
  h - help, show this help
395
- m - merge, run merge tool
396
303
  HELP
304
+ if block_given
305
+ help << <<-HELP
306
+ d - diff, show the differences between the old and the new
307
+ m - merge, run merge tool
308
+ HELP
309
+ end
310
+ help
397
311
  end
398
312
 
399
313
  def show_diff(destination, content) #:nodoc:
@@ -411,46 +325,8 @@ class Bundler::Thor
411
325
  mute? || (base && base.options[:quiet])
412
326
  end
413
327
 
414
- # Calculate the dynamic width of the terminal
415
- def dynamic_width
416
- @dynamic_width ||= (dynamic_width_stty.nonzero? || dynamic_width_tput)
417
- end
418
-
419
- def dynamic_width_stty
420
- `stty size 2>/dev/null`.split[1].to_i
421
- end
422
-
423
- def dynamic_width_tput
424
- `tput cols 2>/dev/null`.to_i
425
- end
426
-
427
328
  def unix?
428
- RUBY_PLATFORM =~ /(aix|darwin|linux|(net|free|open)bsd|cygwin|solaris)/i
429
- end
430
-
431
- def truncate(string, width)
432
- as_unicode do
433
- chars = string.chars.to_a
434
- if chars.length <= width
435
- chars.join
436
- else
437
- chars[0, width - 3].join + "..."
438
- end
439
- end
440
- end
441
-
442
- if "".respond_to?(:encode)
443
- def as_unicode
444
- yield
445
- end
446
- else
447
- def as_unicode
448
- old = $KCODE
449
- $KCODE = "U"
450
- yield
451
- ensure
452
- $KCODE = old
453
- end
329
+ Terminal.unix?
454
330
  end
455
331
 
456
332
  def ask_simply(statement, color, options)