fig 0.1.50 → 0.1.51

Sign up to get free protection for your applications and to get access to all the features.
data/Changes CHANGED
@@ -1,3 +1,7 @@
1
+ v0.1.51
2
+
3
+ - You can now set an environment variable to the empty string with "set".
4
+
1
5
  v0.1.50
2
6
 
3
7
  - Trying to get releases via rake to work properly for multiple platforms.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.50
1
+ 0.1.51
data/lib/fig.rb CHANGED
@@ -16,6 +16,7 @@ require 'fig/retriever'
16
16
  require 'fig/userinputerror'
17
17
  require 'fig/windows'
18
18
 
19
+ # Main program
19
20
  module Fig
20
21
  DEFAULT_FIG_FILE = 'package.fig'
21
22
 
@@ -27,7 +28,15 @@ module Fig
27
28
  return package_name, config_name, version_name
28
29
  end
29
30
 
30
- def run_fig(argv)
31
+ def read_in_package_config_file(options)
32
+ if File.exist?(options[:package_config_file])
33
+ return File.read(options[:package_config_file])
34
+ else
35
+ raise UserInputError.new(%Q<File not found: "#{options[:package_config_file]}".>)
36
+ end
37
+ end
38
+
39
+ def initialize_shell_command(argv)
31
40
  shell_command = nil
32
41
  argv.each_with_index do |arg, i|
33
42
  if arg == '--'
@@ -37,168 +46,204 @@ module Fig
37
46
  end
38
47
  end
39
48
 
40
- options, argv, exit_value = parse_options(argv)
41
- if not exit_value.nil?
42
- return exit_value
43
- end
44
-
45
- Logging.initialize_pre_configuration(options[:log_level])
46
-
47
- vars = {}
48
- ENV.each {|key,value| vars[key]=value }
49
+ return shell_command
50
+ end
49
51
 
50
- remote_url = nil
52
+ def initialize_remote_url(options)
51
53
  if options[:update] || options[:publish] || options[:update_if_missing] || options[:list_remote]
52
- remote_url = ENV['FIG_REMOTE_URL']
53
- if remote_url.nil?
54
- $stderr.puts 'Please define the FIG_REMOTE_URL environment variable.'
55
- return 1
54
+ if ENV['FIG_REMOTE_URL'].nil?
55
+ raise UserInputError.new 'Please define the FIG_REMOTE_URL environment variable.'
56
56
  end
57
+ return ENV['FIG_REMOTE_URL']
57
58
  end
58
59
 
59
- configuration = FigRC.find(
60
- options[:figrc],
61
- remote_url,
62
- options[:login],
63
- options[:home],
64
- options[:no_figrc]
65
- )
66
-
67
- Logging.initialize_post_configuration(options[:log_config] || configuration['log configuration'], options[:log_level])
60
+ return nil
61
+ end
68
62
 
69
- remote_user = nil
63
+ def load_package_config_file_contents(options)
64
+ package_config_file = options[:package_config_file]
70
65
 
71
- os = OS.new(options[:login])
72
- repos = Repository.new(
73
- os,
74
- File.expand_path(File.join(options[:home], 'repos')),
75
- remote_url,
76
- configuration,
77
- remote_user,
78
- options[:update],
79
- options[:update_if_missing]
80
- )
81
- retriever = Retriever.new('.')
82
- # Check to see if this is still happening with the new layers of abstraction.
83
- at_exit { retriever.save }
84
- env = Environment.new(os, repos, vars, retriever)
66
+ if package_config_file == :none
67
+ return nil
68
+ elsif package_config_file == '-'
69
+ return $stdin.read
70
+ elsif package_config_file.nil?
71
+ if File.exist?(DEFAULT_FIG_FILE)
72
+ return File.read(DEFAULT_FIG_FILE)
73
+ end
74
+ else
75
+ return read_in_package_config_file(options)
76
+ end
77
+ end
85
78
 
