Class: Autoproj::Configuration

Inherits:
Object
  • Object
show all
Defined in:
lib/autoproj/configuration.rb

Overview

Class that does the handling of configuration options as well as loading/saving on disk

Constant Summary collapse

DEFAULT_UTILITY_SETUP =

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path = nil) ⇒ Configuration

Returns a new instance of Configuration.



29
30
31
32
33
34
35
36
# File 'lib/autoproj/configuration.rb', line 29

def initialize(path = nil)
    @config = Hash.new
    @overrides = Hash.new
    @declared_options = Hash.new
    @displayed_options = Hash.new
    @path = path
    @modified = false
end

Instance Attribute Details

#configObject (readonly)

Set of currently known options

These are the values that are going to be saved on disk. Use #override to change a value without changing the saved configuration file.



16
17
18
# File 'lib/autoproj/configuration.rb', line 16

def config
  @config
end

#declared_optionsObject (readonly)

Set of options that have been declared with #declare



20
21
22
# File 'lib/autoproj/configuration.rb', line 20

def declared_options
  @declared_options
end

#displayed_optionsObject (readonly)

The options that have already been shown to the user



22
23
24
# File 'lib/autoproj/configuration.rb', line 22

def displayed_options
  @displayed_options
end

#interactiveObject

Whether the configuration should be performed interactively or not



27
28
29
# File 'lib/autoproj/configuration.rb', line 27

def interactive
  @interactive
end

#overridesObject (readonly)

Set of overriden option values that won’t get written to file



18
19
20
# File 'lib/autoproj/configuration.rb', line 18

def overrides
  @overrides
end

#pathObject (readonly)

The path to the underlying configuration file



24
25
26
# File 'lib/autoproj/configuration.rb', line 24

def path
  @path
end

Class Method Details

.gems_path_suffixObject

The Ruby platform and version-specific subdirectory used by bundler and rubygem



272
273
274
# File 'lib/autoproj/configuration.rb', line 272

def self.gems_path_suffix
    Ops::Install.gems_path_suffix
end

Instance Method Details

#apply_autobuild_configurationObject



347
348
349
350
351
352
353
354
355
356
# File 'lib/autoproj/configuration.rb', line 347

def apply_autobuild_configuration
    if has_value_for?("autobuild")
        params = get("autobuild")
        if params.kind_of?(Hash)
            params.each do |k, v|
                Autobuild.send("#{k}=", v)
            end
        end
    end
end

#build_dirString

Defines the temporary area in which packages should put their build files

If absolute, it is handled as #prefix_dir: the package name will be appended to it. If relative, it is relative to the package’s source directory

The default is “build”

Returns:

  • (String)


407
408
409
# File 'lib/autoproj/configuration.rb', line 407

def build_dir
    get("build", "build")
end

#bundler_versionObject



343
344
345
# File 'lib/autoproj/configuration.rb', line 343

def bundler_version
    get "bundler_version", nil
end

#configure(option_name) ⇒ Object

Configures a given option by asking the user about its desired value

Returns:

  • (Object)

    the new option value

Raises:

  • ConfigError if the option is not declared



179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/autoproj/configuration.rb', line 179

def configure(option_name)
    if (opt = declared_options[option_name])
        if (current_value = config[option_name])
            current_value = current_value.first
        end
        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
        if is_default
            value = opt.validate(value)
        else
            config[option_name] = [value, true]
            displayed_options[option_name] = value
        end
        value
    else
        raise ConfigError.new, "undeclared option '#{option_name}'"
    end
end

#declare(name, type, **options, &validator) ⇒ Object

Declare an option

This declares a given option, thus allowing to ask the user about it

Parameters:

  • name (String)

    the option name

  • type (String)

    the option type (can be ‘boolean’ or ‘string’)

  • options (Hash)

    a customizable set of options

