fig 0.1.62 → 0.1.64

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 (43) hide show
  1. data/Changes +156 -0
  2. data/VERSION +1 -1
  3. data/bin/fig +9 -2
  4. data/bin/fig-debug +9 -2
  5. data/lib/fig/applicationconfiguration.rb +3 -2
  6. data/lib/fig/atexit.rb +37 -0
  7. data/lib/fig/backtrace.rb +23 -6
  8. data/lib/fig/command.rb +131 -31
  9. data/lib/fig/command/coveragesupport.rb +40 -0
  10. data/lib/fig/command/listing.rb +8 -8
  11. data/lib/fig/command/optionerror.rb +8 -0
  12. data/lib/fig/{options.rb → command/options.rb} +248 -144
  13. data/lib/fig/command/packageload.rb +161 -62
  14. data/lib/fig/configfileerror.rb +2 -0
  15. data/lib/fig/environment.rb +350 -246
  16. data/lib/fig/environmentvariables/casesensitive.rb +1 -1
  17. data/lib/fig/figrc.rb +78 -78
  18. data/lib/fig/grammar.treetop +204 -219
  19. data/lib/fig/log4rconfigerror.rb +2 -0
  20. data/lib/fig/operatingsystem.rb +382 -334
  21. data/lib/fig/package.rb +11 -33
  22. data/lib/fig/packagecache.rb +1 -1
  23. data/lib/fig/packagedescriptor.rb +103 -21
  24. data/lib/fig/packagedescriptorparseerror.rb +16 -0
  25. data/lib/fig/parser.rb +36 -19
  26. data/lib/fig/parserpackagebuildstate.rb +56 -0
  27. data/lib/fig/repository.rb +504 -259
  28. data/lib/fig/statement.rb +30 -12
  29. data/lib/fig/statement/archive.rb +8 -5
  30. data/lib/fig/statement/asset.rb +19 -0
  31. data/lib/fig/statement/command.rb +2 -2
  32. data/lib/fig/statement/configuration.rb +20 -20
  33. data/lib/fig/statement/include.rb +13 -34
  34. data/lib/fig/statement/override.rb +21 -7
  35. data/lib/fig/statement/path.rb +22 -2
  36. data/lib/fig/statement/resource.rb +14 -4
  37. data/lib/fig/statement/retrieve.rb +34 -4
  38. data/lib/fig/statement/set.rb +22 -2
  39. data/lib/fig/workingdirectorymaintainer.rb +197 -0
  40. data/lib/fig/workingdirectorymetadata.rb +45 -0
  41. metadata +52 -46
  42. data/lib/fig/retriever.rb +0 -141
  43. data/lib/fig/statement/publish.rb +0 -15
@@ -1,15 +1,35 @@
1
1
  module Fig; end
2
2
 
3
- # A statement within a package configuration file (package.fig).
3
+ # A statement within a package definition file (package.fig).
4
4
  class Fig::Statement
5
- attr_reader :line, :column
5
+ ENVIRONMENT_VARIABLE_NAME_REGEX = %r< \A \w+ \z >x
6
+
7
+ attr_reader :line, :column, :source_description
8
+
9
+ def self.position_description(line, column, source_description)
10
+ if not line or not column
11
+ return '' if not source_description
12
+
13
+ return " (#{source_description})"
14
+ end
15
+
16
+ description = " (line #{line}, column #{column}"
17
+ if source_description
18
+ description << ", #{source_description}"
19
+ end
20
+ description << ')'
21
+
22
+ return description
23
+ end
6
24
 
7
25
  # This mess of getting these as a single array necessary is due to
8
26
  # limitations of the "*" array splat operator in ruby v1.8.
9
- def initialize(line_column)
27
+ def initialize(line_column, source_description)
10
28
  if line_column
11
29
  @line, @column = *line_column
12
30
  end
31
+
32
+ @source_description = source_description
13
33
  end
14
34
 
15
35
  # Block will receive a Statement.
@@ -17,13 +37,12 @@ class Fig::Statement
17
37
  return
18
38
  end
19
39
 
20
- # Block will receive a Package and a Statement.
21
- def walk_statements_following_package_dependencies(repository, package, configuration, &block)
22
- return
40
+ def urls()
41
+ return []
23
42
  end
24
43
 
25
- def urls
26
- return []
44
+ def is_asset?()
45
+ return false
27
46
  end
28
47
 
29
48
  # Returns a representation of the position of this statement, if the position
@@ -32,9 +51,8 @@ class Fig::Statement
32
51
  # statement%{statement.position_string()}.>" and get nice looking output
33
52
  # regardless of whether the position is actually known or not.
34
53
  def position_string