86
- options[:modifiers].each do |modifier|
87
- env.apply_config_statement(nil, modifier, nil)
79
+ def display_package_list(repository)
80
+ repository.list_packages.sort.each do |item|
81
+ puts item
88
82
  end
83
+ end
89
84
 
90
- package_config_file = nil
91
- if options[:package_config_file] == :none
92
- # ignore
93
- elsif options[:package_config_file] == '-'
94
- package_config_file = $stdin.read
95
- elsif options[:package_config_file].nil?
96
- package_config_file = File.read(DEFAULT_FIG_FILE) if File.exist?(DEFAULT_FIG_FILE)
97
- else
98
- if File.exist?(options[:package_config_file])
99
- package_config_file = File.read(options[:package_config_file])
100
- else
101
- $stderr.puts %Q<File not found: "#{options[:package_config_file]}".>
102
- return 1
103
- end
85
+ def display_remote_package_list(repository)
86
+ repository.list_remote_packages.sort.each do |item|
87
+ puts item
104
88
  end
89
+ end
105
90
 
106
- options[:cleans].each do |descriptor|
91
+ def display_configs_in_local_packages_list(options, repository)
92
+ options[:list_configs].each do |descriptor|
107
93
  package_name, version_name = descriptor.split('/')
108
- repos.clean(package_name, version_name)
94
+ repository.read_local_package(package_name, version_name).configs.each do |config|
95
+ puts config.name
96
+ end
109
97
  end
98
+ end
99
+
100
+ def resolve_listing(options, repository)
110
101
  if options[:list]
111
- repos.list_packages.sort.each do |item|
112
- puts item
113
- end
114
- return 0
102
+ display_package_list(repository)
103
+ return true
115
104
  end
116
105
 
117
106
  if options[:list_remote]
118
- repos.list_remote_packages.sort.each do |item|
119
- puts item
120
- end
121
- return 0
107
+ display_remote_package_list(repository)
108
+ return true
122
109
  end
123
110
 
124
111
  if not options[:list_configs].empty?
125
- options[:list_configs].each do |descriptor|
126
- package_name, version_name = descriptor.split('/')
127
- repos.read_local_package(package_name, version_name).configs.each do |config|
128
- puts config.name
129
- end
130
- end
131
- return 0
112
+ display_configs_in_local_packages_list(options, repository)
113
+ return true
132
114
  end
133
115
 
116
+ return false
117
+ end
118
+
119
+ def parse_package_config_file(options, package_config_file, environment, configuration)
134
120
  if package_config_file
135
121
  package = Parser.new(configuration).parse_package(nil, nil, '.', package_config_file)
136
- direct_retrieves=[]
137
122
  if options[:update] || options[:update_if_missing]
138
123
  package.retrieves.each do |var, path|
139
- if var =~ %r< ^ \@ ([^/]+) (.*) >x
140
- direct_retrieves << [$1, $2, path]
141
- else
142
- env.add_retrieve(var, path)
143
- end
124
+ environment.add_retrieve(var, path)
144
125
  end
145
126
  end
127
+
146
128
  unless options[:publish] || options[:list] || options[:publish_local]
147
- env.register_package(package)
148
- env.apply_config(package, options[:config], nil)
149
- direct_retrieves.each do |info|
150
- env.direct_retrieve(info[0], info[1], info[2])
151
- end
129
+ environment.register_package(package)
130
+ environment.apply_config(package, options[:config], nil)
152
131
  end
153
132
  else
154
133
  package = Package.new(nil, nil, '.', [])
155
134
  end
156
135
 
