fig 0.1.67 → 0.1.69

Sign up to get free protection for your applications and to get access to all the features.
data/Changes CHANGED
@@ -1,3 +1,65 @@
1
+ v0.1.69
2
+
3
+ Backwards incompatibilities:
4
+
5
+ - While publishing, you cannot simultaneously have a package definition file
6
+ (e.g. "package.fig") and use environment variable options (--set/--append).
7
+ Previous to now, any package definition file would simply be ignored and
8
+ the publish would happen based upon the environment variable options.
9
+
10
+ - Easier to understand, yet unlikely to already exist case:
11
+
12
+ fig package/1.2.3 --publish --set VARIABLE=VALUE --file non-default.fig
13
+
14
+ Is this supposed to mean publish based upon the --set option or the
15
+ --file option? Again, it was the former, but that was non-obvious.
16
+
17
+ - More likely existing case:
18
+
19
+ fig package/1.2.3 --publish --set VARIABLE=VALUE
20
+
21
+ while there is a "package.fig" file in the current directory.
22
+ Workaround: use the "--no-file" option:
23
+
24
+ fig package/1.2.3 --publish --set VARIABLE=VALUE --no-file
25
+
26
+ Just to be clear, it's perfectly fine (and useful) to have combined a
27
+ package definition file and environment variable options when not
28
+ publishing.
29
+
30
+ New feature (and backwards incompatibility):
31
+
32
+ - Locks FIG_HOME when updating. (Or attempts to. If FIG_HOME is on NFS, all
33
+ bets are off.) By default, if Fig is updating and notices another instance
34
+ updating, it will fail. You can override this behavior via
35
+ --update-lock-response. Specify "wait" to get Fig to wait for lock release
36
+ or "ignore" for it to skip lock checking.
37
+
38
+ The default behavior of failing was chosen to prevent surprises in the
39
+ scenario of starting multiple servers out of the same directory:
40
+
41
+ for exchange in cme ice liffe cboe
42
+ do
43
+ fig --update -- run-server $exchange &
44
+ done
45
+
46
+ If Fig defaulted to waiting, the above scenario would silently cause three
47
+ out of the four servers to block until the other one's updates were
48
+ finished.
49
+
50
+ Bug fixes:
51
+
52
+ - Specifying --update with FIG_REMOTE_URL using FTP should be fast as it used
53
+ to be.
54
+
55
+ - Skips retrieving directories and files to themselves. (Tragic accident of
56
+ retrieving "." onto itself resulted in a corrupted git repo.)
57
+
58
+ v0.1.68.beta.2
59
+ v0.1.68.beta.1
60
+
61
+ - Test releases
62
+
1
63
  v0.1.67
2
64
 
3
65
  Backwards incompatibilities:
@@ -462,7 +524,7 @@ v0.1.42
462
524
 
463
525
  - Fig::Package refactoring.
464
526
 
465
- - "file:" protocol works for FIG_REMOTE_HOME.
527
+ - "file:" protocol works for FIG_REMOTE_URL.
466
528
 
467
529
  - Testing no longer requires ssh.
468
530
 
data/lib/fig.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Fig
2
- VERSION = '0.1.67'
2
+ VERSION = '0.1.69'
3
3
  end
@@ -1,4 +1,4 @@
1
- require 'rubygems'
1
+ require 'fileutils'
2
2
  require 'net/ftp'
3
3
  require 'set'
4
4
 
@@ -16,6 +16,7 @@ require 'fig/repository'
16
16
  require 'fig/repository_error'
17
17
  require 'fig/runtime_environment'
18
18
  require 'fig/statement/configuration'
19
+ require 'fig/update_lock'
19
20
  require 'fig/user_input_error'
20
21
  require 'fig/working_directory_maintainer'
21
22
 
@@ -23,9 +24,10 @@ module Fig; end
23
24
 
24
25
  # Main program
25
26
  class Fig::Command
26
- def run_fig(argv)
27
+ def run_fig(argv, options = nil)
27
28
  begin
28
- @options = Fig::Command::Options.new(argv)
29
+ @options = options || Fig::Command::Options.new()
30
+ @options.process_command_line(argv)
29
31
  rescue Fig::UserInputError => error
30
32
  $stderr.puts error.to_s # Logging isn't set up yet.
31
33
  return Fig::Command::Action::EXIT_FAILURE
@@ -67,7 +69,8 @@ class Fig::Command
67
69
  base_config(),
68
70
  @environment,
69
71
  @repository,
70
- @operating_system
72
+ @operating_system,
73
+ @package_source_description
71
74
  )
72
75
 
73
76
  actions.each do
@@ -84,25 +87,40 @@ class Fig::Command
84
87
  return Fig::Command::Action::EXIT_SUCCESS
85
88
  end
86
89
 
87
- def run_with_exception_handling(argv)
90
+ def run_with_exception_handling(argv, options = nil)
88
91
  begin