35
- return '' if not @line
36
- return '' if not @column
37
-
38
- return " (line #{@line}, column #{@column})"
54
+ return Fig::Statement.position_description(
55
+ @line, @column, @source_description
56
+ )
39
57
  end
40
58
  end
@@ -1,21 +1,24 @@
1
1
  require 'fig/statement'
2
+ require 'fig/statement/asset'
2
3
 
3
4
  module Fig; end
4
5
 
5
- # Specifies an archive file (possibly via a URL) that is part of the current package.
6
+ # Specifies an archive file (possibly via a URL) that is part of a package.
6
7
  #
7
8
  # Differs from a Resource in that the contents will be extracted.
8
9
  class Fig::Statement::Archive < Fig::Statement
10
+ include Fig::Statement::Asset
11
+
9
12
  attr_reader :url
10
13
 
11
- def initialize(line_column, url)
12
- super(line_column)
14
+ def initialize(line_column, source_description, url)
15
+ super(line_column, source_description)
13
16
 
14
17
  @url = url
15
18
  end
16
19
 
17
- def urls
18
- return [@url]
20
+ def asset_name()
21
+ return standard_asset_name()
19
22
  end
20
23
 
21
24
  def unparse(indent)
@@ -0,0 +1,19 @@
1
+ module Fig; end
2
+ class Fig::Statement; end
3
+
4
+ # Some sort of file to be included in a package.
5
+ module Fig::Statement::Asset
6
+ def urls()
7
+ return [ url() ]
8
+ end
9
+
10
+ def is_asset?()
11
+ return true
12
+ end
13
+
14
+ def standard_asset_name()
15
+ # Not so hot of an idea if the URL has query parameters in it, but not
16
+ # going to fix this now.
17
+ return url().split('/').last()
18
+ end
19
+ end
@@ -7,8 +7,8 @@ module Fig; end
7
7
  class Fig::Statement::Command < Fig::Statement
8
8
  attr_reader :command
9
9
 
10
- def initialize(line_column, command)
11
- super(line_column)
10
+ def initialize(line_column, source_description, command)
11
+ super(line_column, source_description)
12
12
 
13
13
  @command = command
14
14
  end
@@ -3,22 +3,25 @@ require 'fig/statement/command'
3
3
 
4
4
  module Fig; end
5
5
 
6
- # A grouping of statements within a configuration. May not be nested.
6
+ # A grouping of statements within a package. May not be nested.
7
+ #
8
+ # Any processing of statements is guaranteed to hit any Overrides first.
7
9
  class Fig::Statement::Configuration < Fig::Statement
8
10
  attr_reader :name, :statements
9
11
 
10
- def initialize(line_column, name, statements)
11
- super(line_column)
12
+ def initialize(line_column, source_description, name, statements)
13
+ super(line_column, source_description)
12
14
 
13
15
  @name = name
14
- @statements = statements
15
- end
16
16
 
17
- def with_name(name)
18
- Configuration.new(name, statements)
17
+ overrides, others = statements.partition do
18
+ |statement| statement.is_a?(Fig::Statement::Override)
19
+ end
20
+
21
+ @statements = [overrides, others].flatten
19
22
  end
20
23
 
21
- def command
24
+ def command_statement
22
25
  return statements.find do
23
26
  |statement| statement.is_a?(Fig::Statement::Command)
24
27
  end
@@ -32,19 +35,16 @@ class Fig::Statement::Configuration < Fig::Statement
32
35
  end
33
36
  end
34
37
 
35
- # Block will receive a Package and a Statement.
36
- def walk_statements_following_package_dependencies(repository, package, configuration, &block)
37
- @statements.each do |statement|
38
- yield package, self, statement
39
- statement.walk_statements_following_package_dependencies(
40
- repository, package, self, &block
41
- )
42
- end
43
-
44
- return
45
- end
46
-
47
38
  def unparse(indent)
48
39
  unparse_statements(indent, "config #{@name}", @statements, 'end')
49
40
  end
41
+
42
+ private
43
+
44
+ def unparse_statements(indent, prefix, statements, suffix)
45
+ body =
46
+ @statements.map {|statement| statement.unparse(indent + ' ') }.join("\n")
47
+
48
+ return ["\n#{indent}#{prefix}", body, "#{indent}#{suffix}"].join("\n")
49
+ end
50
50
  end
@@ -4,15 +4,22 @@ require 'fig/statement'
4
4
  module Fig; end
5
5
 
6
6
  # Dual role: "include :configname" incorporates one configuration into another;
7
- # "include package[/version]" declares a dependency upon another package.
7
+ # "include package[/version]" declares a dependency upon another package (with
8
+ # incorporation of the "default" configuration from that other package if no
9
+ # ":configname" is specified.
8
10
  class Fig::Statement::Include < Fig::Statement
