Skip to content

Commit

Permalink
Permit autoproj to perform configuration noninteractively by relying …
Browse files Browse the repository at this point in the history
…on the default values
  • Loading branch information
2maz committed Feb 28, 2019
1 parent 8ab9481 commit ff8fc94
Show file tree
Hide file tree
Showing 7 changed files with 178 additions and 9 deletions.
11 changes: 8 additions & 3 deletions lib/autoproj/build_option.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ def doc
end
end

def ask(current_value, doc = nil)
def ask(current_value, doc = nil, interactive: true)
default_value =
if !current_value.nil? then current_value.to_s
elsif options[:default] then options[:default].to_str
Expand All @@ -54,9 +54,14 @@ def ask(current_value, doc = nil)

STDOUT.print " #{doc || self.doc} [#{default_value}] "
STDOUT.flush
answer = STDIN.readline.chomp
if answer == ''
if interactive
answer = STDIN.readline.chomp
if answer == ''
answer = default_value
end
else
answer = default_value
STDOUT.puts "\n using: #{default_value} (noninteractive mode)"
end
validate(answer)

Expand Down
4 changes: 3 additions & 1 deletion lib/autoproj/cli/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -176,11 +176,13 @@ def self.validate_options(args, options)
debug: false,
color: TTY::Color.color?,
progress: TTY::Color.color?,
parallel: nil
parallel: nil,
interactive: true

Autoproj.silent = options[:silent]
Autobuild.color = options[:color]
Autobuild.progress_display_enabled = options[:progress]
Autoproj.interactive = options[:interactive]

if options[:verbose]
Autoproj.verbose = true
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: true,
desc: 'tell autoproj to run (non)interactively'

stop_on_unknown_option! :exec
check_unknown_options! except: :exec
Expand Down
46 changes: 44 additions & 2 deletions lib/autoproj/configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,11 @@
require 'backports/2.4.0/true_class/dup'

module Autoproj
class << self
attr_accessor :interactive
end
@interactive = nil

# Class that does the handling of configuration options as well as
# loading/saving on disk
class Configuration
Expand All @@ -30,6 +35,9 @@ def initialize(path = nil)
@displayed_options = Hash.new
@path = path
@modified = false
# Set of options that should
# use the defaults
@use_default = Set.new
end

# Whether the configuration was changed since the last call to {#load}
Expand Down Expand Up @@ -177,7 +185,10 @@ def configure(option_name)
if current_value = config[option_name]
current_value = current_value.first
end
value = opt.ask(current_value)
value = opt.ask(current_value, nil, interactive: interactive?)
if !config.include?(option_name) && !interactive?
@use_default << option_name
end
@modified = true
config[option_name] = [value, true]
displayed_options[option_name] = value
Expand Down Expand Up @@ -215,7 +226,7 @@ def save(path = self.path, force: false)
Ops.atomic_write(path) do |io|
h = Hash.new
config.each do |key, value|
h[key] = value.first
h[key] = value.first unless use_default?(key)
end

io.write YAML.dump(h)
Expand Down Expand Up @@ -440,6 +451,37 @@ def randomize_layout=(value)
set('randomize_layout', value, true)
end

# Sets whether the configuration should be done interactively
# by asking the user, or non-interactively by using the provided default
# value of an option
#
# @return [Boolean]
# @see interactive?
def interactive=(flag)
set('interactive', flag, true)
end

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

# Returns whether a configuration option always fallbacks
# to the current default value of the option
def use_default?(option_name)
@use_default.include?(option_name)
end

DEFAULT_UTILITY_SETUP = Hash[
'doc' => true,
'test' => false]
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
44 changes: 44 additions & 0 deletions test/cli/test_reconfigure.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
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)
#@ws.config.declare(option_name,"string",default: default_value)
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
71 changes: 71 additions & 0 deletions test/test_configuration.rb
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,77 @@ module Autoproj
refute @config.modified?
end
end
describe "#interactive" do
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 !@config.interactive?
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 @config.has_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

0 comments on commit ff8fc94

Please sign in to comment.