Options Hash (**options):

  • :short_doc (String)

    the one-line documentation string that is displayed when the user does not have to be queried. It defaults to the first line of :doc if not given

  • :doc (String)

    the full option documentation. It is displayed to the user when he is explicitly asked about the option’s value

  • :default (Object)

    the default value this option should take

  • :possible_values (Array)

    list of possible values (only if the option type is ‘string’)

  • :lowercase (Boolean) — default: false

    whether the user’s input should be converted to lowercase before it gets validated / saved.

  • :uppercase (Boolean) — default: false

    whether the user’s input should be converted to uppercase before it gets validated / saved.



165
166
167
# File 'lib/autoproj/configuration.rb', line 165

def declare(name, type, **options, &validator)
    declared_options[name] = BuildOption.new(name, type, options, validator)
end

#declared?(name) ⇒ Boolean

Checks if an option exists

Returns:

  • (Boolean)


171
172
173
# File 'lib/autoproj/configuration.rb', line 171

def declared?(name)
    declared_options.has_key?(name)
end

#each_reused_autoproj_installation(&block) ⇒ Object



238
239
240
241
242
243
244
# File 'lib/autoproj/configuration.rb', line 238

def each_reused_autoproj_installation(&block)
    if has_value_for?("reused_autoproj_installations")
        get("reused_autoproj_installations").each(&block)
    else
        [].each(&block)
    end
end

#gems_gem_homeString

The GEM_HOME into which the workspace gems are installed

Parameters:

  • ws (Workspace)

    the workspace whose gems are being considered

Returns:

  • (String)


296
297
298
# File 'lib/autoproj/configuration.rb', line 296

def gems_gem_home
    File.join(gems_install_path, self.class.gems_path_suffix)
end

#gems_install_pathString

The gem install root into which the workspace gems are installed

Note that while this setting is separated from the other gems path, the only way to reliably isolate the gems of an autoproj workspace is to separate both the autoproj gems and the workspace gems. This is why there are only –public and –private settings in autoproj_install

