rubygems-update 3.4.18 → 3.4.20
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +48 -0
- data/POLICIES.md +2 -2
- data/bundler/CHANGELOG.md +45 -0
- data/bundler/lib/bundler/build_metadata.rb +2 -2
- data/bundler/lib/bundler/cli/binstubs.rb +1 -1
- data/bundler/lib/bundler/cli/info.rb +1 -1
- data/bundler/lib/bundler/cli/install.rb +1 -1
- data/bundler/lib/bundler/cli/outdated.rb +1 -1
- data/bundler/lib/bundler/cli/platform.rb +7 -5
- data/bundler/lib/bundler/cli/update.rb +1 -0
- data/bundler/lib/bundler/definition.rb +25 -20
- data/bundler/lib/bundler/dsl.rb +1 -1
- data/bundler/lib/bundler/env.rb +1 -1
- data/bundler/lib/bundler/fetcher/base.rb +2 -2
- data/bundler/lib/bundler/fetcher/compact_index.rb +4 -8
- data/bundler/lib/bundler/fetcher/dependency.rb +1 -1
- data/bundler/lib/bundler/fetcher/downloader.rb +2 -0
- data/bundler/lib/bundler/fetcher/index.rb +1 -2
- data/bundler/lib/bundler/fetcher.rb +42 -31
- data/bundler/lib/bundler/friendly_errors.rb +1 -1
- data/bundler/lib/bundler/gem_helper.rb +3 -4
- data/bundler/lib/bundler/index.rb +62 -31
- data/bundler/lib/bundler/installer/parallel_installer.rb +1 -1
- data/bundler/lib/bundler/installer/standalone.rb +8 -1
- data/bundler/lib/bundler/lockfile_parser.rb +3 -15
- data/bundler/lib/bundler/man/bundle-add.1 +1 -1
- data/bundler/lib/bundler/man/bundle-binstubs.1 +1 -1
- data/bundler/lib/bundler/man/bundle-cache.1 +1 -1
- data/bundler/lib/bundler/man/bundle-check.1 +1 -1
- data/bundler/lib/bundler/man/bundle-clean.1 +1 -1
- data/bundler/lib/bundler/man/bundle-config.1 +1 -1
- data/bundler/lib/bundler/man/bundle-console.1 +1 -1
- data/bundler/lib/bundler/man/bundle-doctor.1 +1 -1
- data/bundler/lib/bundler/man/bundle-exec.1 +1 -1
- data/bundler/lib/bundler/man/bundle-gem.1 +1 -1
- data/bundler/lib/bundler/man/bundle-help.1 +1 -1
- data/bundler/lib/bundler/man/bundle-info.1 +3 -3
- data/bundler/lib/bundler/man/bundle-info.1.ronn +3 -3
- data/bundler/lib/bundler/man/bundle-init.1 +1 -1
- data/bundler/lib/bundler/man/bundle-inject.1 +1 -1
- data/bundler/lib/bundler/man/bundle-install.1 +1 -1
- data/bundler/lib/bundler/man/bundle-list.1 +1 -1
- data/bundler/lib/bundler/man/bundle-lock.1 +1 -1
- data/bundler/lib/bundler/man/bundle-open.1 +1 -1
- data/bundler/lib/bundler/man/bundle-outdated.1 +1 -1
- data/bundler/lib/bundler/man/bundle-platform.1 +1 -1
- data/bundler/lib/bundler/man/bundle-plugin.1 +1 -1
- data/bundler/lib/bundler/man/bundle-pristine.1 +1 -1
- data/bundler/lib/bundler/man/bundle-remove.1 +1 -1
- data/bundler/lib/bundler/man/bundle-show.1 +1 -1
- data/bundler/lib/bundler/man/bundle-update.1 +1 -1
- data/bundler/lib/bundler/man/bundle-version.1 +1 -1
- data/bundler/lib/bundler/man/bundle-viz.1 +1 -1
- data/bundler/lib/bundler/man/bundle.1 +1 -1
- data/bundler/lib/bundler/man/gemfile.5 +25 -1
- data/bundler/lib/bundler/man/gemfile.5.ronn +10 -0
- data/bundler/lib/bundler/plugin/index.rb +1 -1
- data/bundler/lib/bundler/plugin.rb +1 -1
- data/bundler/lib/bundler/resolver.rb +18 -3
- data/bundler/lib/bundler/retry.rb +1 -1
- data/bundler/lib/bundler/ruby_dsl.rb +27 -0
- data/bundler/lib/bundler/ruby_version.rb +2 -2
- data/bundler/lib/bundler/rubygems_integration.rb +1 -1
- data/bundler/lib/bundler/self_manager.rb +2 -0
- data/bundler/lib/bundler/settings.rb +37 -13
- data/bundler/lib/bundler/source/git/git_proxy.rb +14 -2
- data/bundler/lib/bundler/source/git.rb +7 -0
- data/bundler/lib/bundler/source/rubygems.rb +22 -25
- data/bundler/lib/bundler/source_list.rb +0 -4
- data/bundler/lib/bundler/templates/newgem/github/workflows/main.yml.tt +1 -1
- data/bundler/lib/bundler/ui/rg_proxy.rb +1 -1
- data/bundler/lib/bundler/version.rb +1 -1
- data/bundler/lib/bundler.rb +1 -1
- data/lib/rubygems/available_set.rb +1 -1
- data/lib/rubygems/basic_specification.rb +2 -2
- data/lib/rubygems/bundler_version_finder.rb +1 -1
- data/lib/rubygems/command.rb +16 -19
- data/lib/rubygems/commands/cert_command.rb +1 -1
- data/lib/rubygems/commands/dependency_command.rb +3 -4
- data/lib/rubygems/commands/owner_command.rb +8 -10
- data/lib/rubygems/commands/uninstall_command.rb +6 -7
- data/lib/rubygems/commands/unpack_command.rb +4 -6
- data/lib/rubygems/config_file.rb +1 -1
- data/lib/rubygems/core_ext/kernel_gem.rb +1 -1
- data/lib/rubygems/core_ext/kernel_warn.rb +4 -5
- data/lib/rubygems/dependency_installer.rb +8 -12
- data/lib/rubygems/deprecate.rb +2 -2
- data/lib/rubygems/gemcutter_utilities.rb +3 -4
- data/lib/rubygems/installer.rb +9 -11
- data/lib/rubygems/name_tuple.rb +1 -1
- data/lib/rubygems/package/tar_reader/entry.rb +18 -20
- data/lib/rubygems/package/tar_reader.rb +0 -5
- data/lib/rubygems/package.rb +11 -6
- data/lib/rubygems/query_utils.rb +1 -1
- data/lib/rubygems/request_set/gem_dependency_api.rb +1 -1
- data/lib/rubygems/request_set/lockfile/parser.rb +1 -1
- data/lib/rubygems/resolver/activation_request.rb +2 -4
- data/lib/rubygems/resolver/installed_specification.rb +1 -1
- data/lib/rubygems/resolver/local_specification.rb +1 -1
- data/lib/rubygems/s3_uri_signer.rb +1 -1
- data/lib/rubygems/security/trust_dir.rb +4 -6
- data/lib/rubygems/security.rb +1 -1
- data/lib/rubygems/source/local.rb +34 -37
- data/lib/rubygems/source.rb +2 -2
- data/lib/rubygems/source_list.rb +2 -2
- data/lib/rubygems/spec_fetcher.rb +29 -33
- data/lib/rubygems/specification.rb +36 -28
- data/lib/rubygems/specification_policy.rb +33 -32
- data/lib/rubygems/stub_specification.rb +13 -10
- data/lib/rubygems/uninstaller.rb +1 -1
- data/lib/rubygems/user_interaction.rb +4 -4
- data/lib/rubygems/util/licenses.rb +115 -0
- data/lib/rubygems/validator.rb +5 -7
- data/lib/rubygems.rb +6 -9
- data/rubygems-update.gemspec +4 -4
- data/test/rubygems/helper.rb +18 -20
- data/test/rubygems/test_gem.rb +4 -4
- data/test/rubygems/test_gem_commands_build_command.rb +2 -1
- data/test/rubygems/test_gem_commands_stale_command.rb +1 -1
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.lock +28 -12
- data/test/rubygems/test_gem_ext_cargo_builder/custom_name/ext/custom_name_lib/Cargo.toml +1 -1
- data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.lock +16 -14
- data/test/rubygems/test_gem_ext_cargo_builder/rust_ruby_example/Cargo.toml +1 -1
- data/test/rubygems/test_gem_indexer.rb +1 -1
- data/test/rubygems/test_gem_package.rb +117 -2
- data/test/rubygems/test_gem_package_tar_header.rb +7 -7
- data/test/rubygems/test_gem_package_tar_reader_entry.rb +53 -1
- data/test/rubygems/test_gem_package_tar_writer.rb +13 -13
- data/test/rubygems/test_gem_remote_fetcher.rb +21 -25
- data/test/rubygems/test_gem_requirement.rb +1 -1
- data/test/rubygems/test_gem_specification.rb +42 -6
- data/test/rubygems/test_gem_update_suggestion.rb +14 -20
- data/test/rubygems/test_require.rb +4 -6
- data/test/rubygems/utilities.rb +2 -2
- metadata +31 -5
@@ -1048,7 +1048,7 @@ class Gem::Specification < Gem::BasicSpecification
|
|
1048
1048
|
next if s.activated?
|
1049
1049
|
s.contains_requirable_file? path
|
1050
1050
|
end
|
1051
|
-
stub
|
1051
|
+
stub&.to_spec
|
1052
1052
|
end
|
1053
1053
|
|
1054
1054
|
def self.find_active_stub_by_path(path)
|
@@ -1301,10 +1301,20 @@ class Gem::Specification < Gem::BasicSpecification
|
|
1301
1301
|
Gem.load_yaml
|
1302
1302
|
|
1303
1303
|
yaml_set = false
|
1304
|
+
retry_count = 0
|
1304
1305
|
|
1305
1306
|
array = begin
|
1306
1307
|
Marshal.load str
|
1307
1308
|
rescue ArgumentError => e
|
1309
|
+
# Avoid an infinite retry loop when the argument error has nothing to do
|
1310
|
+
# with the classes not being defined.
|
1311
|
+
# 1 retry each allowed in case all 3 of
|
1312
|
+
# - YAML
|
1313
|
+
# - YAML::Syck::DefaultKey
|
1314
|
+
# - YAML::PrivateType
|
1315
|
+
# need to be defined
|
1316
|
+
raise if retry_count >= 3
|
1317
|
+
|
1308
1318
|
#
|
1309
1319
|
# Some very old marshaled specs included references to `YAML::PrivateType`
|
1310
1320
|
# and `YAML::Syck::DefaultKey` constants due to bugs in the old emitter
|
@@ -1322,11 +1332,12 @@ class Gem::Specification < Gem::BasicSpecification
|
|
1322
1332
|
if message.include?("YAML::Syck::")
|
1323
1333
|
YAML.const_set "Syck", YAML unless YAML.const_defined?(:Syck)
|
1324
1334
|
|
1325
|
-
YAML::Syck.const_set "DefaultKey", Class.new if message.include?("YAML::Syck::DefaultKey")
|
1326
|
-
elsif message.include?("YAML::PrivateType")
|
1335
|
+
YAML::Syck.const_set "DefaultKey", Class.new if message.include?("YAML::Syck::DefaultKey") && !YAML::Syck.const_defined?(:DefaultKey)
|
1336
|
+
elsif message.include?("YAML::PrivateType") && !YAML.const_defined?(:PrivateType)
|
1327
1337
|
YAML.const_set "PrivateType", Class.new
|
1328
1338
|
end
|
1329
1339
|
|
1340
|
+
retry_count += 1
|
1330
1341
|
retry
|
1331
1342
|
ensure
|
1332
1343
|
Object.__send__(:remove_const, "YAML") if yaml_set
|
@@ -1623,8 +1634,8 @@ class Gem::Specification < Gem::BasicSpecification
|
|
1623
1634
|
# we need to fresh build when same name and version of default gems
|
1624
1635
|
return if self.class.find_by_full_name(full_name)&.default_gem?
|
1625
1636
|
return if File.exist? gem_build_complete_path
|
1626
|
-
return
|
1627
|
-
return
|
1637
|
+
return unless File.writable?(base_dir)
|
1638
|
+
return unless File.exist?(File.join(base_dir, "extensions"))
|
1628
1639
|
|
1629
1640
|
begin
|
1630
1641
|
# We need to require things in $LOAD_PATH without looking for the
|
@@ -1642,7 +1653,7 @@ class Gem::Specification < Gem::BasicSpecification
|
|
1642
1653
|
builder.build_extensions
|
1643
1654
|
end
|
1644
1655
|
ensure
|
1645
|
-
ui
|
1656
|
+
ui&.close
|
1646
1657
|
Gem::Specification.unresolved_deps.replace unresolved_deps
|
1647
1658
|
end
|
1648
1659
|
end
|
@@ -1811,13 +1822,12 @@ class Gem::Specification < Gem::BasicSpecification
|
|
1811
1822
|
Gem::Specification.each do |spec|
|
1812
1823
|
deps = check_dev ? spec.dependencies : spec.runtime_dependencies
|
1813
1824
|
deps.each do |dep|
|
1814
|
-
|
1815
|
-
|
1816
|
-
|
1817
|
-
|
1818
|
-
end
|
1819
|
-
out << [spec, dep, sats]
|
1825
|
+
next unless self.satisfies_requirement?(dep)
|
1826
|
+
sats = []
|
1827
|
+
find_all_satisfiers(dep) do |sat|
|
1828
|
+
sats << sat
|
1820
1829
|
end
|
1830
|
+
out << [spec, dep, sats]
|
1821
1831
|
end
|
1822
1832
|
end
|
1823
1833
|
out
|
@@ -2256,21 +2266,20 @@ class Gem::Specification < Gem::BasicSpecification
|
|
2256
2266
|
attributes.each do |attr_name|
|
2257
2267
|
current_value = self.send attr_name
|
2258
2268
|
current_value = current_value.sort if %i[files test_files].include? attr_name
|
2259
|
-
|
2260
|
-
|
2269
|
+
next unless current_value != default_value(attr_name) ||
|
2270
|
+
self.class.required_attribute?(attr_name)
|
2261
2271
|
|
2262
|
-
|
2272
|
+
q.text "s.#{attr_name} = "
|
2263
2273
|
|
2264
|
-
|
2265
|
-
|
2266
|
-
|
2267
|
-
q.text "Time.utc(#{current_value.year}, #{current_value.month}, #{current_value.day})"
|
2268
|
-
else
|
2269
|
-
q.pp current_value
|
2270
|
-
end
|
2274
|
+
if attr_name == :date
|
2275
|
+
current_value = current_value.utc
|
2271
2276
|
|
2272
|
-
q.
|
2277
|
+
q.text "Time.utc(#{current_value.year}, #{current_value.month}, #{current_value.day})"
|
2278
|
+
else
|
2279
|
+
q.pp current_value
|
2273
2280
|
end
|
2281
|
+
|
2282
|
+
q.breakable
|
2274
2283
|
end
|
2275
2284
|
end
|
2276
2285
|
end
|
@@ -2612,11 +2621,10 @@ class Gem::Specification < Gem::BasicSpecification
|
|
2612
2621
|
ensure
|
2613
2622
|
trail.pop
|
2614
2623
|
end
|
2615
|
-
|
2616
|
-
|
2617
|
-
|
2618
|
-
|
2619
|
-
end
|
2624
|
+
next if result == :next
|
2625
|
+
spec_name = dep_spec.name
|
2626
|
+
dep_spec.traverse(trail, visited, &block) unless
|
2627
|
+
trail.any? {|s| s.name == spec_name }
|
2620
2628
|
end
|
2621
2629
|
end
|
2622
2630
|
ensure
|
@@ -127,7 +127,7 @@ class Gem::SpecificationPolicy
|
|
127
127
|
|
128
128
|
metadata.each do |key, value|
|
129
129
|
entry = "metadata['#{key}']"
|
130
|
-
|
130
|
+
unless key.is_a?(String)
|
131
131
|
error "metadata keys must be a String"
|
132
132
|
end
|
133
133
|
|
@@ -135,7 +135,7 @@ class Gem::SpecificationPolicy
|
|
135
135
|
error "metadata key is too large (#{key.size} > 128)"
|
136
136
|
end
|
137
137
|
|
138
|
-
|
138
|
+
unless value.is_a?(String)
|
139
139
|
error "#{entry} value must be a String"
|
140
140
|
end
|
141
141
|
|
@@ -143,10 +143,9 @@ class Gem::SpecificationPolicy
|
|
143
143
|
error "#{entry} value is too large (#{value.size} > 1024)"
|
144
144
|
end
|
145
145
|
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
end
|
146
|
+
next unless METADATA_LINK_KEYS.include? key
|
147
|
+
if value !~ VALID_URI_PATTERN
|
148
|
+
error "#{entry} has invalid link: #{value.inspect}"
|
150
149
|
end
|
151
150
|
end
|
152
151
|
end
|
@@ -198,28 +197,27 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
198
197
|
!version.prerelease? && (op == ">" || op == ">=")
|
199
198
|
end
|
200
199
|
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
segments = dep_version.segments
|
200
|
+
next unless open_ended
|
201
|
+
op, dep_version = dep.requirement.requirements.first
|
205
202
|
|
206
|
-
|
203
|
+
segments = dep_version.segments
|
207
204
|
|
208
|
-
|
209
|
-
" use a bounded requirement, such as '~> x.y'"
|
210
|
-
else
|
211
|
-
bugfix = if op == ">"
|
212
|
-
", '> #{dep_version}'"
|
213
|
-
elsif op == ">=" && base != segments
|
214
|
-
", '>= #{dep_version}'"
|
215
|
-
end
|
205
|
+
base = segments.first 2
|
216
206
|
|
217
|
-
|
218
|
-
|
207
|
+
recommendation = if (op == ">" || op == ">=") && segments == [0]
|
208
|
+
" use a bounded requirement, such as '~> x.y'"
|
209
|
+
else
|
210
|
+
bugfix = if op == ">"
|
211
|
+
", '> #{dep_version}'"
|
212
|
+
elsif op == ">=" && base != segments
|
213
|
+
", '>= #{dep_version}'"
|
219
214
|
end
|
220
215
|
|
221
|
-
|
216
|
+
" if #{dep.name} is semantically versioned, use:\n" \
|
217
|
+
" add_#{dep.type}_dependency '#{dep.name}', '~> #{base.join '.'}'#{bugfix}"
|
222
218
|
end
|
219
|
+
|
220
|
+
warning_messages << ["open-ended dependency on #{dep} is not recommended", recommendation].join("\n") + "\n"
|
223
221
|
end
|
224
222
|
if warning_messages.any?
|
225
223
|
warning_messages.each {|warning_message| warning warning_message }
|
@@ -345,7 +343,7 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
345
343
|
String
|
346
344
|
end
|
347
345
|
|
348
|
-
unless Array === val && val.all? {|x| x.
|
346
|
+
unless Array === val && val.all? {|x| x.is_a?(klass) || (field == :licenses && x.nil?) }
|
349
347
|
error "#{field} must be an Array of #{klass}"
|
350
348
|
end
|
351
349
|
end
|
@@ -360,6 +358,8 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
360
358
|
licenses = @specification.licenses
|
361
359
|
|
362
360
|
licenses.each do |license|
|
361
|
+
next if license.nil?
|
362
|
+
|
363
363
|
if license.length > 64
|
364
364
|
error "each license must be 64 characters or less"
|
365
365
|
end
|
@@ -370,20 +370,21 @@ duplicate dependency on #{dep}, (#{prev.requirement}) use:
|
|
370
370
|
licenses = @specification.licenses
|
371
371
|
|
372
372
|
licenses.each do |license|
|
373
|
-
if
|
374
|
-
|
375
|
-
|
373
|
+
next if Gem::Licenses.match?(license) || license.nil?
|
374
|
+
suggestions = Gem::Licenses.suggestions(license)
|
375
|
+
message = <<-WARNING
|
376
376
|
license value '#{license}' is invalid. Use a license identifier from
|
377
|
-
http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
377
|
+
http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license,
|
378
|
+
or set it to nil if you don't want to specify a license.
|
379
|
+
WARNING
|
380
|
+
message += "Did you mean #{suggestions.map {|s| "'#{s}'" }.join(', ')}?\n" unless suggestions.nil?
|
381
|
+
warning(message)
|
382
382
|
end
|
383
383
|
|
384
384
|
warning <<-WARNING if licenses.empty?
|
385
385
|
licenses is empty, but is recommended. Use a license identifier from
|
386
|
-
http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license
|
386
|
+
http://spdx.org/licenses or '#{Gem::Licenses::NONSTANDARD}' for a nonstandard license,
|
387
|
+
or set it to nil if you don't want to specify a license.
|
387
388
|
WARNING
|
388
389
|
end
|
389
390
|
|
@@ -35,7 +35,7 @@ class Gem::StubSpecification < Gem::BasicSpecification
|
|
35
35
|
|
36
36
|
def initialize(data, extensions)
|
37
37
|
parts = data[PREFIX.length..-1].split(" ", 4)
|
38
|
-
@name = parts[0]
|
38
|
+
@name = -parts[0]
|
39
39
|
@version = if Gem::Version.correct?(parts[1])
|
40
40
|
Gem::Version.new(parts[1])
|
41
41
|
else
|
@@ -112,20 +112,23 @@ class Gem::StubSpecification < Gem::BasicSpecification
|
|
112
112
|
saved_lineno = $.
|
113
113
|
|
114
114
|
Gem.open_file loaded_from, OPEN_MODE do |file|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
115
|
+
file.readline # discard encoding line
|
116
|
+
stubline = file.readline
|
117
|
+
if stubline.start_with?(PREFIX)
|
118
|
+
extline = file.readline
|
119
|
+
|
120
|
+
extensions =
|
121
|
+
if extline.delete_prefix!(PREFIX)
|
122
|
+
extline.chomp!
|
123
|
+
extline.split "\0"
|
121
124
|
else
|
122
125
|
StubLine::NO_EXTENSIONS
|
123
126
|
end
|
124
127
|
|
125
|
-
|
126
|
-
|
127
|
-
rescue EOFError
|
128
|
+
stubline.chomp! # readline(chomp: true) allocates 3x as much as .readline.chomp!
|
129
|
+
@data = StubLine.new stubline, extensions
|
128
130
|
end
|
131
|
+
rescue EOFError
|
129
132
|
end
|
130
133
|
ensure
|
131
134
|
$. = saved_lineno
|
data/lib/rubygems/uninstaller.rb
CHANGED
@@ -135,7 +135,7 @@ class Gem::Uninstaller
|
|
135
135
|
|
136
136
|
if index == list.size
|
137
137
|
remove_all list
|
138
|
-
elsif index >= 0 && index < list.size
|
138
|
+
elsif index && index >= 0 && index < list.size
|
139
139
|
uninstall_gem list[index]
|
140
140
|
else
|
141
141
|
say "Error: must enter a number [1-#{list.size + 1}]"
|
@@ -286,13 +286,13 @@ class Gem::StreamUI
|
|
286
286
|
# Ask a question. Returns an answer if connected to a tty, nil otherwise.
|
287
287
|
|
288
288
|
def ask(question)
|
289
|
-
return nil
|
289
|
+
return nil unless tty?
|
290
290
|
|
291
291
|
@outs.print(question + " ")
|
292
292
|
@outs.flush
|
293
293
|
|
294
294
|
result = @ins.gets
|
295
|
-
result
|
295
|
+
result&.chomp!
|
296
296
|
result
|
297
297
|
end
|
298
298
|
|
@@ -300,14 +300,14 @@ class Gem::StreamUI
|
|
300
300
|
# Ask for a password. Does not echo response to terminal.
|
301
301
|
|
302
302
|
def ask_for_password(question)
|
303
|
-
return nil
|
303
|
+
return nil unless tty?
|
304
304
|
|
305
305
|
@outs.print(question, " ")
|
306
306
|
@outs.flush
|
307
307
|
|
308
308
|
password = _gets_noecho
|
309
309
|
@outs.puts
|
310
|
-
password
|
310
|
+
password&.chomp!
|
311
311
|
password
|
312
312
|
end
|
313
313
|
|