diff --git a/CHANGELOG.md b/CHANGELOG.md index 74bc7dfa..362eeb03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -24,6 +24,8 @@ https://github.com/capistrano/capistrano/compare/v3.2.0...v3.2.1 * Changed asking question to more standard format (like common unix commandline tools) (@sponomarev) * Fixed typos in the README. (@sponomarev) * Added `keys` method to Configuration to allow introspection of configuration options. (@juanibiapina) + * The `ask` method now supports the `echo: false` option. (@mbrictson) + * Capistrano now depends on the `highline` gem. ## `3.2.0` diff --git a/README.md b/README.md index c4321746..30c24157 100644 --- a/README.md +++ b/README.md @@ -153,6 +153,11 @@ end Perfect, who needs telephones. +When using `ask` to get user input, you can pass `echo: false` to prevent the input from being displayed: + +```ruby +ask(:database_passsword, "default", echo: false) +``` ## Using password authentication diff --git a/capistrano.gemspec b/capistrano.gemspec index 4558e1d4..0fe2d29a 100644 --- a/capistrano.gemspec +++ b/capistrano.gemspec @@ -28,6 +28,7 @@ eos gem.add_dependency 'sshkit', '~> 1.3' gem.add_dependency 'rake', '>= 10.0.0' gem.add_dependency 'i18n' + gem.add_dependency 'highline' gem.add_development_dependency 'rspec' gem.add_development_dependency 'mocha' diff --git a/lib/capistrano/all.rb b/lib/capistrano/all.rb index 87dbc75b..40b1c5c6 100644 --- a/lib/capistrano/all.rb +++ b/lib/capistrano/all.rb @@ -1,6 +1,7 @@ require 'rake' require 'sshkit' require 'sshkit/dsl' +require 'highline' Rake.application.options.trace = true diff --git a/lib/capistrano/configuration.rb b/lib/capistrano/configuration.rb index a5f978e9..a7cf8a3b 100644 --- a/lib/capistrano/configuration.rb +++ b/lib/capistrano/configuration.rb @@ -15,8 +15,8 @@ module Capistrano end end - def ask(key, default=nil) - question = Question.new(self, key, default) + def ask(key, default=nil, options={}) + question = Question.new(self, key, default, options) set(key, question) end diff --git a/lib/capistrano/configuration/question.rb b/lib/capistrano/configuration/question.rb index ffd99605..ba8aa4fd 100644 --- a/lib/capistrano/configuration/question.rb +++ b/lib/capistrano/configuration/question.rb @@ -2,27 +2,23 @@ module Capistrano class Configuration class Question - def initialize(env, key, default) - @env, @key, @default = env, key, default + def initialize(env, key, default, options) + @env, @key, @default, @options = env, key, default, options end def call - ask_question - save_response + response = highline_ask(question) { |q| q.echo = echo? } + save_response(value_or_default(response)) end private - attr_reader :env, :key, :default + attr_reader :env, :key, :default, :options - def ask_question - $stdout.print question - end - - def save_response + def save_response(value) env.set(key, value) end - def value + def value_or_default(response) if response.empty? default else @@ -30,13 +26,19 @@ module Capistrano end end - def response - @response ||= $stdin.gets.chomp - end - def question I18n.t(:question, key: key, default_value: default, scope: :capistrano) end + + def echo? + (options || {}).fetch(:echo, true) + end + + def highline_ask(question, &block) + # For compatibility, we call #to_s to unwrap HighLine::String and + # return a regular String. + HighLine.new.ask(question, &block).to_s + end end end end diff --git a/lib/capistrano/dsl/env.rb b/lib/capistrano/dsl/env.rb index 6728bad9..fcae68fa 100644 --- a/lib/capistrano/dsl/env.rb +++ b/lib/capistrano/dsl/env.rb @@ -27,8 +27,8 @@ module Capistrano env.delete(key) end - def ask(key, value) - env.ask(key, value) + def ask(key, value, options={}) + env.ask(key, value, options) end def role(name, servers, options={}) diff --git a/spec/lib/capistrano/configuration/question_spec.rb b/spec/lib/capistrano/configuration/question_spec.rb index cf1220c5..40b847db 100644 --- a/spec/lib/capistrano/configuration/question_spec.rb +++ b/spec/lib/capistrano/configuration/question_spec.rb @@ -5,13 +5,14 @@ module Capistrano describe Question do - let(:question) { Question.new(env, key, default) } + let(:question) { Question.new(env, key, default, options) } let(:default) { :default } let(:key) { :branch } let(:env) { stub } + let(:options) { nil } describe '.new' do - it 'takes a key, default' do + it 'takes a key, default, options' do question end end @@ -47,6 +48,33 @@ module Capistrano end end + + describe 'highline behavior' do + let(:highline) { stub } + + before do + question.expects(:highline_ask).yields(highline).returns("answer") + env.expects(:set).with(key, "answer") + end + + context 'with no options' do + let(:options) { nil } + + it 'passes echo: true to HighLine' do + highline.expects(:"echo=").with(true) + question.call + end + end + + context 'with echo: false' do + let(:options) { { echo: false } } + + it 'passes echo: false to HighLine' do + highline.expects(:"echo=").with(false) + question.call + end + end + end end end diff --git a/spec/lib/capistrano/configuration_spec.rb b/spec/lib/capistrano/configuration_spec.rb index 42c37a2d..718f6046 100644 --- a/spec/lib/capistrano/configuration_spec.rb +++ b/spec/lib/capistrano/configuration_spec.rb @@ -138,14 +138,15 @@ module Capistrano describe 'asking' do let(:question) { stub } + let(:options) { Hash.new } before do - Configuration::Question.expects(:new).with(config, :branch, :default). + Configuration::Question.expects(:new).with(config, :branch, :default, options). returns(question) end it 'prompts for the value when fetching' do - config.ask(:branch, :default) + config.ask(:branch, :default, options) expect(config.fetch(:branch)).to eq question end end