89
- return_code = run_fig(argv)
90
- return return_code
92
+ return run_fig(argv, options)
91
93
  rescue Fig::URLAccessError => error
92
94
  urls = error.urls.join(', ')
93
- $stderr.puts "Access to #{urls} in #{error.package}/#{error.version} not allowed."
94
- return Fig::Command::Action::EXIT_FAILURE
95
+ $stderr.puts \
96
+ "Access to #{urls} in #{error.package}/#{error.version} not allowed."
95
97
  rescue Fig::UserInputError => error
96
98
  log_error_message(error)
97
- return Fig::Command::Action::EXIT_FAILURE
98
99
  end
100
+
101
+ return Fig::Command::Action::EXIT_FAILURE
102
+ end
103
+
104
+ def add_publish_listener(listener)
105
+ @publish_listeners << listener
106
+
107
+ return
108
+ end
109
+
110
+ def initialize()
111
+ @publish_listeners = []
99
112
  end
100
113
 
101
114
  private
102
115
 
103
116
  ExecutionContext =
104
117
  Struct.new(
105
- :base_package, :base_config, :environment, :repository, :operating_system
118
+ :base_package,
119
+ :base_config,
120
+ :environment,
121
+ :repository,
122
+ :operating_system,
123
+ :package_source_description
106
124
  )
107
125
 
108
126
  def derive_remote_url()
@@ -119,17 +137,18 @@ class Fig::Command
119
137
  def check_include_statements_versions?()
120
138
  return false if @options.suppress_warning_include_statement_missing_version?
121
139
 
122
- suppressed_warnings = @configuration['suppress warnings']
140
+ suppressed_warnings = @application_configuration['suppress warnings']
123
141
  return true if not suppressed_warnings
124
142
 
125
143
  return ! suppressed_warnings.include?('include statement missing version')
126
144
  end
127
145
 
128
146
  def configure()
147
+ set_up_update_lock()
129
148
  set_up_application_configuration()
130
149
 
131
150
  Fig::Logging.initialize_post_configuration(
132
- @options.log_config() || @configuration['log configuration'],
151
+ @options.log_config() || @application_configuration['log configuration'],
133
152
  @options.log_level()
134
153
  )
135
154
 
@@ -139,8 +158,23 @@ class Fig::Command
139
158
  prepare_environment()
140
159
  end
141
160
 
161
+ def set_up_update_lock()
162
+ return if not @options.update_packages
163
+
164
+ update_lock_response = @options.update_lock_response
165
+ return if update_lock_response == :ignore
166
+
167
+ @update_lock = Fig::UpdateLock.new(@options.home, update_lock_response)
168
+
169
+ # *sigh* Ruby 1.8 doesn't support close_on_exec(), so we've got to ensure
170
+ # this stuff on our own.
171
+ Fig::AtExit.add { @update_lock.close }
172
+
173
+ return
174
+ end
175
+
142
176
  def set_up_application_configuration()
