autoproj 1.10.2 → 1.11.0.b1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/Manifest.txt +9 -0
  3. data/Rakefile +4 -0
  4. data/bin/aup +5 -1
  5. data/bin/autolocate +1 -82
  6. data/bin/autoproj +6 -56
  7. data/bin/autoproj-bootstrap +31 -3
  8. data/bin/autoproj-cache +3 -60
  9. data/bin/autoproj-clean +1 -1
  10. data/bin/autoproj-create-set +0 -0
  11. data/bin/autoproj-doc +1 -1
  12. data/bin/autoproj-envsh +0 -0
  13. data/bin/autoproj-list +1 -1
  14. data/bin/autoproj-locate +17 -16
  15. data/bin/autoproj-query +0 -0
  16. data/bin/autoproj-show +0 -0
  17. data/bin/autoproj-switch-config +23 -0
  18. data/bin/autoproj-test +2 -2
  19. data/bin/autoproj_bootstrap +354 -210
  20. data/bin/autoproj_bootstrap.in +8 -0
  21. data/bin/autoproj_stress_test +1 -1
  22. data/lib/autoproj.rb +7 -0
  23. data/lib/autoproj/autobuild.rb +14 -35
  24. data/lib/autoproj/build_option.rb +104 -0
  25. data/lib/autoproj/cmdline.rb +62 -355
  26. data/lib/autoproj/configuration.rb +161 -0
  27. data/lib/autoproj/gitorious.rb +31 -20
  28. data/lib/autoproj/installation_manifest.rb +7 -1
  29. data/lib/autoproj/manifest.rb +124 -342
  30. data/lib/autoproj/ops/build.rb +107 -0
  31. data/lib/autoproj/ops/cache.rb +82 -0
  32. data/lib/autoproj/ops/configuration.rb +302 -0
  33. data/lib/autoproj/ops/loader.rb +97 -0
  34. data/lib/autoproj/ops/main_config_switcher.rb +271 -0
  35. data/lib/autoproj/ops/tools.rb +54 -0
  36. data/lib/autoproj/options.rb +26 -178
  37. data/lib/autoproj/osdeps.rb +49 -9
  38. data/lib/autoproj/package_set.rb +168 -87
  39. data/lib/autoproj/system.rb +6 -23
  40. data/lib/autoproj/variable_expansion.rb +0 -1
  41. data/lib/autoproj/vcs_definition.rb +23 -0
  42. data/lib/autoproj/version.rb +1 -1
  43. metadata +17 -7
