fig 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. data/Changes +94 -0
  2. data/lib/fig.rb +1 -1
  3. data/lib/fig/command.rb +18 -7
  4. data/lib/fig/command/action/dump_package_definition_for_command_line.rb +2 -2
  5. data/lib/fig/command/action/dump_package_definition_parsed.rb +2 -2
  6. data/lib/fig/command/action/dump_package_definition_text.rb +2 -2
  7. data/lib/fig/command/action/source_package.rb +65 -0
  8. data/lib/fig/command/options.rb +64 -15
  9. data/lib/fig/command/options/parser.rb +24 -14
  10. data/lib/fig/command/package_applier.rb +32 -7
  11. data/lib/fig/command/package_loader.rb +16 -7
  12. data/lib/fig/external_program.rb +72 -0
  13. data/lib/fig/figrc.rb +1 -1
  14. data/lib/fig/grammar/v0.rb +2 -2
  15. data/lib/fig/grammar/v0.treetop +2 -2
  16. data/lib/fig/grammar/v1.rb +17 -1737
  17. data/lib/fig/grammar/v1.treetop +6 -217
  18. data/lib/fig/grammar/v1_base.rb +1750 -0
  19. data/lib/fig/grammar/v1_base.treetop +229 -0
  20. data/lib/fig/grammar/v2.rb +508 -0
  21. data/lib/fig/grammar/v2.treetop +65 -0
  22. data/lib/fig/grammar_monkey_patches.rb +7 -0
  23. data/lib/fig/no_such_package_config_error.rb +3 -1
  24. data/lib/fig/not_yet_parsed_package.rb +27 -0
  25. data/lib/fig/operating_system.rb +5 -5
  26. data/lib/fig/package.rb +20 -2
  27. data/lib/fig/package_definition_text_assembler.rb +2 -1
  28. data/lib/fig/package_descriptor.rb +11 -4
  29. data/lib/fig/parser.rb +44 -58
  30. data/lib/fig/parser_package_build_state.rb +39 -4
  31. data/lib/fig/protocol/file.rb +2 -2
  32. data/lib/fig/protocol/ftp.rb +15 -10
  33. data/lib/fig/protocol/http.rb +1 -1
  34. data/lib/fig/protocol/netrc_enabled.rb +29 -16
  35. data/lib/fig/protocol/sftp.rb +19 -12
  36. data/lib/fig/repository.rb +33 -21
  37. data/lib/fig/repository_package_publisher.rb +129 -8
  38. data/lib/fig/runtime_environment.rb +114 -28
  39. data/lib/fig/statement/include.rb +21 -4
  40. data/lib/fig/statement/include_file.rb +94 -0
  41. data/lib/fig/unparser.rb +15 -7
  42. data/lib/fig/unparser/v1.rb +2 -80
  43. data/lib/fig/unparser/v1_base.rb +85 -0
  44. data/lib/fig/unparser/v2.rb +55 -0
  45. data/lib/fig/working_directory_maintainer.rb +12 -0
  46. metadata +61 -51
@@ -2,15 +2,17 @@ require 'stringio'
2
2
 
3
3
  require 'fig/include_backtrace'
4
4
  require 'fig/logging'
5
+ require 'fig/not_yet_parsed_package'
5
6
  require 'fig/package'
6
7
  require 'fig/package_descriptor'
7
8
  require 'fig/repository_error'
8
9
  require 'fig/statement/include'
10
+ require 'fig/statement/include_file'
9
11
  require 'fig/statement/override'
10
12
  require 'fig/statement/path'
11
13
  require 'fig/statement/set'
12
- require 'fig/user_input_error'
13
14
  require 'fig/unparser'
15
+ require 'fig/user_input_error'
14
16
 
15
17
  module Fig; end
16
18
 
@@ -24,16 +26,19 @@ class Fig::RuntimeEnvironment
24
26
 
25
27
  def initialize(
26
28
  repository,
29
+ parser,
27
30
  suppress_includes,
28
31
  variables_override,
29
32
  working_directory_maintainer
30
33
  )
31
34
  @repository = repository