9
- attr_reader :descriptor, :overrides, :containing_package_descriptor
11
+ attr_reader :descriptor, :containing_package_descriptor
10
12
 
11
- def initialize(line_column, descriptor, overrides, containing_package_descriptor)
12
- super(line_column)
13
+ # Centralized definition of requirements for descriptors for include
14
+ # statements.
15
+ def self.parse_descriptor(raw_string, options = {})
16
+ return Fig::PackageDescriptor.parse(raw_string, options)
17
+ end
18
+
19
+ def initialize(line_column, source_description, descriptor, containing_package_descriptor)
20
+ super(line_column, source_description)
13
21
 
14
22
  @descriptor = descriptor
15
- @overrides = overrides
16
23
  @containing_package_descriptor = containing_package_descriptor
17
24
  end
18
25
 
@@ -55,35 +62,12 @@ class Fig::Statement::Include < Fig::Statement
55
62
  )
56
63
  end
57
64
 
58
- # Block will receive a Package and a Statement.
59
- def walk_statements_following_package_dependencies(
60
- repository, package, configuration, &block
61
- )
62
- referenced_package = nil
63
- if package_name()
64
- referenced_package = repository.get_package(descriptor())
65
- else
66
- referenced_package = package
67
- end
68
-
69
- configuration = referenced_package[referenced_config_name()]
70
-
71
- yield referenced_package, configuration
72
- configuration.walk_statements_following_package_dependencies(
73
- repository, referenced_package, nil, &block
74
- )
75
-
76
- return
77
- end
78
-
79
65
  def unparse(indent)
80
66
  text = ''
81
67
  text += package_name() if package_name()
82
68
  text += "/#{version()}" if version()
83
69
  text += ":#{config_name()}" if config_name()
84
- @overrides.each do |override|
85
- text += override.unparse
86
- end
70
+
87
71
  return "#{indent}include #{text}"
88
72
  end
89
73
 
@@ -94,11 +78,6 @@ class Fig::Statement::Include < Fig::Statement
94
78
  end
95
79
 
96
80
  def referenced_version(containing_package, backtrace)
97
- overrides().each do
98
- |override|
99
- backtrace.add_override(override.package_name(), override.version())
100
- end
101
-
102
81
  package_name = nil
103
82
  original_version = nil
104
83
  if package_name()
@@ -3,24 +3,38 @@ require 'fig/statement'
3
3
 
4
4
  module Fig; end
5
5
 
6
- # Overrides one package version dependency with another in an include
7
- # statement.
6
+ # Overrides one package version dependency with another.
8
7
  #
9
- # include blah/1.2.3 override somedependency/3.2.6
8
+ # config whatever
9
+ # override somedependency/3.2.6
10
+ # end
10
11
  #
11
12
  # indicates that, regardless of which version of somedependency the blah
12
13
  # package says it needs, the blah package will actually use v3.2.6.
13
14
  class Fig::Statement::Override < Fig::Statement
14
15
  attr_reader :package_name, :version
15
16
 
16
- def initialize(line_column, package_name, version)
17
- super(line_column)
17
+ # Centralized definition of requirements for descriptors for override
18
+ # statements.
19
+ def self.parse_descriptor(raw_string, options = {})
20
+ filled_in_options = {}
21
+ filled_in_options.merge!(options)
22
+ filled_in_options[:name] = :required
23
+ filled_in_options[:version] = :required
24
+ filled_in_options[:config] = :forbidden
25
+
26
+ return Fig::PackageDescriptor.parse(raw_string, filled_in_options)
27
+ end
28
+
29
+ def initialize(line_column, source_description, package_name, version)
30
+ super(line_column, source_description)
18
31
 
19
32
  @package_name = package_name
20
33
  @version = version
21
34
  end
22
35
 
23
- def unparse()
24
- return ' override ' + Fig::PackageDescriptor.format(@package_name, @version, nil)
36
+ def unparse(indent)
37
+ return "#{indent}override " +
38
+ Fig::PackageDescriptor.format(@package_name, @version, nil)
25
39
  end
26
40
  end
@@ -5,10 +5,30 @@ module Fig; end
5
5
  # A statement that specifies or modifies a path environment variable, e.g.
6
6
  # "append", "path", "add" (though those are all synonyms).
7
7
  class Fig::Statement::Path < Fig::Statement
