fig 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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)