143
- @configuration = Fig::FigRC.find(
177
+ @application_configuration = Fig::FigRC.find(
144
178
  @options.figrc(),
145
179
  derive_remote_url(),
146
180
  @options.login?,
@@ -155,8 +189,8 @@ class Fig::Command
155
189
  @repository = Fig::Repository.new(
156
190
  @operating_system,
157
191
  @options.home(),
158
- @configuration,
159
- nil, # remote_user
192
+ @application_configuration,
193
+ @publish_listeners,
160
194
  check_include_statements_versions?
161
195
  )
162
196
 
@@ -209,8 +243,9 @@ class Fig::Command
209
243
  else
210
244
  @base_package = package_loader.load_package_object_from_file()
211
245
  end
246
+ @package_source_description = package_loader.package_source_description()
212
247
 
213
- applier = new_package_applier(package_loader.package_source_description())
248
+ applier = new_package_applier()
214
249
 
215
250
  if retrieves_should_happen
216
251
  applier.activate_retrieves()
@@ -233,7 +268,7 @@ class Fig::Command
233
268
 
234
269
  def new_package_loader()
235
270
  return Fig::Command::PackageLoader.new(
236
- @configuration,
271
+ @application_configuration,
237
272
  @descriptor,
238
273
  @options.package_definition_file,
239
274
  base_config(),
@@ -241,20 +276,20 @@ class Fig::Command
241
276
  )
242
277
  end
243
278
 
244
- def new_package_applier(package_source_description)
279
+ def new_package_applier()
245
280
  return Fig::Command::PackageApplier.new(
246
281
  @base_package,
247
282
  @environment,
248
283
  @options,
249
284
  @descriptor,
250
285
  base_config(),
251
- package_source_description
286
+ @package_source_description
252
287
  )
253
288
  end
254
289
 
255
- # If the user has specified a descriptor, than any package.fig or --file
256
- # option is ignored. Thus, in order to avoid confusing the user, we make
257
- # specifying both an error.
290
+ # If the user has specified a descriptor and we are not publishing, than any
291
+ # package.fig or --file option is ignored. Thus, in order to avoid confusing
292
+ # the user, we make specifying both an error.
258
293
  def ensure_descriptor_and_file_were_not_both_specified()
259
294
  file = @options.package_definition_file()
260
295
 
@@ -263,7 +298,7 @@ class Fig::Command
263
298
  # processed.
264
299
  file_specified = ! file.nil? && file != :none
265
300
 
266
- if @descriptor and file_specified
301
+ if @descriptor && file_specified
267
302
  raise Fig::UserInputError.new(
268
303
  %Q<Cannot specify both a package descriptor (#{@descriptor.original_string}) and the --file option (#{file}).>
269
304
  )
@@ -1,6 +1,13 @@
1
1
  module Fig; end
2
2
  class Fig::Command; end
3
3
 
4
+ # One of the main activities Fig should do as part of the current run.
5
+ #
6
+ # This exists because the code used to have complicated logic about whether a
7
+ # package.fig should be read, whether the Package object should be loaded,
8
+ # should a config be applied, when should some activity happen, etc. Now, we
9
+ # let the Action object say what it wants in terms of setup and then tell it to
10
+ # do whatever it needs to.
4
11
  module Fig::Command::Action
5
12
  EXIT_SUCCESS = 0
6
13
  EXIT_FAILURE = 1
@@ -34,7 +34,7 @@ class Fig::Command::Action::Publish
34
34
  Fig::Logging.info "#{@descriptor.to_string()} has already been published."
35
35
 
36
36
  if not @force
37
- raise UserInputError.new(
37
+ raise Fig::UserInputError.new(
38
38
  'Use the --force option if you really want to overwrite.'
39
39
  )
40
40
  else
@@ -44,7 +44,11 @@ class Fig::Command::Action::Publish
44
44
 
45
45
  Fig::Logging.info "Publishing #{@descriptor.to_string()}."
46
46
  @execution_context.repository.publish_package(
47
- @publish_statements, @descriptor, false
47
+ @publish_statements,
48
+ @descriptor,
49
+ false,
50
+ @execution_context.base_package,
51
+ @force
48
52
  )
49
53
 
50
54
  return EXIT_SUCCESS
@@ -21,7 +21,11 @@ class Fig::Command::Action::PublishLocal
21
21
 
22
22
  Fig::Logging.info "Publishing #{@descriptor.to_string()}."
23
23
  @execution_context.repository.publish_package(
24
- @publish_statements, @descriptor, :publish_local
24
+ @publish_statements,
25
+ @descriptor,
26
+ :publish_local,
27
+ @execution_context.base_package,
28
+ false
25
29
  )
26
30
 
27
31
  return EXIT_SUCCESS
@@ -1,3 +1,4 @@
1
+ require 'fig/command/package_loader'
1
2
  require 'fig/package'
2
3
  require 'fig/statement/configuration'
3
4
  require 'fig/user_input_error'
@@ -59,20 +60,8 @@ module Fig::Command::Action::Role::Publish
59
60
  )
60
61
  end
61
62
 
62
- # TODO: fail on environment statements && --file because the --file will
63
- # get ignored as far as statements are concerned.
64
- publish_statements = nil
65
63
  if not @environment_statements.empty?
66
- @publish_statements =
67
- @package_contents_statements +
68
- [
69
- Fig::Statement::Configuration.new(
70
- nil,
71
- nil,
72
- Fig::Package::DEFAULT_CONFIG,
73
- @environment_statements
74
- )
75
- ]
64
+ derive_publish_statements_from_environment_statements
76
65
  elsif not @package_contents_statements.empty?
77
66
  raise Fig::UserInputError.new(
78
67
  '--resource/--archive options were specified, but no --set/--append option was given. Will not publish.'
@@ -87,4 +76,36 @@ module Fig::Command::Action::Role::Publish
87
76
 
88
77
  return
89
78
  end
79
+
80
+ def derive_publish_statements_from_environment_statements
81
+ if @execution_context.package_source_description
82
+ message = 'Cannot publish based upon both a package definition file ('
83
+ message << @execution_context.package_source_description
84
+ message << ') and --set/--append options.'
85
+
86
+ if @execution_context.package_source_description ==
87
+ Fig::Command::PackageLoader::DEFAULT_FIG_FILE
88
+
89
+ message << "\n\n"
90
+ message << 'You can avoid loading '
91
+ message << Fig::Command::PackageLoader::DEFAULT_FIG_FILE
92
+ message << ' by using the --no-file option.'
93
+ end
94
+
95
+ raise Fig::UserInputError.new(message)
96
+ end
97
+
98
+ @publish_statements =
99
+ @package_contents_statements +
100
+ [
101
+ Fig::Statement::Configuration.new(
102
+ nil,
103
+ nil,
104
+ Fig::Package::DEFAULT_CONFIG,
105
+ @environment_statements
106
+ )
107
+ ]
108
+
109
+ return
110
+ end
90
111
  end
@@ -19,8 +19,12 @@ class Fig::Command::Action::Version
19
19
  return true
20
20
  end
21
21
 
22
+ def configure(options)
23
+ @version_message = options.version_message
24
+ end
25
+
22
26
  def execute()
23
- puts File.basename($0) + ' v' + Fig::VERSION
27
+ puts @version_message || File.basename($0) + ' v' + Fig::VERSION
24
28
 
25
29
  return EXIT_SUCCESS
26
30
  end
@@ -1,5 +1,3 @@
1
- require 'optparse'
2
-
3
1
  require 'fig/command/action/clean'
4
2
  require 'fig/command/action/get'
5
3
  require 'fig/command/action/help'
@@ -24,7 +22,7 @@ require 'fig/command/action/update'
24
22
  require 'fig/command/action/update_if_missing'
25
23
  require 'fig/command/action/version'
26
24
  require 'fig/command/option_error'
27
- require 'fig/package'
25
+ require 'fig/command/options/parser'
28
26
  require 'fig/package_descriptor'
29
27
  require 'fig/statement/archive'
30
28
  require 'fig/statement/include'
@@ -37,55 +35,6 @@ class Fig::Command; end
37
35
 
38
36
  # Command-line processing.
39
37
  class Fig::Command::Options
40
- USAGE = <<-EOF
41
- Usage:
42
-
43
- fig [...] [DESCRIPTOR] [--update | --update-if-missing] [-- COMMAND]
44
- fig [...] [DESCRIPTOR] [--update | --update-if-missing] [--command-extra-args VALUES]
45
-
46
- fig {--publish | --publish-local} DESCRIPTOR
47
- [--resource PATH]
48
- [--archive PATH]
49
- [--include DESCRIPTOR]
50
- [--override DESCRIPTOR]
51
- [--force]
52
- [...]
53
-
54
- fig --clean DESCRIPTOR [...]
55
-
56
- fig --get VARIABLE [DESCRIPTOR] [...]
57
- fig --list-configs [DESCRIPTOR] [...]
58
- fig --list-dependencies [--list-tree] [--list-all-configs] [DESCRIPTOR] [...]
59
- fig --list-variables [--list-tree] [--list-all-configs] [DESCRIPTOR] [...]
60
- fig {--list-local | --list-remote} [...]
61
-
62
- fig {--version | --help}
63
-
64
-
65
- A DESCRIPTOR looks like <package name>[/<version>][:<config>] e.g. "foo",
66
- "foo/1.2.3", and "foo/1.2.3:default". Whether ":<config>" and "/<version>" are
67
- required or allowed is dependent upon what your are doing.
68
-
69
- Standard options (represented as "[...]" above):
70
-
71
- [--set VARIABLE=VALUE]
72
- [--append VARIABLE=VALUE]
73
- [--file PATH] [--no-file]
74
- [--config CONFIG]
75
- [--login]
76
- [--log-level LEVEL] [--log-config PATH]
77
- [--figrc PATH] [--no-figrc]
78
- [--suppress-warning-include-statement-missing-version]
79
-
80
- Environment variables:
81
-
82
- FIG_REMOTE_URL (required),
83
- FIG_HOME (path to local repository cache, defaults to $HOME/.fighome).
84
- EOF
85
-
86
- LOG_LEVELS = %w[ off fatal error warn info debug all ]
87
- LOG_ALIASES = { 'warning' => 'warn' }
88
-
89
38
  # Public version of #strip_shell_command() here so that it can be kept in
90
39
  # sync.
91
40
  def self.strip_shell_command(argv)
@@ -107,14 +56,57 @@ Environment variables:
107
56
  return argv
108
57
  end
109
58
 
110
- attr_reader :shell_command
111
- attr_reader :command_extra_argv
112
- attr_reader :descriptor
113
- attr_reader :exit_code
114
- attr_reader :update_packages
59
+ attr_reader :command_extra_argv
60
+ attr_reader :config
61
+ attr_reader :descriptor
62
+ attr_reader :environment_statements
63
+ attr_reader :exit_code
64
+ attr_reader :figrc
65
+ attr_reader :home
66
+ attr_reader :log_config
67
+ attr_reader :log_level
68
+ attr_reader :package_contents_statements
69
+ attr_reader :package_definition_file
70
+ attr_reader :parser
71
+ attr_reader :shell_command
72
+ attr_reader :update_lock_response
73
+ attr_reader :update_packages
74
+ attr_reader :variable_to_get
75
+ attr_accessor :version_message
76
+
77
+ def initialize()
78
+ @home = ENV['FIG_HOME'] || File.expand_path('~/.fighome')
79
+ @parser = Fig::Command::Options::Parser.new()
80
+ end
81
+
82
+ def process_command_line(argv)
83
+ argv = argv.clone
84
+ strip_shell_command(argv)
85
+
86
+ set_up_parser()
87
+ @help_message = @parser.help
88
+
89
+ @parser.parse!(argv)
90
+
91
+ if not exit_code.nil?
92
+ return
93
+ end
94
+
95
+ if argv.size > 1
96
+ $stderr.puts %q<Extra arguments. Should only have a package/version after all other options. Had "> + argv.join(%q<", ">) + %q<" left over.>
97
+ @exit_code = 1
98
+ return
99
+ end
100
+
101
+ derive_primary_descriptor(argv.first)
102
+ if not @base_action and @descriptor
103
+ set_base_action(Fig::Command::Action::RunCommandStatement)
104
+ end
105
+ set_up_sub_actions()
115
106
 
116
- def initialize(argv)
117
- process_command_line(argv)
107
+ actions().each {|action| action.configure(self)}
108
+
109
+ return
118
110
  end
119
111
 
120
112
  def actions()
@@ -132,65 +124,29 @@ Environment variables:
132
124
  return actions
133
125
  end
134
126
 
135
- def config()
136
- return @options[:config]
137
- end
138
-
139
- def figrc()
140
- return @options[:figrc]
141
- end
142
-
143
127
  def force?()
144
- return @options[:force]
128
+ return @force
145
129
  end
146
130
 
147
- def variable_to_get()
148
- return @options[:variable_to_get]
149
- end
150
-
151
- def home()
152
- return @options[:home]
153
- end
131
+ def help_message()
132
+ return @help_message + <<-'END_MESSAGE'
133
+ -- end of Fig options; anything after this is used as a command to run
134
+ --command-extra-args end of Fig options; anything after this is appended to the end of a
135
+ "command" statement in a "config" block.
154
136
 
155
- def log_config()
156
- return @options[:log_config]
137
+ END_MESSAGE
157
138
  end
158
139
 
159
140
  def login?()
160
- return @options[:login]
161
- end
162
-
163
- def log_level()
164
- return @options[:log_level]
141
+ return @login
165
142
  end
166
143
 
167
144
  def no_figrc?()
168
- return @options[:no_figrc]
169
- end
170
-
171
- def environment_statements()
172
- return @options[:environment_statements]
173
- end
174
-
175
- def package_definition_file()
176
- return @options[:package_definition_file]
177
- end
178
-
179
- def package_contents_statements()
180
- return @options[:package_contents_statements]
145
+ return @no_figrc
181
146
  end
182
147
 
183
148
  def suppress_warning_include_statement_missing_version?()
184
- return @options[:suppress_warning_include_statement_missing_version]
185
- end
186
-
187
- def help_message()
188
- return @help_message + <<-'END_MESSAGE'
189
- -- end of Fig options; anything after this is used as a command to run
190
- --command-extra-args end of Fig options; anything after this is appended to the end of a
191
- "command" statement in a "config" block.
192
-
193
- END_MESSAGE
149
+ return @suppress_warning_include_statement_missing_version
194
150
  end
195
151
 
196
152
  private
@@ -200,64 +156,12 @@ Environment variables:
200
156
  # regex with "\A" and "\z".
201
157
  STARTS_WITH_NON_HYPHEN = %r< \A [^-] .* >x
202
158
 
203
- ARGUMENT_DESCRIPTION = {
204
- '--set' => Fig::Statement::Set::ARGUMENT_DESCRIPTION,
205
- '--append' => Fig::Statement::Path::ARGUMENT_DESCRIPTION
206
- }
207
-
208
- def list_tree?()
209
- return @options[:list_tree]
210
- end
211
-
212
159
  def list_all_configs?()
213
- return @options[:list_all_configs]
160
+ return @list_all_configs
214
161
  end
215
162
 
216
- def process_command_line(argv)
217
- argv = argv.clone
218
- strip_shell_command(argv)
219
-
220
- @switches = []
221
- @options = {}
222
-
223
- @options[:home] = ENV['FIG_HOME'] || File.expand_path('~/.fighome')
224
-
225
- parser = new_parser()
226
- @help_message = parser.help
227
-
228
- begin
229
- parser.parse!(argv)
230
- rescue OptionParser::InvalidArgument => error
231
- raise_invalid_argument(error.args[0], error.args[1])
232
- rescue OptionParser::MissingArgument => error
233
- raise_missing_argument(error.args[0])
234
- rescue OptionParser::InvalidOption => error
235
- raise Fig::Command::OptionError.new(
236
- "Unknown option #{error.args[0]}.\n\n#{USAGE}"
237
- )
238
- rescue OptionParser::ParseError => error
239
- raise Fig::Command::OptionError.new(error.to_s)
240
- end
241
-
242
- if not exit_code.nil?
243
- return
244
- end
245
-
246
- if argv.size > 1
247
- $stderr.puts %q<Extra arguments. Should only have a package/version after all other options. Had "> + argv.join(%q<", ">) + %q<" left over.>
248
- @exit_code = 1
249
- return
250
- end
251
-
252
- derive_primary_descriptor(argv.first)
253
- if not @base_action and @descriptor
254
- set_base_action(Fig::Command::Action::RunCommandStatement)
255
- end
256
- set_up_sub_actions()
257
-
258
- actions().each {|action| action.configure(self)}
259
-
260
- return
163
+ def list_tree?()
164
+ return @list_tree
261
165
  end
262
166
 
263
167
  def strip_shell_command(argv)
@@ -282,78 +186,45 @@ Environment variables:
282
186
  return
283
187
  end
284
188
 
285
- def raise_missing_argument(option)
286
- raise Fig::Command::OptionError.new(
287
- "Please provide a value for #{option}."
288
- )
289
- end
189
+ def set_up_parser
190
+ set_up_queries()
191
+ set_up_commands()
192
+ set_up_package_configuration_source()
193
+ set_up_environment_statements()
194
+ set_up_package_contents_statements()
195
+ set_up_remote_repository_access()
196
+ set_up_program_configuration()
290
197
 
291
- def raise_invalid_argument(option, value)
292
- # *sigh* OptionParser does not raise MissingArgument for the case of an
293
- # option with a required value being followed by another option. It
294
- # assigns the next option as the value instead. E.g. for
295
- #
296
- # fig --set --get FOO
297
- #
298
- # it assigns "--get" as the value of the "--set" option.
299
- switch_strings =
300
- (@switches.collect {|switch| [switch.short, switch.long]}).flatten
301
- if switch_strings.any? {|string| string == value}
302
- raise_missing_argument(option)
303
- end
304
-
305
- description = ARGUMENT_DESCRIPTION[option]
306
- if description.nil?
307
- description = ''
308
- else
309
- description = ' ' + description
310
- end
311
-
312
- raise Fig::Command::OptionError.new(
313
- %Q<Invalid value for #{option}: "#{value}".#{description}>
314
- )
315
- end
316
-
317
- def new_parser
318
- return OptionParser.new do |parser|
319
- set_up_queries(parser)
320
- set_up_commands(parser)
321
- set_up_package_configuration_source(parser)
322
- set_up_environment_statements(parser)
323
- set_up_package_contents_statements(parser)
324
- set_up_remote_repository_access(parser)
325
- set_up_program_configuration(parser)
326
- end
198
+ return
327
199
  end
328
200
 
329
- def set_up_queries(parser)
330
- parser.banner = "#{USAGE}\n"
331
- @switches << parser.define_tail(
201
+ def set_up_queries()
202
+ @parser.on_tail(
332
203
  '-?', '-h','--help','display this help text'
333
204
  ) do
334
205
  set_base_action(Fig::Command::Action::Help)
335
206
  end
336
207
 
337
- @switches << parser.define_tail('-v', '--version', 'print Fig version') do
208
+ @parser.on_tail('-v', '--version', 'print Fig version') do
338
209
  set_base_action(Fig::Command::Action::Version)
339
210
  end
340
211
 
341
- @switches << parser.define(
212
+ @parser.on(
342
213
  '-g',
343
214
  '--get VARIABLE',
344
215
  STARTS_WITH_NON_HYPHEN,
345
216
  'print value of environment variable VARIABLE'
346
217
  ) do |variable_to_get|
347
218
  set_base_action(Fig::Command::Action::Get)
348
- @options[:variable_to_get] = variable_to_get
219
+ @variable_to_get = variable_to_get
349
220
  end
350
221
 
351
- set_up_listings(parser)
222
+ set_up_listings()
352
223
 
353
224
  return
354
225
  end
355
226
 
356
- def set_up_listings(parser)
227
+ def set_up_listings()
357
228
  option_mapping = {
358
229
  :local_packages => [
359
230
  ['--list-local', '--list', 'list packages in $FIG_HOME'],
@@ -388,39 +259,39 @@ Environment variables:
388
259
  | type, specification_action_class |
389
260
 
390
261
  specification, action_class = *specification_action_class
391
- @switches << parser.define(*specification) do
262
+ @parser.on(*specification) do
392
263
  set_base_action(action_class)
393
264
  end
394
265
  end
395
266
 
396
- @switches << parser.define(
267
+ @parser.on(
397
268
  '--list-tree', 'for listings, output a tree instead of a list'
398
269
  ) do
399
- @options[:list_tree] = true
270
+ @list_tree = true
400
271
  end
401
272
 
402
- @switches << parser.define(
273
+ @parser.on(
403
274
  '--list-all-configs',
404
275
  'for listings, follow all configurations of the base package'
405
276
  ) do
406
- @options[:list_all_configs] = true
277
+ @list_all_configs = true
407
278
  end
408
279
 
409
280
  return
410
281
  end
411
282
 
412
- def set_up_commands(parser)
413
- @switches << parser.define('--clean', 'remove package from $FIG_HOME') do
283
+ def set_up_commands()
284
+ @parser.on('--clean', 'remove package from $FIG_HOME') do
414
285
  set_base_action(Fig::Command::Action::Clean)
415
286
  end
416
287
 
417
- @switches << parser.define(
288
+ @parser.on(
418
289
  '--publish', 'install package in $FIG_HOME and in remote repo'
419
290
  ) do |publish|
420
291
  set_base_action(Fig::Command::Action::Publish)
421
292
  end
422
293
 
423
- @switches << parser.define(
294
+ @parser.on(
424
295
  '--publish-local', 'install package only in $FIG_HOME'
425
296
  ) do |publish_local|
426
297
  set_base_action(Fig::Command::Action::PublishLocal)
@@ -439,57 +310,63 @@ Environment variables:
439
310
  \z
440
311
  >x
441
312
 
442
- def set_up_package_configuration_source(parser)
443
- @switches << parser.define(
313
+ def set_up_package_configuration_source()
314
+ @parser.on(
444
315
  '-c',
445
316
  '--config CONFIG',
446
317
  STARTS_WITH_NON_HYPHEN,
447
318
  %q<apply configuration CONFIG, default is "default">
448
319
  ) do |config|
449
- @options[:config] = config
320
+ @config = config
450
321
  end
451
322
 
452
- @options[:package_definition_file] = nil
453
- @switches << parser.define(
323
+ @package_definition_file = nil
324
+ @parser.on(
454
325
  '--file FILE',
455
326
  FILE_OPTION_VALUE_PATTERN,
456
327
  %q<read Fig file FILE. Use '-' for stdin. See also --no-file>
457
328
  ) do |path|
458
- @options[:package_definition_file] = path
329
+ @package_definition_file = path
459
330
  end
460
331
 
461
- @switches << parser.define(
332
+ @parser.on(
462
333
  '--no-file', 'ignore package.fig file in current directory'
463
334
  ) do |path|
464
- @options[:package_definition_file] = :none
335
+ @package_definition_file = :none
465
336
  end
466
337
 
467
338
  return
468
339
  end
469
340
 
470
- def set_up_environment_statements(parser)
471
- @options[:environment_statements] = []
472
- @switches << parser.define(
341
+ def set_up_environment_statements()
342
+ @environment_statements = []
343
+ @parser.on(
473
344
  '-p',
474
345
  '--append VARIABLE=VALUE',
475
346
  STARTS_WITH_NON_HYPHEN,
476
347
  'append (actually, prepend) VALUE to PATH-like environment variable VARIABLE'
477
348
  ) do |name_value|
478
- @options[:environment_statements] <<
349
+ @environment_statements <<
479
350
  new_variable_statement('--append', name_value, Fig::Statement::Path)
480
351
  end
352
+ @parser.add_argument_description(
353
+ %w<-p --append>, Fig::Statement::Path::ARGUMENT_DESCRIPTION
354
+ )
481
355
 
482
- @switches << parser.define(
356
+ @parser.on(
483
357
  '-s',
484
358
  '--set VARIABLE=VALUE',
485
359
  STARTS_WITH_NON_HYPHEN,
486
360
  'set environment variable VARIABLE to VALUE'
487
361
  ) do |name_value|
488
- @options[:environment_statements] <<
362
+ @environment_statements <<
489
363
  new_variable_statement('--set', name_value, Fig::Statement::Set)
490
364
  end
365
+ @parser.add_argument_description(
366
+ %w<-s --set>, Fig::Statement::Set::ARGUMENT_DESCRIPTION
367
+ )
491
368
 
492
- @switches << parser.define(
369
+ @parser.on(
493
370
  '-i',
494
371
  '--include DESCRIPTOR',
495
372
  STARTS_WITH_NON_HYPHEN,
@@ -509,10 +386,10 @@ Environment variables:
509
386
  # We've never allowed versionless includes from the command-line. Hooray!
510
387
  statement.complain_if_version_missing()
511
388
 
512
- @options[:environment_statements] << statement
389
+ @environment_statements << statement
513
390
  end
514
391
 
515
- @switches << parser.define(
392
+ @parser.on(
516
393
  '--override DESCRIPTOR',
517
394
  STARTS_WITH_NON_HYPHEN,
518
395
  'dictate version of package as specified in DESCRIPTOR'
@@ -527,37 +404,37 @@ Environment variables:
527
404
  nil, '--override option', descriptor.name, descriptor.version
528
405
  )
529
406
 
530
- @options[:environment_statements] << statement
407
+ @environment_statements << statement
531
408
  end
532
409
 
533
410
  return
534
411
  end
535
412
 
536
- def set_up_package_contents_statements(parser)
537
- @options[:package_contents_statements] = []
538
- @switches << parser.define(
413
+ def set_up_package_contents_statements()
414
+ @package_contents_statements = []
415
+ @parser.on(
539
416
  '--archive PATH',
540
417
  STARTS_WITH_NON_HYPHEN,
541
418
  'include PATH archive in package (when using --publish)'
542
419
  ) do |path|
543
- @options[:package_contents_statements] <<
420
+ @package_contents_statements <<
544
421
  Fig::Statement::Archive.new(nil, '--archive option', path)
545
422
  end
546
423
 
547
- @switches << parser.define(
424
+ @parser.on(
548
425
  '--resource PATH',
549
426
  STARTS_WITH_NON_HYPHEN,
550
427
  'include PATH resource in package (when using --publish)'
551
428
  ) do |path|
552
- @options[:package_contents_statements] <<
429
+ @package_contents_statements <<
553
430
  Fig::Statement::Resource.new(nil, '--resource option', path)
554
431
  end
555
432
 
556
433
  return
557
434
  end
558
435
 
559
- def set_up_remote_repository_access(parser)
560
- @switches << parser.define(
436
+ def set_up_remote_repository_access()
437
+ @parser.on(
561
438
  '-u',
562
439
  '--update',
563
440
  'check remote repo for updates and download to $FIG_HOME as necessary'
@@ -565,7 +442,7 @@ Environment variables:
565
442
  set_update_action(Fig::Command::Action::Update, :unconditionally)
566
443
  end
567
444
 
568
- @switches << parser.define(
445
+ @parser.on(
569
446
  '-m',
570
447
  '--update-if-missing',
571
448
  'check remote repo for updates only if package missing from $FIG_HOME'
@@ -573,58 +450,73 @@ Environment variables:
573
450
  set_update_action(Fig::Command::Action::UpdateIfMissing, :if_missing)
574
451
  end
575
452
 
576
- @switches << parser.define(
453
+ @parser.on(
577
454
  '-l', '--login', 'login to remote repo as a non-anonymous user'
578
455
  ) do
579
- @options[:login] = true
456
+ @login = true
580
457
  end
581
458
 
582
- @options[:force] = nil
583
- @switches << parser.define(
459
+ @force = nil
460
+ @parser.on(
584
461
  '--force',
585
462
  'force-overwrite existing version of a package to the remote repo'
586
463
  ) do |force|
587
- @options[:force] = force
464
+ @force = force
588
465
  end
589
466
 
590
467
  return
591
468
  end
592
469
 
593
- def set_up_program_configuration(parser)
594
- @switches << parser.define(
470
+ LOG_LEVELS = %w< off fatal error warn info debug all >
471
+ LOG_ALIASES = { 'warning' => 'warn' }
472
+
473
+ def set_up_program_configuration()
474
+ @parser.on(
595
475
  '--figrc PATH',
596
476
  STARTS_WITH_NON_HYPHEN,
597
477
  'add PATH to configuration used for Fig'
598
478
  ) do |path|
599
- @options[:figrc] = path
479
+ @figrc = path
600
480
  end
601
481
 
602
- @switches << parser.define('--no-figrc', 'ignore ~/.figrc') { @options[:no_figrc] = true }
482
+ @parser.on('--no-figrc', 'ignore ~/.figrc') { @no_figrc = true }
603
483
 
604
- @switches << parser.define(
484
+ @parser.on(
605
485
  '--log-config PATH',
606
486
  STARTS_WITH_NON_HYPHEN,
607
487
  'use PATH file as configuration for Log4r'
608
488
  ) do |path|
609
- @options[:log_config] = path
489
+ @log_config = path
610
490
  end
611
491
 
612
492
  level_list = LOG_LEVELS.join(', ')
613
- @switches << parser.define(
493
+ @parser.on(
614
494
  '--log-level LEVEL',
615
495
  LOG_LEVELS,
616
496
  LOG_ALIASES,
617
497
  'set logging level to LEVEL',
618
498
  " (#{level_list})"
619
499
  ) do |log_level|
620
- @options[:log_level] = log_level
500
+ @log_level = log_level
501
+ end
502
+
503
+ @update_lock_response = :fail
504
+ update_lock_responses = [:fail, :wait, :ignore]
505
+ response_list = update_lock_responses.join(', ')
506
+ @parser.on(
507
+ '--update-lock-response TYPE',
508
+ update_lock_responses,
509
+ 'what to do when update lock already exists',
510
+ " (#{response_list}, default is fail)"
511
+ ) do |response|
512
+ @update_lock_response = response
621
513
  end
622
514
 
623
- @switches << parser.define(
515
+ @parser.on(
624
516
  '--suppress-warning-include-statement-missing-version',
625
517
  %q<don't complain about "include package" without a version>
626
518
  ) do
627
- @options[:suppress_warning_include_statement_missing_version] = true
519
+ @suppress_warning_include_statement_missing_version = true
628
520
  end
629
521
 
630
522
  return
@@ -665,7 +557,7 @@ Environment variables:
665
557
 
666
558
  def new_variable_statement(option, name_value, statement_class)
667
559
  variable, value = statement_class.parse_name_value(name_value) {
668
- raise_invalid_argument(option, name_value)
560
+ @parser.raise_invalid_argument(option, name_value)
669
561
  }
670
562
 
671
563
  return statement_class.new(nil, "#{option} option", variable, value)