Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permit autoproj to perform configuration noninteractively by relying … #243

Merged
merged 1 commit into from
Mar 1, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 24 additions & 7 deletions lib/autoproj/build_option.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,18 +45,35 @@ def doc
end
end

# Return either the current value if it is not nil, or use
# a default value
#
# @return [value, Boolean] Current value, and flag whether this is a
# default value
def ensure_value(current_value)
if !current_value.nil?
return current_value.to_s, false
elsif options[:default]
return options[:default].to_str, true
else
return '', true
end
end

# Ask the user for the setting of this option
# by providing the current value as input and falling
# back to default values if needed
#
# @param [String] current_value the option's current value
# @param [String] doc a string to override the default option banner
def ask(current_value, doc = nil)
default_value =
if !current_value.nil? then current_value.to_s
elsif options[:default] then options[:default].to_str
else ''
end
value,_ = ensure_value(current_value)

STDOUT.print " #{doc || self.doc} [#{default_value}] "
STDOUT.print " #{doc || self.doc} [#{value}] "
STDOUT.flush
answer = STDIN.readline.chomp
if answer == ''
answer = default_value
answer = value
end
validate(answer)

Expand Down
1 change: 1 addition & 0 deletions lib/autoproj/cli/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ def validate_user_selection(user_selection, resolved_selection)
end

def validate_options(args, options)
ws.config.interactive = options[:interactive]
self.class.validate_options(args, options)
end

Expand Down
2 changes: 2 additions & 0 deletions lib/autoproj/cli/main.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ class Main < Thor
desc: 'enables or disables colored display (enabled by default if the terminal supports it)'
class_option :progress, type: :boolean, default: TTY::Color.color?,
desc: 'enables or disables progress display (enabled by default if the terminal supports it)'
class_option 'interactive', type: :boolean, default: nil,
desc: 'tell autoproj to run (non)interactively'

stop_on_unknown_option! :exec
check_unknown_options! except: :exec
Expand Down
60 changes: 49 additions & 11 deletions lib/autoproj/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ class Configuration
attr_reader :displayed_options
# The path to the underlying configuration file
attr_reader :path
# Whether the configuration should be performed interactively
# or not
attr_accessor :interactive

def initialize(path = nil)
@config = Hash.new
Expand All @@ -43,16 +46,24 @@ def reset_modified
@modified = false
end

# Deletes the current value for an option
# Deletes the current configuration for all options or the one specified
#
# The user will be asked for a new value next time the option is needed
# The user will be asked for a new value next time one of the reset
# options is needed
#
# @param [String] the option name
# @param [String] name the option name (or by default nil to reset all
# options)
# @return the deleted value
def reset(name)
@modified ||= config.has_key?(name)
config.delete(name)
overrides.delete(name)
def reset(name = nil)
if name
@modified ||= config.has_key?(name)
config.delete(name)
overrides.delete(name)
else
@config.clear
@overrides.clear
@modified = true
end
end

# Sets a configuration option
Expand Down Expand Up @@ -177,10 +188,18 @@ def configure(option_name)
if current_value = config[option_name]
current_value = current_value.first
end
value = opt.ask(current_value)
is_default = false
if interactive?
value = opt.ask(current_value, nil)
else
value, is_default = opt.ensure_value(current_value)
Autoproj.info " using: #{value} (noninteractive mode)"
end
@modified = true
config[option_name] = [value, true]
displayed_options[option_name] = value
if !is_default
config[option_name] = [value, true]
displayed_options[option_name] = value
end
value
else
raise ConfigError.new, "undeclared option '#{option_name}'"
Expand Down Expand Up @@ -440,6 +459,21 @@ def randomize_layout=(value)
set('randomize_layout', value, true)
end

# Returns true if the configuration should be performed interactively
#
# @return [Boolean]
# @see interactive=
def interactive?
if !interactive.nil?
return interactive
elsif ENV['AUTOPROJ_NONINTERACTIVE'] == '1'
return false
elsif has_value_for?("interactive")
return get('interactive')
end
true
end

DEFAULT_UTILITY_SETUP = Hash[
'doc' => true,
'test' => false]
Expand Down Expand Up @@ -545,7 +579,11 @@ def prefer_indep_over_os_packages?
def to_hash
result = Hash.new
@config.each do |key, (value, _)|
result[key] = value
if declared_options.include?(key)
result[key] = declared_options[key].ensure_value(value)
else
result[key] = value
end
end
overrides.each do |key, value|
result[key] = value
Expand Down
9 changes: 6 additions & 3 deletions lib/autoproj/test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,7 @@ def ws_create_os_package_resolver
os_package_manager: 'os')
end

def ws_create(dir = make_tmpdir)
def ws_create(dir = make_tmpdir, partial_config: false)
require 'autoproj/ops/main_config_switcher'
FileUtils.cp_r Ops::MainConfigSwitcher::MAIN_CONFIGURATION_TEMPLATE, File.join(dir, 'autoproj')
FileUtils.mkdir_p File.join(dir, '.autoproj')
Expand All @@ -280,8 +280,11 @@ def ws_create(dir = make_tmpdir)
@ws = Workspace.new(
dir, os_package_resolver: ws_os_package_resolver,
package_managers: ws_package_managers)
ws.config.set 'osdeps_mode', 'all'
ws.config.set 'apt_dpkg_update', true