8
+ VALUE_REGEX = %r< \A [^;:"<>|\s]+ \z >x
9
+ ARGUMENT_DESCRIPTION =
10
+ %q[The value must look like "NAME=VALUE". VALUE cannot contain any of ";:<>|", double quotes, or whitespace.]
11
+
12
+ # Yields on error.
13
+ def self.parse_name_value(combined)
14
+ variable, value = combined.split("=")
15
+
16
+ if variable !~ ENVIRONMENT_VARIABLE_NAME_REGEX
17
+ yield
18
+ end
19
+
20
+ value = '' if value.nil?
21
+ if value !~ VALUE_REGEX
22
+ yield
23
+ end
24
+
25
+ return [variable, value]
26
+ end
27
+
8
28
  attr_reader :name, :value
9
29
 
10
- def initialize(line_column, name, value)
11
- super(line_column)
30
+ def initialize(line_column, source_description, name, value)
31
+ super(line_column, source_description)
12
32
 
13
33
  @name = name
14
34
  @value = value
@@ -1,4 +1,6 @@
1
+ require 'fig/repository'
1
2
  require 'fig/statement'
3
+ require 'fig/statement/asset'
2
4
 
3
5
  module Fig; end
4
6
 
@@ -6,16 +8,24 @@ module Fig; end
6
8
  #
7
9
  # Differs from an Archive in that the contents will not be extracted.
8
10
  class Fig::Statement::Resource < Fig::Statement
11
+ include Fig::Statement::Asset
12
+
9
13
  attr_reader :url
10
14
 
11
- def initialize(line_column, url)
12
- super(line_column)
15
+ def initialize(line_column, source_description, url)
16
+ super(line_column, source_description)
13
17
 
14
18
  @url = url
15
19
  end
16
20
 
17
- def urls
18
- return [@url]
21
+ def asset_name()
22
+ if Fig::Repository.is_url?(url())
23
+ return standard_asset_name()
24
+ end
25
+
26
+ # This resource will end up being bundled with others and will not live in
27
+ # the package by itself.
28
+ return nil
19
29
  end
20
30
 
21
31
  def unparse(indent)
@@ -1,16 +1,46 @@
1
+ require 'fig/logging'
1
2
  require 'fig/statement'
2
3
 
3
4
  module Fig; end
4
5
 
5
- # Specifies the destination to put a dependency into.
6
+ # Specifies that files from a package should be copied into the current
7
+ # directory when an environment variable has its value changed.
6
8
  class Fig::Statement::Retrieve < Fig::Statement
7
- attr_reader :var, :path
9
+ attr_reader :var, :path
8
10
 
9
- def initialize(line_column, var, path)
10
- super(line_column)
11
+ def initialize(line_column, source_description, var, path)
12
+ super(line_column, source_description)
11
13
 
12
14
  @var = var
13
15
  @path = path
16
+
17
+ # Yeah, it's not cross-platform, but File doesn't have an #absolute? method
18
+ # and this is better than nothing.
19
+ if path =~ %r< ^ / >x
20
+ Fig::Logging.warn(
21
+ %Q<The retrieve path "#{path}"#{position_string()} looks like it is intended to be absolute; retrieve paths are always treated as relative.>
22
+ )
23
+ end
24
+ end
25
+
26
+ def loaded_but_not_referenced?()
27
+ return added_to_environment? && ! referenced?
28
+ end
29
+
30
+ def added_to_environment?()
31
+ return @added_to_environment
32
+ end
33
+
34
+ def added_to_environment(yea_or_nay)
35
+ @added_to_environment = yea_or_nay
36
+ end
37
+
38
+ def referenced?()
39
+ return @referenced
40
+ end
41
+
42
+ def referenced(yea_or_nay)
43
+ @referenced = yea_or_nay
14
44
  end
15
45
 
16
46
  def unparse(indent)
@@ -4,10 +4,30 @@ module Fig; end
4
4
 
5
5
  # A statement that sets the value of an environment variable.
6
6
  class Fig::Statement::Set < Fig::Statement
7
+ VALUE_REGEX = %r< \A \S* \z >x
8
+ ARGUMENT_DESCRIPTION =
9
+ %q<The value must look like "NAME=VALUE", though VALUE can be empty.>
10
+
11
+ # Yields on error.
12
+ def self.parse_name_value(combined)
13
+ variable, value = combined.split("=")
14
+
15
+ if variable !~ ENVIRONMENT_VARIABLE_NAME_REGEX
16
+ yield
17
+ end
18
+
19
+ value = '' if value.nil?
20
+ if value !~ VALUE_REGEX
21
+ yield
22
+ end
23
+
24
+ return [variable, value]
25
+ end
26
+
7
27
  attr_reader :name, :value
8
28
 
9
- def initialize(line_column, name, value)
10
- super(line_column)
29
+ def initialize(line_column, source_description, name, value)
30
+ super(line_column, source_description)
11
31
 
12
32
  @name = name
13
33
  @value = value