157
- if options[:publish] || options[:publish_local]
158
- if !argv.empty?
159
- $stderr.puts %Q<Unexpected arguments: #{argv.join(' ')}>
160
- return 10
161
- end
162
- package_name, config_name, version_name = parse_descriptor(options[:publish] || options[:publish_local])
163
- if package_name.nil? || version_name.nil?
164
- $stderr.puts 'Please specify a package name and a version name.'
165
- return 10
166
- end
167
- if not options[:modifiers].empty?
168
- publish_statements = options[:resources] + options[:archives] + [Package::Configuration.new('default', options[:modifiers])]
169
- publish_statements << Package::Publish.new('default','default')
170
- elsif not package.statements.empty?
171
- publish_statements = package.statements
172
- else
173
- $stderr.puts 'Nothing to publish.'
174
- return 1
175
- end
176
- if options[:publish]
177
- Logging.info "Checking status of #{package_name}/#{version_name}..."
178
- if repos.list_remote_packages.include?("#{package_name}/#{version_name}")
179
- Logging.info "#{package_name}/#{version_name} has already been published."
180
- if not options[:force]
181
- Logging.fatal 'Use the --force option if you really want to overwrite, or use --publish-local for testing.'
182
- return 1
183
- else
184
- Logging.info 'Overwriting...'
185
- end
136
+ return package, environment
137
+ end
138
+
139
+ def publish(argv, options, package, repository)
140
+ if not argv.empty?
141
+ $stderr.puts %Q<Unexpected arguments: #{argv.join(' ')}>
142
+ return 10
143
+ end
144
+
145
+ package_name, config_name, version_name = parse_descriptor(options[:publish] || options[:publish_local])
146
+
147
+ if package_name.nil? || version_name.nil?
148
+ $stderr.puts 'Please specify a package name and a version name.'
149
+ return 10
150
+ end
151
+
152
+ if not options[:non_command_package_statements].empty?
153
+ publish_statements = options[:resources] + options[:archives] + [Package::Configuration.new('default', options[:non_command_package_statements])]
154
+ publish_statements << Package::Publish.new('default','default')
155
+ elsif not package.statements.empty?
156
+ publish_statements = package.statements
157
+ else
158
+ $stderr.puts 'Nothing to publish.'
159
+ return 1
160
+ end
161
+
162
+ if options[:publish]
163
+ Logging.info "Checking status of #{package_name}/#{version_name}..."
164
+
165
+ if repository.list_remote_packages.include?("#{package_name}/#{version_name}")
166
+ Logging.info "#{package_name}/#{version_name} has already been published."
167
+
168
+ if not options[:force]
169
+ Logging.fatal 'Use the --force option if you really want to overwrite, or use --publish-local for testing.'
170
+ return 1
171
+ else
172
+ Logging.info 'Overwriting...'
186
173
  end
187
174
  end
188
- Logging.info "Publishing #{package_name}/#{version_name}."
189
- repos.publish_package(publish_statements, package_name, version_name, options[:publish_local])
190
- elsif options[:echo]
191
- puts env[options[:echo]]
175
+ end
176
+
177
+ Logging.info "Publishing #{package_name}/#{version_name}."
178
+ repository.publish_package(publish_statements, package_name, version_name, options[:publish_local])
179
+
180
+ return 0
181
+ end
182
+
183
+ def run_fig(argv)
184
+ shell_command = initialize_shell_command(argv)
185
+
186
+ options, argv, exit_value = parse_options(argv)
187
+ if not exit_value.nil?
188
+ return exit_value
189
+ end
190
+
191
+ Logging.initialize_pre_configuration(options[:log_level])
192
+
193
+ remote_url = initialize_remote_url(options)
194
+
195
+ configuration = FigRC.find(
196
+ options[:figrc], remote_url, options[:login], options[:home], options[:no_figrc]
197
+ )
198
+
199
+ Logging.initialize_post_configuration(options[:log_config] || configuration['log configuration'], options[:log_level])
200
+
201
+ os = OS.new(options[:login])
202
+ repository = Repository.new(
203
+ os,
204
+ File.expand_path(File.join(options[:home], 'repos')),
205
+ remote_url,
206
+ configuration,
207
+ nil, # remote_user
208
+ options[:update],
209
+ options[:update_if_missing]
210
+ )
211
+
212
+ retriever = Retriever.new('.')
213
+ # Check to see if this is still happening with the new layers of abstraction.
214
+ at_exit { retriever.save }
215
+ environment = Environment.new(os, repository, nil, retriever)
216
+
217
+ options[:non_command_package_statements].each do |statement|
218
+ environment.apply_config_statement(nil, statement, nil)
219
+ end
220
+
221
+ package_config_file = load_package_config_file_contents(options)
222
+
223
+ options[:cleans].each do |descriptor|
224
+ package_name, version_name = descriptor.split('/')
225
+ repository.clean(package_name, version_name)
226
+ return true
227
+ end
228
+
229
+ if resolve_listing(options, repository)
230
+ return true
231
+ end
232
+
233
+ package, environment = parse_package_config_file(options, package_config_file, environment, configuration)
234
+
235
+ if options[:publish] || options[:publish_local]
236
+ return publish(argv, options, package, repository)
237
+ elsif options[:get]
238
+ puts environment[options[:get]]
192
239
  elsif shell_command