35
+ @parser = parser
32
36
  @suppress_includes = suppress_includes
33
37
  @variables =
34
38
  variables_override || Fig::OperatingSystem.get_environment_variables()
35
39
  @retrieves = {}
36
- @packages = {}
40
+ @named_packages = {}
41
+ @packages_from_files = {}
37
42
  @working_directory_maintainer = working_directory_maintainer
38
43
  end
39
44
 
@@ -74,13 +79,13 @@ class Fig::RuntimeEnvironment
74
79
  )
75
80
  end
76
81
 
77
- @packages[name] = package
82
+ @named_packages[name] = package
78
83
 
79
84
  return
80
85
  end
81
86
 
82
87
  def get_package(name)
83
- return @packages[name]
88
+ return @named_packages[name]
84
89
  end
85
90
 
86
91
  def apply_config(package, config_name, backtrace)
@@ -88,6 +93,10 @@ class Fig::RuntimeEnvironment
88
93
  return
89
94
  end
90
95
 
96
+ Fig::Logging.debug(
97
+ "Applying #{package.to_descriptive_string_with_config config_name}."
98
+ )
99
+
91
100
  new_backtrace = backtrace ||
92
101
  Fig::IncludeBacktrace.new(
93
102
  nil,
@@ -99,11 +108,13 @@ class Fig::RuntimeEnvironment
99
108
  )
100
109
  )
101
110
 
102
- config = package[config_name]
111
+ config = nil
112
+ begin
113
+ config = package[config_name]
114
+ rescue Fig::NoSuchPackageConfigError => error
115
+ raise_repository_error(error.message, new_backtrace, error.package)
116
+ end
103
117
 
104
- Fig::Logging.debug(
105
- "Applying #{package.to_descriptive_string_with_config config_name}."
106
- )
107
118
  package.add_applied_config_name(config_name)
108
119
  config.statements.each do
109
120
  |statement|
@@ -155,7 +166,11 @@ class Fig::RuntimeEnvironment
155
166
  when Fig::Statement::Set
156
167
  set_variable(package, statement, backtrace)
157
168
  when Fig::Statement::Include
158
- include_config(package, statement.descriptor, backtrace)
169
+ include_config(package, statement, backtrace)
170
+ when Fig::Statement::IncludeFile
171
+ include_file_config(
172
+ package, statement.path, statement.config_name, backtrace
173
+ )
159
174
  when Fig::Statement::Override
160
175
  backtrace.add_override(statement)
161
176
  end
@@ -180,20 +195,46 @@ class Fig::RuntimeEnvironment
180
195
 
181
196
  private
182
197
 
183
- def include_config(starting_package, descriptor, backtrace)
198
+ def include_config(starting_package, include_statement, backtrace)
184
199
  # Because package application starts with the synthetic package for the
185
200
  # command-line, we can't really disable includes, full stop. Instead, we
186
201
  # use the flag on the base package to break the chain of includes.
187
- #
188
- # Alternative approach: We could put a flag on synthetic include statements
189
- # that says to always apply them.
190
202
  return if starting_package.base? && @suppress_includes == :all
191
203
 
204
+ package, resolved_descriptor, new_backtrace =
205
+ determine_included_package starting_package, include_statement, backtrace
206
+
207
+ return if \
208
+ starting_package.base? \
209
+ && @suppress_includes == :cross_package \
210
+ && package != starting_package
211
+
212
+ apply_config(
213
+ package,
214
+ resolved_descriptor.config || Fig::Package::DEFAULT_CONFIG,
215
+ new_backtrace
216
+ )
217
+
218
+ return
219
+ end
220
+
221
+ def determine_included_package(starting_package, include_statement, backtrace)
222
+ descriptor = include_statement.descriptor
223
+
224
+ if ! include_statement.included_package.nil?
225
+ return \
226
+ include_statement.included_package,
227
+ descriptor,
228
+ Fig::IncludeBacktrace.new(backtrace, descriptor)
229
+ end
230
+
192
231
  resolved_descriptor = nil
193
232
 
194
233
  # Check to see if this include has been overridden.