The gems are actually installed under a platform and version-specific subdirectory (returned by #gems_path_suffix)

Parameters:

  • ws (Workspace)

    the workspace whose gems are being considered

Returns:

  • (String)


288
289
290
# File 'lib/autoproj/configuration.rb', line 288

def gems_install_path
    get("gems_install_path")
end

#get(key, *default_value) ⇒ Object

Get the value for a given option



109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
# File 'lib/autoproj/configuration.rb', line 109

def get(key, *default_value)
    return overrides[key].dup if overrides.has_key?(key)

    has_value = config.has_key?(key)
    value, validated = config[key]

    if !declared?(key)
        if has_value
            value.dup
        elsif default_value.empty?
            raise ConfigError, "undeclared option '#{key}'"
        else
            default_value.first.dup
        end
    elsif validated
        doc = declared_options[key].short_doc
        doc = "#{doc}:" if doc[-1, 1] != "?"
        displayed_options[key] = value
        value.dup
    else
        configure(key).dup
    end
end

#has_value_for?(name) ⇒ Boolean

Tests whether a value is set for the given option name

Returns:

  • (Boolean)


104
105
106
# File 'lib/autoproj/configuration.rb', line 104

def has_value_for?(name)
    config.has_key?(name) || overrides.has_key?(name)
end

#import_log_enabled=(value) ⇒ Object



250
251
252
# File 'lib/autoproj/configuration.rb', line 250

def import_log_enabled=(value)
    set("import_log_enabled", !!value)
end

#import_log_enabled?Boolean

Returns:

  • (Boolean)


246
247
248
# File 'lib/autoproj/configuration.rb', line 246

def import_log_enabled?
    get("import_log_enabled", true)
end

#importer_cache_dirObject

A cache directory for autobuild’s importers



359
360
361
# File 'lib/autoproj/configuration.rb', line 359

def importer_cache_dir
    get("importer_cache_dir", nil)
end

#importer_cache_dir=(path) ⇒ Object

Set import and gem cache directory



364
365
366
# File 'lib/autoproj/configuration.rb', line 364

def importer_cache_dir=(path)
    set("importer_cache_dir", path, true)
end

#interactive?Boolean

Returns true if the configuration should be performed interactively

Returns:

  • (Boolean)

See Also:



462
463
464
465
466
467
468
469
470
471
472
# File 'lib/autoproj/configuration.rb', line 462

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

#load(path: self.path, reconfigure: false) ⇒ Object



204
205
206
207
208
209
210
211
212
213
# File 'lib/autoproj/configuration.rb', line 204

def load(path: self.path, reconfigure: false)
    current_keys = @config.keys
    return unless (h = YAML.load(File.read(path)))

    h.each do |key, value|
        current_keys.delete(key)
        set(key, value, !reconfigure)
    end
    @modified = false if current_keys.empty?
end

#load_config_once(filename, config_dir: Autoproj.workspace.config_dir) ⇒ Object

Allows to load a seed-config.yml file (also from a buildconf repository) rather than providing it before checkout using the –seed-config paramater of the autoproj_bootstrap script this allows to bootstrap with –no-interactive and still apply a custom config e.g. in CI/CD The call to this function has to be in the init.rb of the buildconf BEFORE any other config option, e.g. the git server configuration settings The filename parameter is the name of the config seed yml file in the repository



612
613
614
615
616
617
618
619
620
# File 'lib/autoproj/configuration.rb', line 612

def load_config_once(filename, config_dir: Autoproj.workspace.config_dir)
    seed_config = File.expand_path(filename, config_dir)

    return if get("default_config_applied_#{seed_config}", false)

    Autoproj.message "loading seed config #{seed_config}"
    load path: seed_config
    set "default_config_applied_#{seed_config}", true, true
end

#load_config_once_with_permission(filename, default: "yes", config_dir: Autoproj.workspace.config_dir) ⇒ Object

Similar to load_config_once but asks the user if the default config should be applied



623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
# File 'lib/autoproj/configuration.rb', line 623

def load_config_once_with_permission(filename, default: "yes", config_dir: Autoproj.workspace.config_dir)
    seed_config = File.expand_path(filename, config_dir)
    # only run this code if config has not beed applied already (don't run when reconfiguring)
    return if has_value_for?("use_default_config_#{seed_config}")

    declare "use_default_config_#{seed_config}",
            "boolean",
            default: default,
            doc: ["Should the default workspace config be used?",
                  "This buildconf denines a default configuration in the buildconf (#{seed_config})",
                  "Should it be applied?"]
    if get("use_default_config_#{seed_config}")
        load_config_once(filename, config_dir: config_dir)
    end
end

#merge(conf) ⇒ Object



575
576
577
# File 'lib/autoproj/configuration.rb', line 575

def merge(conf)
    config.merge!(conf.config)
end

#modified?Boolean

Whether the configuration was changed since the last call to #load or #save

Returns:

  • (Boolean)


40
41
42
# File 'lib/autoproj/configuration.rb', line 40

def modified?
    @modified
end

#override(option_name, value) ⇒ Object

Override a known option value

The new value will not be saved to disk, unlike with #set



88
89
90
# File 'lib/autoproj/configuration.rb', line 88

def override(option_name, value)
    overrides[option_name] = value
end

#parallel_build_levelObject



254
255
256
# File 'lib/autoproj/configuration.rb', line 254

def parallel_build_level
    get("parallel_build_level", nil) || Autobuild.parallel_build_level
end

#parallel_build_level=(level) ⇒ Object



258
259
260
261
# File 'lib/autoproj/configuration.rb', line 258

def parallel_build_level=(level)
    set("parallel_build_level", level)
    Autobuild.parallel_build_level = level
end

#parallel_import_levelObject



263
264
265
# File 'lib/autoproj/configuration.rb', line 263

def parallel_import_level
    get("parallel_import_level", 10)
end

#parallel_import_level=(level) ⇒ Object



267
268
269
# File 'lib/autoproj/configuration.rb', line 267

def parallel_import_level=(level)
    set("parallel_import_level", level)
end

#prefer_indep_over_os_packages?Boolean

Whether the OS package handler should prefer installing OS-independent packages (as e.g. RubyGems) as opposed to the binary packages equivalent (e.g. thor as a gem vs. thor as the ruby-thor Ubuntu package)

This is false by default

Returns:

  • (Boolean)


585
586
587
# File 'lib/autoproj/configuration.rb', line 585

def prefer_indep_over_os_packages?
    get("prefer_indep_over_os_packages", false)
end

#prefix_dirString

The directory in which packages will be installed.

If it is a relative path, it is relative to the root dir of the installation.

The default is “install”

Returns:

  • (String)


381
382
383
# File 'lib/autoproj/configuration.rb', line 381

def prefix_dir
    get("prefix", "install")
end

#prefix_dir=(path) ⇒ Object

Sets the directory in which packages will be installed



369
370
371
# File 'lib/autoproj/configuration.rb', line 369

def prefix_dir=(path)
    set("prefix", path, true)
end

#randomize_layout=(value) ⇒ Boolean

Sets whether the layout should be randomized

Returns:

  • (Boolean)

See Also:



454
455
456
# File 'lib/autoproj/configuration.rb', line 454

def randomize_layout=(value)
    set("randomize_layout", value, true)
end

#randomize_layout?Boolean

Returns true if packages and prefixes should be auto-generated, based on the SHA of the package names. This is meant to be used for build services that want to check that dependencies are properly set

The default is false (disabled)

Returns:

  • (Boolean)


446
447
448
# File 'lib/autoproj/configuration.rb', line 446

def randomize_layout?
    get("randomize_layout", false)
end

#reconfigure!Object



215
216
217
218
219
220
221
222
# File 'lib/autoproj/configuration.rb', line 215

def reconfigure!
    new_config = Hash.new
    config.each do |key, (value, _user_validated)|
        new_config[key] = [value, false]
    end
    @modified = true
    @config = new_config
end

#reset(name = nil) ⇒ Object

Deletes the current configuration for all options or the one specified

The user will be asked for a new value next time one of the reset options is needed

Parameters:

  • name (String) (defaults to: nil)

    the option name (or by default nil to reset all options)

Returns:

  • the deleted value



57
58
59
60
61
62
63
64
65
66
67
# File 'lib/autoproj/configuration.rb', line 57

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

#reset_modifiedObject

Resets the modified? flag to false



45
46
47
# File 'lib/autoproj/configuration.rb', line 45

def reset_modified
    @modified = false
end

#reset_overrides(*names) ⇒ Object

Remove all overrides



93
94
95
96
97
98
99
# File 'lib/autoproj/configuration.rb', line 93

def reset_overrides(*names)
    if names.empty?
        @overrides.clear
    else
        names.each { |n| @overrides.delete(n) }
    end
end

#ruby_executableObject

The full path to the expected ruby executable



301
302
303
304
305
306
307
308
# File 'lib/autoproj/configuration.rb', line 301

def ruby_executable
    unless (path = get("ruby_executable", nil))
        path = OSPackageResolver.autodetect_ruby_program
        set("ruby_executable", path, true)
    end

    path
end

#save(path = self.path, force: false) ⇒ Object



224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/autoproj/configuration.rb', line 224

def save(path = self.path, force: false)
    return if !modified? && !force

    Ops.atomic_write(path) do |io|
        h = Hash.new
        config.each do |key, value|
            h[key] = value.first
        end

        io.write YAML.dump(h)
    end
    @modified = false
end

#separate_prefixes=(flag) ⇒ Object

Controls whether there should be one prefix per package



435
436
437
# File 'lib/autoproj/configuration.rb', line 435

def separate_prefixes=(flag)
    set("separate_prefixes", flag, true)
end

#separate_prefixes?Boolean

Returns true if there should be one prefix per package

The default is false (disabled)

Returns:

  • (Boolean)


428
429
430
# File 'lib/autoproj/configuration.rb', line 428

def separate_prefixes?
    get("separate_prefixes", false)
end

#set(key, value, user_validated = false) ⇒ Object

Sets a configuration option

Parameters:

  • key (String)

    the option name

  • value (Object)

    the option value

  • user_validated (Boolean) (defaults to: false)

    if true, autoproj will not ask the user about this value next time it is needed. Otherwise, it will be asked about it, the new value being used as default



76
77
78
79
80
81
82
83
# File 'lib/autoproj/configuration.rb', line 76

def set(key, value, user_validated = false)
    if config.has_key?(key)
        @modified ||= (config[key][0] != value)
    else
        @modified = true
    end
    config[key] = [value.dup, user_validated]
end

#shell_helpers=(flag) ⇒ Object



339
340
341
# File 'lib/autoproj/configuration.rb', line 339

def shell_helpers=(flag)
    set "shell_helpers", flag, true
end

#shell_helpers?Boolean

Returns:

  • (Boolean)


335
336
337
# File 'lib/autoproj/configuration.rb', line 335

def shell_helpers?
    get "shell_helpers", true
end

#source_dirString?

Defines a folder to which source packages will be layed out relative to

If nil, packages will be layed out relative to root_dir Only relative paths are allowed

The default is nil

Returns:

  • (String, nil)


419
420
421
# File 'lib/autoproj/configuration.rb', line 419

def source_dir
    get("source", nil)
end

#to_hashObject

The configuration as a key => value map



590
591
592
593
594
595
596
597
598
599
600
601
602
603
# File 'lib/autoproj/configuration.rb', line 590

def to_hash
    result = Hash.new
    @config.each do |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
    end
    result
end

#use_prerelease?Boolean

Returns:

  • (Boolean)


324
325
326
327
328
329
330
331
332
333
# File 'lib/autoproj/configuration.rb', line 324

def use_prerelease?
    use_prerelease =
        if (env_flag = ENV["AUTOPROJ_USE_PRERELEASE"])
            env_flag == "1"
        elsif has_value_for?("autoproj_use_prerelease")
            get("autoproj_use_prerelease")
        end
    set "autoproj_use_prerelease", (use_prerelease ? true : false), true
    use_prerelease
end

#user_shellsArray<String>

The shells used in this workspace.

Returns:

  • (Array<String>)


393
394
395
# File 'lib/autoproj/configuration.rb', line 393

def user_shells
    get("user_shells", [])
end

#user_shells=(shells) ⇒ Object

Sets the shells used in this workspace.



386
387
388
# File 'lib/autoproj/configuration.rb', line 386

def user_shells=(shells)
    set("user_shells", shells, true)
end

#utility_default(utility, enabled) ⇒ void

This method returns an undefined value.

Set the given utility to enabled by default

Unlike #utility_enable_all and #utility_disable_all, it does not touch existing exclusions

Parameters:

  • utility (String)

    the utility name (e.g. ‘doc’ or ‘test’)

  • enabled (Boolean)

    whether the utility will be enabled (true) or disabled (false)



516
517
518
# File 'lib/autoproj/configuration.rb', line 516

def utility_default(utility, enabled)
    set("#{utility_key(utility)}_default", enabled ? true : false)
end

#utility_disable(utility, *packages) ⇒ void

This method returns an undefined value.

Disables a utility for a specific package

Note that if the default for this utility is to be disabled, this is essentially a no-op.

Parameters:

  • utility (String)

    the utility name (e.g. ‘doc’ or ‘test’)

  • packages (String)

    the package names



567
568
569
570
571
572
573
# File 'lib/autoproj/configuration.rb', line 567

def utility_disable(utility, *packages)
    utility_config = get(utility_key(utility), Hash.new)
    packages.each do |pkg_name|
        utility_config[pkg_name] = false
    end
    set(utility_key(utility), utility_config)
end

#utility_disable_all(utility) ⇒ void

This method returns an undefined value.

Disables a utility for all packages

This both sets the default value for all packages and resets all package-specific values set with utility_enable_for and utility_disable_for

Parameters:

  • utility (String)

    the utility name (e.g. ‘doc’ or ‘test’)



554
555
556
557
# File 'lib/autoproj/configuration.rb', line 554

def utility_disable_all(utility)
    reset(utility_key(utility))
    set("#{utility_key(utility)}_default", false)
end

#utility_enable(utility, *packages) ⇒ void

This method returns an undefined value.

Enables a utility for a set of packages

Parameters:

  • utility (String)

    the utility name (e.g. ‘doc’ or ‘test’)

  • packages (String)

    the package names



538
539
540
541
542
543
544
# File 'lib/autoproj/configuration.rb', line 538

def utility_enable(utility, *packages)
    utility_config = get(utility_key(utility), Hash.new)
    packages.each do |pkg_name|
        utility_config[pkg_name] = true
    end
    set(utility_key(utility), utility_config)
end

#utility_enable_all(utility) ⇒ void

This method returns an undefined value.

Enables a utility for all packages

This both sets the default value for all packages and resets all package-specific values set with utility_enable_for and utility_disable_for

Parameters:

  • utility (String)

    the utility name (e.g. ‘doc’ or ‘test’)



528
529
530
531
# File 'lib/autoproj/configuration.rb', line 528

def utility_enable_all(utility)
    reset(utility_key(utility))
    set("#{utility_key(utility)}_default", true)
end

#utility_enabled_for?(utility, package) ⇒ Boolean

Returns whether a given utility is enabled for the package

If there is no specific configuration for the package, uses the global default set with utility_enable_all or utility_disable_all. If none of these methods has been called, uses the default in DEFAULT_UTILITY_SETUP

Parameters:

  • utility (String)

    the utility name (e.g. ‘doc’ or ‘test’)

  • package (String)

    the package name

Returns:

  • (Boolean)

    true if the utility should be enabled for the requested package and false otherwise



498
499
500
501
502
503
504
505
# File 'lib/autoproj/configuration.rb', line 498

def utility_enabled_for?(utility, package)
    utility_config = get(utility_key(utility), Hash.new)
    if utility_config.has_key?(package)
        utility_config[package]
    else
        get("#{utility_key(utility)}_default", DEFAULT_UTILITY_SETUP[utility])
    end
end

#utility_key(utility) ⇒ String

The configuration key that should be used to store the utility enable/disable information

Parameters:

  • the (String)

    utility name

Returns:

  • (String)

    the config key



483
484
485
# File 'lib/autoproj/configuration.rb', line 483

def utility_key(utility)
    "autoproj_#{utility}_utility"
end

#validate_ruby_executableObject

Verify that the Ruby executable that is being used to run autoproj matches the one expected in the configuration



312
313
314
315
316
317
318
319
320
321
322
# File 'lib/autoproj/configuration.rb', line 312

def validate_ruby_executable
    actual = OSPackageResolver.autodetect_ruby_program
    if has_value_for?("ruby_executable")
        expected = get("ruby_executable")
        if expected != actual
            raise ConfigError.new, "this autoproj installation was bootstrapped using #{expected}, but you are currently running under #{actual}. Changing the Ruby executable for in an existing autoproj workspace is unsupported"
        end
    else
        set("ruby_executable", actual, true)
    end
end

#validated_valuesObject

Returns the option’s name-value pairs for the options that do not require user input



135
136
137
138
139
140
141
142
143
# File 'lib/autoproj/configuration.rb', line 135

def validated_values
    config.inject(Hash.new) do |h, (k, v)|
        h[k] =
            if overrides.has_key?(k) then overrides[k]
            elsif v.last || !declared?(k) then v.first
            end
        h
    end
end