193
240
  argv.shift
194
- env.execute_shell(shell_command) { |cmd| os.shell_exec cmd }
195
- elsif argv[0]
196
- package_name, config_name, version_name = parse_descriptor(argv.shift)
197
- env.include_config(package, package_name, config_name, version_name, {}, nil)
198
- env.execute_config(package, package_name, config_name, nil, argv) { |cmd| os.shell_exec cmd }
241
+ environment.execute_shell(shell_command) { |cmd| os.shell_exec cmd }
199
242
  elsif not argv.empty?
200
- env.execute_config(package, nil, options[:config], nil, argv) { |cmd| os.shell_exec cmd }
201
- elsif not repos.updating?
243
+ package_name, config_name, version_name = parse_descriptor(argv.shift)
244
+ environment.include_config(package, package_name, config_name, version_name, {}, nil)
245
+ environment.execute_config(package, package_name, config_name, nil, argv) { |cmd| os.shell_exec cmd }
246
+ elsif not repository.updating?
202
247
  $stderr.puts "Nothing to do.\n"
203
248
  $stderr.puts USAGE
204
249
  $stderr.puts %q<Run "fig --help" for a full list of commands.>
@@ -208,37 +253,36 @@ module Fig
208
253
  return 0
209
254
  end
210
255
 
256
+ def log_error_message(error)
257
+ # If there's no message, we assume that the cause has already been logged.
258
+ if error_has_message?(error)
259
+ Logging.fatal error.to_s
260
+ end
261
+ end
262
+
211
263
  def run_with_exception_handling(argv)
212
264
  begin
213
265
  return_code = run_fig(argv)
214
266
  return return_code
215
- rescue URLAccessError => exception
267
+ rescue URLAccessError => error
216
268
  urls = exception.urls.join(', ')
217
269
  $stderr.puts "Access to #{urls} in #{exception.package}/#{exception.version} not allowed."
218
270
  return 1
219
- rescue UserInputError => exception
220
- # If there's no message, we assume that the cause has already been logged.
221
- if not exception_has_message?(exception)
222
- Logging.fatal exception.to_s
223
- end
224
-
271
+ rescue UserInputError => error
272
+ log_error_message(error)
225
273
  return 1
226
- rescue OptionParser::InvalidOption => exception
227
- $stderr.puts exception.to_s
274
+ rescue OptionParser::InvalidOption => error
275
+ $stderr.puts error.to_s
228
276
  $stderr.puts USAGE
229
277
  return 1
230
278
  rescue RepositoryError => error
231
- # If there's no message, we assume that the cause has already been logged.
232
- if not exception_has_message?(error)
233
- Logging.fatal error.to_s
234
- end
235
-
279
+ log_error_message(error)
236
280
  return 1
237
281
  end
238
282
  end
239
283
 
240
- def exception_has_message?(exception)
241
- class_name = exception.class.name
242
- return exception.message == class_name
284
+ def error_has_message?(error)
285
+ class_name = error.class.name
286
+ return error.message != class_name
243
287
  end
244
288
  end
@@ -1,5 +1,6 @@
1
-
2
1
  module Fig