@@ -0,0 +1,97 @@
1
+ module Autoproj
2
+ module Ops
3
+ class Loader
4
+ # @return [Array<String>] information about what is being loaded
5
+ attr_reader :file_stack
6
+
7
+ def initialize
8
+ @file_stack = Array.new
9
+ end
10
+
11
+ def in_package_set(pkg_set, path)
12
+ @file_stack.push([pkg_set, File.expand_path(path).gsub(/^#{Regexp.quote(Autoproj.root_dir)}\//, '')])
13
+ yield
14
+ ensure
15
+ @file_stack.pop
16
+ end
17
+
18
+ def filter_load_exception(error, package_set, path)
19
+ raise error if Autoproj.verbose
20
+ rx_path = Regexp.quote(path)
21
+ if error_line = error.backtrace.find { |l| l =~ /#{rx_path}/ }
22
+ if line_number = Integer(/#{rx_path}:(\d+)/.match(error_line)[1])
23
+ line_number = "#{line_number}:"
24
+ end
25
+
26
+ if package_set.local?
27
+ raise ConfigError.new(path), "#{path}:#{line_number} #{error.message}", error.backtrace
28
+ else
29
+ raise ConfigError.new(path), "#{File.basename(path)}(package_set=#{package_set.name}):#{line_number} #{error.message}", error.backtrace
30
+ end
31
+ else
32
+ raise error
33
+ end
34
+ end
35
+
36
+ # Returns the information about the file that is currently being loaded
37
+ #
38
+ # The return value is [package_set, path], where +package_set+ is the
39
+ # PackageSet instance and +path+ is the path of the file w.r.t. the autoproj
40
+ # root directory
41
+ def current_file
42
+ if file = @file_stack.last
43
+ file
44
+ else raise ArgumentError, "not in a #in_package_set context"
45
+ end
46
+ end
47
+
48
+ # The PackageSet object representing the package set that is currently being
49
+ # loaded
50
+ def current_package_set
51
+ current_file.first
52
+ end
53
+
54
+ # Load a definition file from a package set
55
+ #
56
+ # If any error is detected, the backtrace will be filtered so that it is
57
+ # easier to understand by the user. Moreover, if +source+ is non-nil, the
58
+ # package set name will be mentionned.
59
+ #
60
+ # @param [PackageSet] pkg_set
61
+ # @param [Array<String>] path
62
+ def load(pkg_set, *path)
63
+ path = File.join(*path)
64
+ in_package_set(pkg_set, File.expand_path(path).gsub(/^#{Regexp.quote(Autoproj.root_dir)}\//, '')) do
65
+ begin
66
+ Kernel.load path
67
+ rescue Interrupt
68
+ raise
69
+ rescue ConfigError => e
70
+ raise
71
+ rescue Exception => e
72
+ filter_load_exception(e, pkg_set, path)
73
+ end
74
+ end
75
+ end
76
+
77
+ # Load a definition file from a package set if the file is present
78
+ #
79
+ # (see load)
80
+ def load_if_present(pkg_set, *path)
81
+ path = File.join(*path)
82
+ if File.file?(path)
83
+ load(pkg_set, *path)
84
+ end
85
+ end
86
+ end
87
+
88
+ # Singleton object that maintains the loading state
89
+ #
90
+ # Note that it is here hopefully temporarily. All the Ops classes should
91
+ # have their loader object given at construction time
92
+ def self.loader
93
+ @loader ||= Loader.new
94
+ end
95
+ end
96
+ end
97
+
@@ -0,0 +1,271 @@
1
+ module Autoproj
2
+ module Ops
3
+ # Operations that modify the source of the main configuration (bootstrap
4
+ # and switch-config)
5
+ class MainConfigSwitcher
6
+ attr_reader :root_dir
7
+
8
+ def initialize(root_dir)
9
+ @root_dir = root_dir
10
+ end
11
+
12
+ # Set of directory entries that are expected to be present in the
13
+ # directory in which the user bootstraps
14
+ #
15
+ # @see check_root_dir_empty
16
+ EXPECTED_ROOT_ENTRIES = [".", "..", "autoproj_bootstrap",
17
+ ".gems", "bootstrap.sh", ENV_FILENAME].to_set
18
+
19
+ # Verifies that {#root_dir} contains only expected entries, to make
20
+ # sure that the user bootstraps into a new directory
21
+ #
22
+ # If the environment variable AUTOPROJ_BOOTSTRAP_IGNORE_NONEMPTY_DIR
23
+ # is set to 1, the check is skipped
24
+ def check_root_dir_empty
25
+ return if ENV['AUTOPROJ_BOOTSTRAP_IGNORE_NONEMPTY_DIR'] == '1'
26
+
27
+ require 'set'
28
+ curdir_entries = Dir.entries('.').to_set - EXPECTED_ROOT_ENTRIES
29
+ return if curdir_entries.empty?
30
+
31
+ while true
32
+ print "The current directory is not empty, continue bootstrapping anyway ? [yes] "
33
+ STDOUT.flush
34
+ answer = STDIN.readline.chomp
35
+ if answer == "no"
36
+ raise Interrupt, "Interrupted by user"
37
+ end
38
+
39
+ if answer == "" || answer == "yes"
40
+ # Set this environment variable since we might restart
41
+ # autoproj later on.
42
+ ENV['AUTOPROJ_BOOTSTRAP_IGNORE_NONEMPTY_DIR'] = '1'
43
+ return
44
+ else
45
+ STDOUT.puts "invalid answer. Please answer 'yes' or 'no'"
46
+ STDOUT.flush
47
+ end
48
+ end
49
+ end
50
+
51
+ # Validates the environment variable AUTOPROJ_CURRENT_ROOT during a
52
+ # bootstrap
53
+ #
54
+ # AUTOPROJ_CURRENT_ROOT must be set to either the new root
55
+ # ({root_dir}) or a root that we are reusing
56
+ #
57
+ # @param [Array<String>] reuse set of autoproj roots that are being reused
58
+ # @raise ConfigError
59
+ def validate_autoproj_current_root(reuse)
60
+ if current_root = ENV['AUTOPROJ_CURRENT_ROOT']
61
+ # Allow having a current root only if it is being reused
62
+ if (current_root != root_dir) && !reuse.include?(current_root)
63
+ Autoproj.error "the env.sh from #{ENV['AUTOPROJ_CURRENT_ROOT']} seem to already be sourced"
64
+ Autoproj.error "start a new shell and try to bootstrap again"
65
+ Autoproj.error
66
+ Autoproj.error "you are allowed to boostrap from another autoproj installation"
67
+ Autoproj.error "only if you reuse it with the --reuse flag"
68
+ raise ConfigError
69
+ end
70
+ end
71
+ end
72
+
73
+ def handle_bootstrap_options(args)
74
+ reuse = []
75
+ parser = OptionParser.new do |opt|
76
+ opt.on '--reuse [DIR]', "reuse the given autoproj installation (can be given multiple times). If given without arguments, reuse the currently active install (#{ENV['AUTOPROJ_CURRENT_ROOT']})" do |path|
77
+ path ||= ENV['AUTOPROJ_CURRENT_ROOT']
78
+
79
+ path = File.expand_path(path)
80
+ if !File.directory?(path) || !File.directory?(File.join(path, 'autoproj'))
81
+ raise ConfigError.new, "#{path} does not look like an autoproj installation"
82
+ end
83
+ reuse << path
84
+ end
85
+ end
86
+ args = parser.parse(args)
87
+ return args, reuse
88
+ end
89
+
90
+ def bootstrap(*args)
91
+ if File.exists?(File.join(root_dir, 'autoproj', "manifest"))
92
+ raise ConfigError.new, "this installation is already bootstrapped. Remove the autoproj directory if it is not the case"
93
+ end
94
+
95
+ check_root_dir_empty
96
+ args, reuse = handle_bootstrap_options(args)
97
+ validate_autoproj_current_root(reuse)
98
+
99
+ Autoproj.root_dir = root_dir
100
+ Autobuild.prefix = Autoproj.build_dir
101
+ Autobuild.srcdir = Autoproj.root_dir
102
+ Autobuild.logdir = File.join(Autobuild.prefix, 'log')
103
+
104
+ Autoproj.manifest = Manifest.new
105
+ load_autoprojrc
106
+ Autoproj.prepare_environment
107
+
108
+ Autoproj::OSDependencies.define_osdeps_mode_option
109
+ osdeps = Autoproj::OSDependencies.load_default
110
+ if osdeps_forced_mode
111
+ osdeps.osdeps_mode = osdeps_forced_mode
112
+ end
113
+ osdeps.osdeps_mode
114
+
115
+ CmdLine.update_myself :force => true, :restart_on_update => false
116
+ Autoproj.change_option 'reused_autoproj_installations', reuse, true
117
+ Autoproj.export_env_sh
118
+
119
+ # If we are not getting the installation setup from a VCS, copy the template
120
+ # files
121
+ if args.empty? || args.size == 1
122
+ sample_dir = File.expand_path(File.join("..", "..", "samples"), File.dirname(__FILE__))
123
+ FileUtils.cp_r File.join(sample_dir, "autoproj"), "autoproj"
124
+ end
125
+
126
+ if args.size == 1 # the user asks us to download a manifest
127
+ manifest_url = args.first
128
+ Autoproj.message("autoproj: downloading manifest file #{manifest_url}", :bold)
129
+ manifest_data =
130
+ begin open(manifest_url) { |file| file.read }
131
+ rescue
132
+ # Delete the autoproj directory
133
+ FileUtils.rm_rf 'autoproj'
134
+ raise ConfigError.new, "cannot read file / URL #{manifest_url}, did you mean 'autoproj bootstrap VCSTYPE #{manifest_url}' ?"
135
+ end
136
+
137
+ File.open(File.join(Autoproj.config_dir, "manifest"), "w") do |io|
138
+ io.write(manifest_data)
139
+ end
140
+
141
+ elsif args.size >= 2 # is a VCS definition for the manifest itself ...
142
+ type, url, *options = *args
143
+ url = VCSDefinition.to_absolute_url(url, Dir.pwd)
144
+ do_switch_config(false, type, url, *options)
145
+ end
146
+ Autoproj.save_config
147
+ end
148
+
149
+ def switch_config(*args)
150
+ Autoproj.load_config
151
+ if Autoproj.has_config_key?('manifest_source')
152
+ vcs = VCSDefinition.from_raw(Autoproj.user_config('manifest_source'))
153
+ end
154
+
155
+ if args.first =~ /^(\w+)=/
156
+ # First argument is an option string, we are simply setting the
157
+ # options without changing the type/url
158
+ type, url = vcs.type, vcs.url
159
+ else
160
+ type, url = args.shift, args.shift
161
+ end
162
+ options = args
163
+
164
+ url = VCSDefinition.to_absolute_url(url)
165
+
166
+ if vcs && (vcs.type == type && vcs.url == url)
167
+ # Don't need to do much: simply change the options and save the config
168
+ # file, the VCS handler will take care of the actual switching
169
+ vcs_def = Autoproj.user_config('manifest_source')
170
+ options.each do |opt|
171
+ opt_name, opt_value = opt.split('=')
172
+ vcs_def[opt_name] = opt_value
173
+ end
174
+ # Validate the VCS definition, but save the hash as-is
175
+ VCSDefinition.from_raw(vcs_def)
176
+ Autoproj.change_option "manifest_source", vcs_def.dup, true
177
+ Autoproj.save_config
178
+ true
179
+
180
+ else
181
+ # We will have to delete the current autoproj directory. Ask the user.
182
+ opt = Autoproj::BuildOption.new("delete current config", "boolean",
183
+ Hash[:default => "false",
184
+ :doc => "delete the current configuration ? (required to switch)"], nil)
185
+
186
+ return if !opt.ask(nil)
187
+
188
+ Dir.chdir(Autoproj.root_dir) do
189
+ do_switch_config(true, type, url, *options)
190
+ end
191
+ false
192
+ end
193
+ end
194
+
195
+ def do_switch_config(delete_current, type, url, *options)
196
+ vcs_def = Hash.new
197
+ vcs_def[:type] = type
198
+ vcs_def[:url] = VCSDefinition.to_absolute_url(url)
199
+ options.each do |opt|
200
+ name, value = opt.split("=")
201
+ if value =~ /^\d+$/
202
+ value = Integer(value)
203
+ end
204
+
205
+ vcs_def[name] = value
206
+ end
207
+
208
+ vcs = VCSDefinition.from_raw(vcs_def)
209
+
210
+ # Install the OS dependencies required for this VCS
211
+ Autoproj::OSDependencies.define_osdeps_mode_option
212
+ osdeps = Autoproj::OSDependencies.load_default
213
+ osdeps.osdeps_mode
214
+ osdeps.install([vcs.type])
215
+
216
+ # Now check out the actual configuration
217
+ config_dir = File.join(Dir.pwd, "autoproj")
218
+ if delete_current
219
+ # Find a backup name for it
220
+ backup_base_name = backup_name = "#{config_dir}.bak"
221
+ index = 0
222
+ while File.directory?(backup_name)
223
+ backup_name = "#{backup_base_name}-#{index}.bak"
224
+ index += 1
225
+ end
226
+
227
+ FileUtils.mv config_dir, backup_name
228
+ end
229
+ Ops::Configuration.update_configuration_repository(
230
+ vcs,
231
+ "autoproj main configuration",
232
+ config_dir)
233
+
234
+ # If the new tree has a configuration file, load it and set
235
+ # manifest_source
236
+ Autoproj.load_config
237
+
238
+ # And now save the options: note that we keep the current option set even
239
+ # though we switched configuration. This is not a problem as undefined
240
+ # options will not be reused
241
+ #
242
+ # TODO: cleanup the options to only keep the relevant ones
243
+ vcs_def = Hash['type' => type, 'url' => url]
244
+ options.each do |opt|
245
+ opt_name, opt_val = opt.split '='
246
+ vcs_def[opt_name] = opt_val
247
+ end
248
+ # Validate the option hash, just in case
249
+ VCSDefinition.from_raw(vcs_def)
250
+ # Save the new options
251
+ Autoproj.change_option "manifest_source", vcs_def.dup, true
252
+ Autoproj.save_config
253
+
254
+ rescue Exception => e
255
+ Autoproj.error "switching configuration failed: #{e.message}"
256
+ if backup_name
257
+ Autoproj.error "restoring old configuration"
258
+ FileUtils.rm_rf config_dir if config_dir
259
+ FileUtils.mv backup_name, config_dir
260
+ end
261
+ raise
262
+ ensure
263
+ if backup_name
264
+ FileUtils.rm_rf backup_name
265
+ end
266
+ end
267
+ end
268
+ end
269
+ end
270
+
271
+
@@ -0,0 +1,54 @@
1
+ module Autoproj
2
+ module Ops
3
+ module Tools
4
+ # Data structure used to use autobuild importers without a package, to
5
+ # import configuration data.
6
+ #
7
+ # It has to match the interface of Autobuild::Package that is relevant
8
+ # for importers
9
+ class FakePackage < Autobuild::Package
10
+ attr_reader :srcdir
11
+ attr_reader :importer
12
+
13
+ # Used by the autobuild importers
14
+ attr_accessor :updated
15
+
16
+ def autoproj_name
17
+ name
18
+ end
19
+
20
+ def initialize(text_name, srcdir, importer = nil)
21
+ super(text_name)
22
+ @srcdir = srcdir
23
+ @importer = importer
24
+ @@packages.delete(text_name)
25
+ end
26
+
27
+ def import(only_local = false)
28
+ importer.import(self, only_local)
29
+ end
30
+
31
+ def add_stat(*args)
32
+ end
33
+ end
34
+
35
+ # Creates an autobuild package whose job is to allow the import of a
36
+ # specific repository into a given directory.
37
+ #
38
+ # +vcs+ is the VCSDefinition file describing the repository, +text_name+
39
+ # the name used when displaying the import progress, +pkg_name+ the
40
+ # internal name used to represent the package and +into+ the directory
41
+ # in which the package should be checked out.
42
+ def create_autobuild_package(vcs, text_name, into)
43
+ importer = vcs.create_autobuild_importer
44
+ FakePackage.new(text_name, into, importer)
45
+
46
+ rescue Autobuild::ConfigException => e
47
+ raise ConfigError.new, "cannot import #{text_name}: #{e.message}", e.backtrace
48
+ end
49
+
50
+ extend Tools
51
+ end
52
+ end
53
+ end
54
+
@@ -1,203 +1,51 @@
1
1
  module Autoproj
2
- class InputError < RuntimeError; end
3
-
4
- class << self
5
- # Programatically overriden autoproj options
6
- #
7
- # @see override_option
8
- attr_reader :option_overrides
9
- end
10
- @option_overrides = Hash.new
11
-
12
- # Programatically override a user-selected option without changing the
13
- # configuration file
2
+ # @deprecated use config.override instead
14
3
  def self.override_option(option_name, value)
15
- @option_overrides[option_name] = value
4
+ config.override(option_name, value)
16
5
  end
17
-
18
- class BuildOption
19
- attr_reader :name
20
- attr_reader :type
21
- attr_reader :options
22
-
23
- attr_reader :validator
24
-
25
- TRUE_STRINGS = %w{on yes y true}
26
- FALSE_STRINGS = %w{off no n false}
27
- def initialize(name, type, options, validator)
28
- @name, @type, @options = name.to_str, type.to_str, options.to_hash
29
- @validator = validator.to_proc if validator
30
- if !BuildOption.respond_to?("validate_#{type}")
31
- raise ConfigError.new, "invalid option type #{type}"
32
- end
33
- end
34
-
35
- def short_doc
36
- if short_doc = options[:short_doc]
37
- short_doc
38
- elsif doc = options[:doc]
39
- if doc.respond_to?(:to_ary) then doc.first
40
- else doc
41
- end
42
- else "#{name} (no documentation for this option)"
43
- end
44
- end
45
-
46
- def doc
47
- doc = (options[:doc] || "#{name} (no documentation for this option)")
48
- if doc.respond_to?(:to_ary) # multi-line
49
- first_line = doc[0]
50
- remaining = doc[1..-1]
51
- if remaining.empty?
52
- first_line
53
- else
54
- remaining = remaining.join("\n").split("\n").join("\n ")
55
- Autoproj.color(first_line, :bold) + "\n " + remaining
56
- end
57
- else
58
- doc
59
- end
60
- end
61
-
62
- def ask(current_value, doc = nil)
63
- default_value =
64
- if !current_value.nil? then current_value.to_s
65
- elsif options[:default] then options[:default].to_str
66
- else ''
67
- end
68
-
69
- STDOUT.print " #{doc || self.doc} [#{default_value}] "
70
- STDOUT.flush
71
- answer = STDIN.readline.chomp
72
- if answer == ''
73
- answer = default_value
74
- end
75
- validate(answer)
76
-
77
- rescue InputError => e
78
- Autoproj.message("invalid value: #{e.message}", :red)
79
- retry
80
- end
81
-
82
- def validate(value)
83
- value = BuildOption.send("validate_#{type}", value, options)
84
- if validator
85
- value = validator[value]
86
- end
87
- value
88
- end
89
-
90
- def self.validate_boolean(value, options)
91
- if TRUE_STRINGS.include?(value.downcase)
92
- true
93
- elsif FALSE_STRINGS.include?(value.downcase)
94
- false
95
- else
96
- raise InputError, "invalid boolean value '#{value}', accepted values are '#{TRUE_STRINGS.join(", ")}' for true, and '#{FALSE_STRINGS.join(", ")} for false"
97
- end
98
- end
99
-
100
- def self.validate_string(value, options)
101
- if possible_values = options[:possible_values]
102
- if options[:lowercase]
103
- value = value.downcase
104
- elsif options[:uppercase]
105
- value = value.upcase
106
- end
107
-
108
- if !possible_values.include?(value)
109
- raise InputError, "invalid value '#{value}', accepted values are '#{possible_values.join("', '")}' (without the quotes)"
110
- end
111
- end
112
- value
113
- end
114
- end
115
-
116
- @user_config = Hash.new
117
-
118
- def self.option_set
119
- @user_config.inject(Hash.new) do |h, (k, v)|
120
- h[k] = v.first
121
- h
122
- end
123
- end
124
-
6
+ # @deprecated use config.reset instead
125
7
  def self.reset_option(key)
126
- @user_config.delete(key)
8
+ config.reset(key)
127
9
  end
128
-
10
+ # @deprecated use config.set(key, value, user_validated) instead
129
11
  def self.change_option(key, value, user_validated = false)
130
- @user_config[key] = [value, user_validated]
12
+ config.set(key, value, user_validated)
131
13
  end
132
-
14
+ # @deprecated use config.validated_values instead
15
+ def self.option_set
16
+ config.validated_values
17
+ end
18
+ # @deprecated use config.get(key) instead
133
19
  def self.user_config(key)
134
- value, seen = @user_config[key]
135
- # All non-user options are always considered as "seen"
136
- seen ||= !@declared_options.has_key?(key)
137
-
138
- if value.nil? || (!seen && Autoproj.reconfigure?)
139
- value = configure(key)
140
- else
141
- if !seen
142
- doc = @declared_options[key].short_doc
143
- if doc[-1, 1] != "?"
144
- doc = "#{doc}:"
145
- end
146
- Autoproj.message " #{doc} #{value}"
147
- @user_config[key] = [value, true]
148
- end
149
- value
150
- end
20
+ config.get(key)
151
21
  end
152
-
153
- @declared_options = Hash.new
22
+ # @deprecated use config.declare(name, type, options, &validator) instead
154
23
  def self.configuration_option(name, type, options, &validator)
155
- @declared_options[name] = BuildOption.new(name, type, options, validator)
24
+ config.declare(name, type, options, &validator)
156
25
  end
157
-
26
+ # @deprecated use config.declared?(name, type, options, &validator) instead
158
27
  def self.declared_option?(name)
159
- @declared_options.has_key?(name)
28
+ config.declared?(name)
160
29
  end
161
-
30
+ # @deprecated use config.configure(option_name) instead
162
31
  def self.configure(option_name)
163
- if opt = @declared_options[option_name]
164
- if current_value = @user_config[option_name]
165
- current_value = current_value.first
166
- end
167
- value = opt.ask(current_value)
168
- @user_config[option_name] = [value, true]
169
- value
170
- else
171
- raise ConfigError.new, "undeclared option '#{option_name}'"
172
- end
32
+ config.configure(option_name)
173
33
  end
174
-
175
- def self.save_config
176
- File.open(File.join(Autoproj.config_dir, "config.yml"), "w") do |io|
177
- config = Hash.new
178
- @user_config.each_key do |key|
179
- config[key] = @user_config[key].first
180
- end
181
-
182
- io.write YAML.dump(config)
183
- end
34
+ # @deprecated use config.has_value_for?(name)
35
+ def self.has_config_key?(name)
36
+ config.has_value_for?(name)
184
37
  end
185
38
 
186
- def self.has_config_key?(name)
187
- @user_config.has_key?(name)
39
+ def self.save_config
40
+ config.save(File.join(Autoproj.config_dir, "config.yml"))
188
41
  end
189
42
 
190
43
  def self.load_config
44
+ @config ||= Configuration.new
45
+
191
46
  config_file = File.join(Autoproj.config_dir, "config.yml")
192
47
  if File.exists?(config_file)
193
- config = YAML.load(File.read(config_file))
194
- if !config
195
- return
196
- end
197
-
198
- config.each do |key, value|
199
- @user_config[key] = [value, false]
200
- end
48
+ config.load(config_file, reconfigure?)
201
49
  end
202
50
  end
203
51