195
- if backtrace
234
+ if (
235
+ backtrace and
196
236
  override_package_name = descriptor.name || starting_package.name
237
+ )
197
238
  override = backtrace.get_override(override_package_name)
198
239
  if override
199
240
  resolved_descriptor =
@@ -205,21 +246,33 @@ class Fig::RuntimeEnvironment
205
246
  resolved_descriptor ||= descriptor
206
247
 
207
248
  new_backtrace = Fig::IncludeBacktrace.new(backtrace, resolved_descriptor)
208
- package = lookup_package(
209
- resolved_descriptor.name || starting_package.name,
210
- resolved_descriptor.version,
211
- new_backtrace
212
- )
249
+ package = nil
213
250
 
214
- return if \
215
- starting_package.base? \
216
- && @suppress_includes == :cross_package \
217
- && package != starting_package
251
+ if included_name = resolved_descriptor.name || starting_package.name
252
+ package = lookup_package(
253
+ included_name, resolved_descriptor.version, new_backtrace
254
+ )
255
+ else
256
+ package = starting_package
257
+ end
258
+
259
+ return package, resolved_descriptor, new_backtrace
260
+ end
261
+
262
+ def include_file_config(including_package, path, config_name, backtrace)
263
+ return if @suppress_includes
264
+
265
+ full_path = File.absolute_path(path, including_package.base_directory)
266
+
267
+ descriptor =
268
+ Fig::PackageDescriptor.new(nil, nil, nil, :description => full_path)
269
+
270
+ new_backtrace = Fig::IncludeBacktrace.new(backtrace, descriptor)
271
+ package =
272
+ package_for_file(including_package, full_path, descriptor, backtrace)
218
273
 
219
274
  apply_config(
220
- package,
221
- resolved_descriptor.config || Fig::Package::DEFAULT_CONFIG,
222
- new_backtrace
275
+ package, config_name || Fig::Package::DEFAULT_CONFIG, new_backtrace
223
276
  )
224
277
 
225
278
  return
@@ -284,7 +337,7 @@ class Fig::RuntimeEnvironment
284
337
  Fig::PackageDescriptor.new(name, version, nil)
285
338
  )
286
339
  package.backtrace = backtrace
287
- @packages[name] = package
340
+ @named_packages[name] = package
288
341
  elsif version && version != package.version
289
342
  raise_repository_error(
290
343
  "Version mismatch for package #{name} (#{version} vs #{package.version}).",
@@ -296,6 +349,32 @@ class Fig::RuntimeEnvironment
296
349
  return package
297
350
  end
298
351
 
352
+ def package_for_file(including_package, full_path, descriptor, backtrace)
353
+ package = @packages_from_files[full_path]
354
+ return package if package
355
+
356
+ if ! File.exist? full_path
357
+ raise_repository_error(
358
+ %Q<"#{full_path}" does not exist.>, backtrace, including_package
359
+ )
360
+ end
361
+
362
+ content = File.read full_path
363
+
364
+ unparsed_package = Fig::NotYetParsedPackage.new
365
+ unparsed_package.descriptor = descriptor
366
+ unparsed_package.working_directory = unparsed_package.base_directory =
367
+ File.dirname(full_path)
368
+ unparsed_package.source_description = full_path
369
+ unparsed_package.unparsed_text = content
370
+
371
+ package = @parser.parse_package unparsed_package
372
+
373
+ @packages_from_files[full_path] = package
374
+
375
+ return package
376
+ end
377
+
299
378
  def determine_package_for_execution(base_package, base_config, descriptor)
300
379
  config_name =
301
380
  determine_config_to_executed(base_package, base_config, descriptor)
@@ -367,13 +446,20 @@ class Fig::RuntimeEnvironment
367
446
  )
368
447
  tokenized_value = statement.tokenized_value
369
448
  return tokenized_value.to_expanded_string { '@' } \
370
- unless package && package.name
449
+ unless package && (package.name || ! (package.synthetic? || package.base?))
371
450
 
372
451
  variable_value =
373
452
  tokenized_value.to_expanded_string { package.runtime_directory }