2
+ # Configuration for the Fig program, as opposed to the configuration for a
3
+ # package.
3
4
  class ApplicationConfiguration
4
5
  def initialize(remote_repository_url)
5
6
  @data = []
data/lib/fig/backtrace.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # Contains traces of file inclusions so that the user can track down which file
2
+ # an error occurred in.
1
3
  class Backtrace
2
4
  attr_reader :overrides
3
5
 
@@ -7,23 +7,31 @@ require 'fig/package/include'
7
7
  require 'fig/package/path'
8
8
  require 'fig/package/set'
9
9
  require 'fig/repositoryerror'
10
+ require 'fig/userinputerror'
10
11
 
11
12
  module Fig
12
- # This class manages the program's state, including the value of all
13
- # environment variables, and which packages have already been applied.
13
+ # Manages the program's metadata, including packages and environment
14
+ # variables, and sets things up for running commands (from "command"
15
+ # statements in configuration files).
14
16
  class Environment
15
17
  DEFAULT_VERSION_NAME = 'current'
16
18
 
17
- def initialize(os, repository, variables, retriever)
19
+ def initialize(os, repository, variables_override, retriever)
18
20
  @os = os
19
21
  @repository = repository
20
- @variables = variables
22
+ @variables = variables_override || get_environment_variables
21
23
  @retrieve_vars = {}
22
24
  @packages = {}
23
25
  @applied_configs = {}
24
26
  @retriever = retriever
25
27
  end
26
28
 
29
+ def get_environment_variables
30
+ vars = {}
31
+ ENV.each { |key,value| vars[key]=value }
32
+ return vars
33
+ end
34
+
27
35
  # Returns the value of an envirionment variable
28
36
  def [](name)
29
37
  @variables[name]
@@ -60,26 +68,35 @@ module Fig
60
68
  end
61
69
  end
62
70
 
63
- def execute_config(base_package, package_name, config_name, version_name, args)
71
+ def execute_command(command, args, package)
72
+ with_environment do
73
+ argument =
74
+ expand_command_line_argument(
75
+ "#{command.command} #{args.join(' ')}"
76
+ )
77
+
78
+ yield expand_path(argument, package).split(' ')
79
+ end
80
+ end
81
+
82
+ def find_config_name_in_package(package_name)
83
+ return @applied_configs.key?(package_name) ? @applied_configs[package_name].first : 'default'
84
+ end
85
+
86
+ def execute_config(base_package, package_name, config_name, version_name, args, &block)
87
+ config_name ||= find_config_name_in_package(package_name)
64
88
  package = lookup_package(
65
89
  package_name || base_package.package_name,
66
90
  version_name,
67
91
  Backtrace.new(nil, package_name, version_name, config_name)
68
92
  )
69
- result = nil
70
- commands = package[config_name || 'default'].commands
71
- with_environment do
72
- # TODO nil check
73
- commands.each do |command|
74
- argument =
75
- expand_command_line_argument(
76
- "#{command.command} #{args.join(' ')}"
77
- )
78
-
79
- result = yield expand_path(argument, package).split(' ')
80
- end
93
+
94
+ command = package[config_name].command
95
+ if command
96
+ execute_command(command, args, package, &block)
97
+ else
98
+ raise UserInputError.new(%Q<The "#{package.to_s}" package with the "#{config_name}" configuration does not contain a command.>)
81
99
  end
82
- result
83
100
  end
84
101
 
85
102
  def apply_config_statement(base_package, statement, backtrace)
@@ -113,12 +130,6 @@ module Fig
113
130
  apply_config(package, config_name || 'default', new_backtrace)
114
131
  end
115
132
 
116
- def direct_retrieve(package_name, source_path, target_path)
117
- package = lookup_package(package_name, nil, nil)
118
- FileUtils.mkdir_p(target_path)
119
- FileUtils.cp_r(File.join(package.directory, source_path, '.'), target_path)
120
- end
121
-
122
133
  private
123
134
 
124
135
  def set_variable(base_package, name, value)