if !partial_config
ws.config.set 'osdeps_mode', 'all'
ws.config.set 'apt_dpkg_update', true
end
ws.config.set 'GITHUB', 'http,ssh', true
ws.config.set 'GITORIOUS', 'http,ssh', true
ws.config.set 'gems_install_path', File.join(dir, 'gems')
Expand Down
10 changes: 8 additions & 2 deletions lib/autoproj/workspace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -236,10 +236,16 @@ def overrides_dir
File.join(config_dir, OVERRIDES_DIR)
end

# Load the configuration for this workspace from
# config_file_path
#
# @param [Boolean] reset Set to true to replace the configuration object,
# set to false to load into the existing
# @return [Configuration] configuration object
def load_config(reconfigure = false)
@config = Configuration.new(config_file_path)
if File.file?(config_file_path)
config.load(reconfigure: reconfigure)
config.reset
config.load(path: config_file_path, reconfigure: reconfigure)
if raw_vcs = config.get('manifest_source', nil)
manifest.vcs = VCSDefinition.from_raw(raw_vcs)
else
Expand Down
42 changes: 42 additions & 0 deletions test/cli/test_reconfigure.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
require 'autoproj/test'
require 'autoproj/cli/main'
require 'autoproj/cli/reconfigure'
require 'timeout'

module Autoproj
module CLI
describe Reconfigure do
attr_reader :ws
before do
option_name = "custom-configuration-option"
default_value = "option-defaultvalue"

@ws = ws_create(make_tmpdir, partial_config: true)
end
after do
Autoproj.verbose = false
end
describe "#reconfigure" do
def run_command(*args)
capture_subprocess_io do
ENV['AUTOPROJ_CURRENT_ROOT'] = ws.root_path.to_s
in_ws do
Main.start([*args,"--debug"], debug: true)
end
end
end

it "reconfigure should run interactively" do
assert_raises Timeout::Error do
Timeout.timeout(3) do
run_command 'reconfigure'
end
end
end
it "reconfigure should run non interactively" do
run_command 'reconfigure','--no-interactive'
end
end
end
end
end
79 changes: 79 additions & 0 deletions test/test_configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,85 @@ module Autoproj
refute @config.modified?
end
end
describe "#interactive" do
it "set interactive mode" do
@config.interactive = false
assert [email protected]?

@config.interactive = true
assert @config.interactive?
end

it "disables interactive configuration setting through config option" do
option_name = "custom-configuration-option"
default_value = "option-defaultvalue"
@config.declare(option_name,"string",default: default_value)

@config.interactive = false

Timeout.timeout(3) do
@config.configure(option_name)
end
assert @config.get(option_name) == default_value
end

it "disables interactive configuration setting through ENV" do
option_name = "custom-configuration-option"
default_value = "option-defaultvalue"
@config.declare(option_name,"string",default: default_value)

ENV['AUTOPROJ_NONINTERACTIVE'] = '1'

assert [email protected]?
begin
Timeout.timeout(3) do
@config.configure(option_name)
end
assert @config.get(option_name) == default_value
ensure
ENV.delete('AUTOPROJ_NONINTERACTIVE')
end
end
it "use interactive configuration by default" do
option_name = "custom-configuration-option"
default_value = "option-defaultvalue"
@config.declare(option_name,"string",default: default_value)
assert @config.interactive?
assert_raises Timeout::Error do
Timeout.timeout(3) do
@config.configure(option_name)
end
end
end
it "skip saving default value" do
option_a_name = "custom-configuration-option-a"
default_a_value = "option-a-defaultvalue"

option_b_name = "custom-configuration-option-b"
default_b_value = "option-b-default-value"
b_value = "option-b-value"

@config.declare(option_a_name,"string",default: default_a_value)
@config.declare(option_b_name,"string",default: default_b_value)

@config.interactive = false
@config.configure(option_a_name)
@config.set(option_b_name, b_value)
@config.configure(option_b_name)

assert [email protected]_value_for?(option_a_name)
assert @config.has_value_for?(option_b_name)

tempfile = Tempfile.new("skip-saving-config")
@config.save(tempfile)

loaded_config = Configuration.new(tempfile)
loaded_config.load
assert !loaded_config.has_value_for?(option_a_name)
assert loaded_config.has_value_for?(option_b_name)
assert loaded_config.get(option_b_name) == b_value
end
end
end
end

Expand Down
1 change: 1 addition & 0 deletions test/test_workspace.rb
Original file line number Diff line number Diff line change
Expand Up @@ -486,6 +486,7 @@ def create_test_executable(path = target_test_path)
flexmock(Autoproj::Configuration).new_instances.
should_receive(:source_dir).and_return(ws.root_dir)
assert_raises(ConfigError) do
ws.config = Configuration.new(ws.root_dir)
ws.load_config
end
end
Expand Down