374
453
 
375
454
  return variable_value if not @retrieves.member?(statement.name)
376
455
 
456
+ if ! package.name
457
+ Fig::Logging.warn \
458
+ "Retrieve of #{statement.name}=#{variable_value} ignored because the statement#{statement.position_string} is in an unnamed package."
459
+
460
+ return variable_value
461
+ end
462
+
377
463
  return retrieve_files(
378
464
  statement.name, variable_value, package, backtrace
379
465
  )
@@ -8,7 +8,9 @@ module Fig; end
8
8
  # incorporation of the "default" configuration from that other package if no
9
9
  # ":configname" is specified.
10
10
  class Fig::Statement::Include < Fig::Statement
11
- attr_reader :descriptor, :containing_package_descriptor
11
+ attr_reader :descriptor
12
+ attr_reader :included_package
13
+ attr_reader :containing_package_descriptor
12
14
 
13
15
  # Centralized definition of requirements for descriptors for include
14
16
  # statements.
@@ -16,10 +18,17 @@ class Fig::Statement::Include < Fig::Statement
16
18
  return Fig::PackageDescriptor.parse(raw_string, options)
17
19
  end
18
20
 
19
- def initialize(line_column, source_description, descriptor, containing_package_descriptor)
21
+ def initialize(
22
+ line_column,
23
+ source_description,
24
+ descriptor,
25
+ included_package, # For synthetic Package for command-line options.
26
+ containing_package_descriptor
27
+ )
20
28
  super(line_column, source_description)
21
29
 
22
30
  @descriptor = descriptor
31
+ @included_package = included_package
23
32
  @containing_package_descriptor = containing_package_descriptor
24
33
  end
25
34
 
@@ -71,11 +80,11 @@ class Fig::Statement::Include < Fig::Statement
71
80
  end
72
81
 
73
82
  def minimum_grammar_for_emitting_input()
74
- return [0]
83
+ return minimum_grammar
75
84
  end
76
85
 
77
86
  def minimum_grammar_for_publishing()
78
- return [0]
87
+ return minimum_grammar
79
88
  end
80
89
 
81
90
  private
@@ -101,4 +110,12 @@ class Fig::Statement::Include < Fig::Statement
101
110
  def referenced_config_name()
102
111
  config_name() || Fig::Package::DEFAULT_CONFIG
103
112
  end
113
+
114
+ def minimum_grammar()
115
+ if included_package
116
+ raise 'Cannot unparse synthetic include statement with directly referenced package.'
117
+ end
118
+
119
+ return [0]
120
+ end
104
121
  end
@@ -0,0 +1,94 @@
1
+ require 'fig/package_descriptor'
2
+ require 'fig/statement'
3
+ require 'fig/user_input_error'
4
+
5
+ module Fig; end
6
+
7
+ # Like an include, but of an unpublished file.
8
+ class Fig::Statement::IncludeFile < Fig::Statement
9
+ def self.parse_path_with_config(path_with_config, &block)
10
+ if match = PATH_WITH_CONFIG_PATTERN.match(path_with_config)
11
+ return validate_and_process_raw_path_and_config_name(
12
+ match[:path], match[:config], &block
13
+ )
14
+ end
15
+
16
+ yield 'could not be understood as a path followed by a config name.'
17
+ return
18
+ end
19
+
20
+ def self.validate_and_process_raw_path_and_config_name(
21
+ raw_path, config_name, &block
22
+ )
23
+ if raw_path !~ /['"]/ && raw_path =~ /:/
24
+ yield 'has an unquoted colon (:) in the path portion.'
25
+ return
26
+ end
27
+ if (
28
+ ! config_name.nil? &&
29
+ config_name !~ Fig::PackageDescriptor::COMPONENT_PATTERN
30
+ )
31
+ yield "contains an invalid config name (#{config_name})."
32
+ return
33
+ end
34
+ tokenized_path = validate_and_process_escapes_in_path(raw_path, &block)
35
+ return if tokenized_path.nil?
36
+
37
+ return tokenized_path.to_expanded_string, config_name
38
+ end
39
+
40
+ private
41
+
42
+ def self.validate_and_process_escapes_in_path(path, &block)
43
+ return Fig::StringTokenizer.new.tokenize(path, &block)
44
+ end
45
+
46
+
47
+ public
48
+
49
+ attr_reader :path
50
+ attr_reader :config_name
51
+ attr_reader :containing_package_descriptor
52
+
53
+ def initialize(
54
+ line_column,
55
+ source_description,
56
+ path,
57
+ config_name,
58
+ containing_package_descriptor
59
+ )
60
+ super(line_column, source_description)
61
+
62
+ @path = path
63
+ @config_name = config_name
64
+ @containing_package_descriptor = containing_package_descriptor
65
+ end
66
+
67
+ def statement_type()
68
+ return 'include-file'
69
+ end
70
+
71
+ def unparse_as_version(unparser)
72
+ return unparser.include_file(self)
73
+ end
74
+
75
+ def minimum_grammar_for_emitting_input()
76
+ return [2, %q<didn't exist prior to v2>]
77
+ end
78
+
79
+ def minimum_grammar_for_publishing()
80
+ raise Fig::UserInputError.new 'Cannot publish an include-file statement.'
81
+ end
82
+
83
+ private
84
+
85
+ PATH_WITH_CONFIG_PATTERN = /
86
+ \A
87
+ (?<path> .+?)
88
+ (?:
89
+ [:]
90
+ (?<config> #{Fig::PackageDescriptor::UNBRACKETED_COMPONENT_PATTERN})
91
+ )?
92
+ \z
93
+ /x
94
+ end
data/lib/fig/unparser.rb CHANGED
@@ -20,9 +20,13 @@ module Fig::Unparser
20
20
  case version
21
21
  when 0
22
22
  return Fig::Unparser::V0, explanations
23
+ when 1
24
+ return Fig::Unparser::V1, explanations
25
+ when 2
26
+ return Fig::Unparser::V2, explanations
23
27
  end
24
28
 
25
- return Fig::Unparser::V1, explanations
29
+ raise "Unexpected version #{version}."
26
30
  end
27
31
 
28
32
  def self.determine_version_and_unparse(
@@ -113,7 +117,7 @@ module Fig::Unparser
113
117
  end
114
118
 
115
119
  def command(statement)
116
- raise NotImplementedError
120
+ raise NotImplementedError.new self
117
121
  end
118
122
 
119
123
  def configuration(configuration_statement)
@@ -144,7 +148,7 @@ module Fig::Unparser
144
148
  end
145
149
 
146
150
  def grammar_version(statement)
147
- raise NotImplementedError
151
+ raise NotImplementedError.new self
148
152
  end
149
153
 
150
154
  def include(statement)
@@ -159,6 +163,10 @@ module Fig::Unparser
159
163
  return
160
164
  end
161
165
 
166
+ def include_file(statement)
167
+ raise NotImplementedError.new self
168
+ end
169
+
162
170
  def override(statement)
163
171
  add_indent
164
172
 
@@ -186,7 +194,7 @@ module Fig::Unparser
186
194
  end
187
195
 
188
196
  def retrieve(statement)
189
- raise NotImplementedError
197
+ raise NotImplementedError.new self
190
198
  end
191
199
 
192
200
  def set(statement)
@@ -202,13 +210,13 @@ module Fig::Unparser
202
210
  end
203
211
 
204
212
  def grammar_description
205
- raise NotImplementedError
213
+ raise NotImplementedError.new self
206
214
  end
207
215
 
208
216
  private
209
217
 
210
218
  def asset(keyword, statement)
211
- raise NotImplementedError
219
+ raise NotImplementedError.new self
212
220
  end
213
221
 
214
222
  def asset_path(statement)
@@ -220,7 +228,7 @@ module Fig::Unparser
220
228
  end
221
229
 
222
230
  def environment_variable(statement, keyword)
223
- raise NotImplementedError
231
+ raise NotImplementedError.new self
224
232
  end
225
233
 
226
234
  def add_indent(indent_level = @indent_level)