fig 0.1.38-java

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.
data/lib/fig.rb ADDED
File without changes
@@ -0,0 +1,50 @@
1
+ class Backtrace
2
+ attr_reader :overrides
3
+
4
+ def initialize(parent, package_name, version_name, config_name)
5
+ @parent = parent
6
+ @package_name = package_name
7
+ @version_name = version_name
8
+ @config_name = config_name || "default"
9
+ @overrides = {}
10
+ end
11
+
12
+ def collect(stack)
13
+ if @parent
14
+ @parent.collect(stack)
15
+ end
16
+ elem = ""
17
+ if @package_name
18
+ elem = @package_name
19
+ end
20
+ if @version_name
21
+ elem += "/" + @version_name
22
+ end
23
+ if @config_name
24
+ elem += ":" + @config_name
25
+ end
26
+ stack << elem
27
+ end
28
+
29
+ def add_override(package_name, version_name)
30
+ # Don't replace an existing override on the stack
31
+ return if get_override(package_name)
32
+ @overrides[package_name] = version_name
33
+ end
34
+
35
+ def get_override(package_name)
36
+ return @overrides[package_name] || (@parent ? @parent.get_override(package_name) : nil)
37
+ end
38
+
39
+ def dump(out)
40
+ stack = []
41
+ collect(stack)
42
+ i=0
43
+ for elem in stack
44
+ indent=""
45
+ i.times { indent += " " }
46
+ out.puts indent+elem
47
+ i += 1
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,192 @@
1
+ require 'fig/backtrace'
2
+
3
+ module Fig
4
+
5
+ # This class manages the program's state, including the value of all environment
6
+ # variables, and which packages have already been applied
7
+ class Environment
8
+ DEFAULT_VERSION_NAME = "current"
9
+
10
+ def initialize(os, repository, variables, retriever)
11
+ @os = os
12
+ @repository = repository
13
+ @variables = variables
14
+ @retrieve_vars = {}
15
+ @packages = {}
16
+ @applied_configs = {}
17
+ @retriever = retriever
18
+ end
19
+
20
+ # Returns the value of an envirionment variable
21
+ def [](name)
22
+ @variables[name]
23
+ end
24
+
25
+ # Indicates that the values from a particular envrionment variable path should
26
+ # be copied to a local directory
27
+ def add_retrieve(name, path)
28
+ @retrieve_vars[name] = path
29
+ end
30
+
31
+ def register_package(package)
32
+ name = package.package_name
33
+ if @packages[name]
34
+ $stderr.puts "Package already exists with name: #{name}"
35
+ exit 10
36
+ end
37
+ @packages[name] = package
38
+ end
39
+
40
+ def apply_config(package, config_name, backtrace)
41
+ if (@applied_configs[package.package_name] ||= []).member?(config_name)
42
+ return
43
+ end
44
+ new_backtrace = backtrace #Backtrace.new(backtrace, package.package_name, package.version_name, config_name)
45
+
46
+ config = package[config_name]
47
+ config.statements.each { |stmt| apply_config_statement(package, stmt, new_backtrace) }
48
+ @applied_configs[package.package_name] << config_name
49
+ end
50
+
51
+ def execute_shell(command)
52
+ with_environment do
53
+ yield command.map{|arg| expand_arg(arg)}
54
+ end
55
+ end
56
+
57
+ def execute_config(base_package, package_name, config_name, version_name, args)
58
+ package = lookup_package(package_name || base_package.package_name, version_name, Backtrace.new(nil, package_name, version_name, config_name))
59
+ result = nil
60
+ commands = package[config_name || "default"].commands
61
+ with_environment do
62
+ # todo nil check
63
+ commands.each do |command|
64
+ result = yield expand_arg("#{command.command} #{args.join(' ')}").gsub("@",package.directory).split(" ")
65
+ end
66
+ end
67
+ result
68
+ end
69
+
70
+ def apply_config_statement(base_package, statement, backtrace)
71
+ case statement
72
+ when Path
73
+ append_variable(base_package, statement.name, statement.value)
74
+ when Set
75
+ set_variable(base_package, statement.name, statement.value)
76
+ when Include
77
+ include_config(base_package, statement.package_name, statement.config_name, statement.version_name, statement.overrides, backtrace)
78
+ when Command
79
+ # ignore
80
+ else
81
+ fail "Unexpected statement: #{statement}"
82
+ end
83
+ end
84
+
85
+ def include_config(base_package, package_name, config_name, version_name, overrides, backtrace)
86
+ # Check to see if this include has been overridden
87
+ if backtrace
88
+ override = backtrace.get_override(package_name || base_package.package_name)
89
+ if override
90
+ version_name = override
91
+ end
92
+ end
93
+ new_backtrace = Backtrace.new(backtrace, package_name, version_name, config_name)
94
+ overrides.each do |override|
95
+ new_backtrace.add_override(override.package_name, override.version_name)
96
+ end
97
+ package = lookup_package(package_name || base_package.package_name, version_name, new_backtrace)
98
+ apply_config(package, config_name || "default", new_backtrace)
99
+ end
100
+
101
+ def direct_retrieve(package_name, source_path, target_path)
102
+ package = lookup_package(package_name, nil, nil)
103
+ FileUtils.mkdir_p(target_path)
104
+ FileUtils.cp_r(File.join(package.directory, source_path, '.'), target_path)
105
+ end
106
+
107
+ private
108
+
109
+ def set_variable(base_package, name, value)
110
+ @variables[name] = expand_value(base_package, name, value)
111
+ end
112
+
113
+ def append_variable(base_package, name, value)
114
+ value = expand_value(base_package, name, value)
115
+ # TODO: converting all environment variables to upcase is not a robust
116
+ # comparison. It also assumes all env vars will be in upcase
117
+ # in package.fig
118
+ prev = nil
119
+ @variables.each do |key, val|
120
+ if key.upcase == name.upcase
121
+ name = key
122
+ prev = val
123
+ end
124
+ end
125
+ if prev
126
+ @variables[name] = value + File::PATH_SEPARATOR + prev
127
+ else
128
+ @variables[name] = value
129
+ end
130
+ end
131
+
132
+ def with_environment
133
+ old_env = {}
134
+ begin
135
+ @variables.each { |key,value| old_env[key] = ENV[key]; ENV[key] = value }
136
+ yield
137
+ ensure
138
+ old_env.each { |key,value| ENV[key] = value }
139
+ end
140
+ end
141
+
142
+ def lookup_package(package_name, version_name, backtrace)
143
+ package = @packages[package_name]
144
+ if package.nil?
145
+ package = @repository.load_package(package_name, version_name || DEFAULT_VERSION_NAME)
146
+ package.backtrace = backtrace
147
+ @packages[package_name] = package
148
+ elsif version_name && version_name != package.version_name
149
+ $stderr.puts "Version mismatch: #{package_name}"
150
+ backtrace.dump($stderr) if backtrace
151
+ package.backtrace.dump($stderr) if package.backtrace
152
+ exit 10
153
+ end
154
+ package
155
+ end
156
+
157
+ # Replace @ symbol with the package's directory
158
+ def expand_value(base_package, name, value)
159
+ return value unless base_package && base_package.package_name
160
+ file = value.gsub(/\@/, base_package.directory)
161
+ if @retrieve_vars.member?(name)
162
+ # A '//' in the source file's path tells us to preserve path information
163
+ # after the '//' when doing a retrieve.
164
+ if file.split('//').size > 1
165
+ preserved_path = file.split('//').last
166
+ target = File.join(@retrieve_vars[name].gsub(/\[package\]/, base_package.package_name), preserved_path)
167
+ else
168
+ target = File.join(@retrieve_vars[name].gsub(/\[package\]/, base_package.package_name))
169
+ if not File.directory?(file)
170
+ target = File.join(target, File.basename(file))
171
+ end
172
+ end
173
+ @retriever.with_config(base_package.package_name, base_package.version_name) do
174
+ @retriever.retrieve(file, target)
175
+ end
176
+ file = target
177
+ end
178
+ file
179
+ end
180
+
181
+ def expand_arg(arg)
182
+ arg.gsub(/\@([a-zA-Z0-9\-\.]+)/) do |match|
183
+ package = @packages[$1]
184
+ if package.nil?
185
+ $stderr.puts "Package not found: #{$1}"
186
+ exit 10
187
+ end
188
+ package.directory
189
+ end
190
+ end
191
+ end
192
+ end
@@ -0,0 +1,157 @@
1
+ require 'fig/package'
2
+
3
+ module Fig
4
+
5
+ grammar Fig
6
+ rule package
7
+ ws statements:(package_statement*) {
8
+ def to_package(package_name, version_name, directory)
9
+ Package.new(package_name, version_name, directory, statements.elements.map { |statement| statement.to_package_statement })
10
+ end
11
+ }
12
+ end
13
+
14
+ rule package_statement
15
+ archive / resource / retrieve / config
16
+ end
17
+
18
+ rule archive
19
+ "archive" ws url {
20
+ def to_package_statement
21
+ Archive.new(url.value.text_value)
22
+ end
23
+ }
24
+ end
25
+
26
+ rule resource
27
+ "resource" ws url {
28
+ def to_package_statement
29
+ Resource.new(url.value.text_value)
30
+ end
31
+ }
32
+ end
33
+
34
+ rule retrieve
35
+ "retrieve" ws var:[@a-zA-Z0-9/\._]+ "->" path:[a-zA-Z0-9_/\.\-\[\]]+ ws {
36
+ def to_package_statement
37
+ Retrieve.new(var.text_value, path.text_value)
38
+ end
39
+ }
40
+ end
41
+
42
+ rule install
43
+ "install" ws statements:config_statement* "end" ws {
44
+ def to_package_statement
45
+ Install.new(statements.elements.map { |statement| statement.to_config_statement })
46
+ end
47
+ }
48
+ end
49
+
50
+ rule config
51
+ "config" ws config_name ws statements:config_statement* "end" ws {
52
+ def to_package_statement
53
+ Configuration.new(config_name.text_value, statements.elements.map { |statement| statement.to_config_statement })
54
+ end
55
+ }
56
+ end
57
+
58
+ rule config_statement
59
+ include / command / path / set
60
+ end
61
+
62
+ rule include
63
+ "include" ws descriptor overrides:(override*) {
64
+ def to_config_statement
65
+ package = descriptor.respond_to?(:package) ? descriptor.package.text_value : nil
66
+ config = descriptor.get_config
67
+ version = descriptor.get_version
68
+ Include.new(package, config, version, overrides.elements.map{ |e| e.to_override })
69
+ end
70
+ }
71
+ end
72
+
73
+ rule override
74
+ "override" ws package_name "/" version_name ws {
75
+ def to_override
76
+ return Override.new(package_name.text_value, version_name.text_value)
77
+ end
78
+ }
79
+ end
80
+
81
+ rule path
82
+ ("append" / "path" / "add") ws name:[a-zA-Z0-9_]+ "=" value:[@a-zA-Z0-9/\-\\._]+ ws {
83
+ def to_config_statement
84
+ Path.new(name.text_value, value.text_value)
85
+ end
86
+ }
87
+ end
88
+
89
+ rule set
90
+ "set" ws name:[a-zA-Z0-9_]+ "=" value:[@a-zA-Z0-9/\-\\._]+ ws {
91
+ def to_config_statement
92
+ Set.new(name.text_value, value.text_value)
93
+ end
94
+ }
95
+ end
96
+
97
+ rule command
98
+ "command" ws string {
99
+ def to_config_statement
100
+ Command.new(string.value.text_value)
101
+ end
102
+ }
103
+ end
104
+
105
+ rule string
106
+ '"' value:(!'"' . )* '"' ws
107
+ end
108
+
109
+ rule descriptor
110
+ ((package:package_name ("/" version:version_name)? (":" config:config_name)? ws) /
111
+ (":" config:config_name ws)) {
112
+ def get_version
113
+ elements.each do |element|
114
+ if element.respond_to?(:version)
115
+ return element.version.text_value
116
+ end
117
+ end
118
+ nil
119
+ end
120
+ def get_config
121
+ return self.config.text_value if self.respond_to?(:config)
122
+ elements.each do |element|
123
+ if element.respond_to?(:config)
124
+ return element.config.text_value
125
+ end
126
+ end
127
+ nil
128
+ end
129
+ }
130
+ end
131
+
132
+ rule package_name
133
+ [a-zA-Z0-9.-]+
134
+ end
135
+
136
+ rule version_name
137
+ [a-zA-Z0-9_\-.]+
138
+ end
139
+
140
+ rule config_name
141
+ [a-zA-Z0-9_\-.]+
142
+ end
143
+
144
+ rule name
145
+ value:[a-zA-Z0-9]+ ws
146
+ end
147
+
148
+ rule url
149
+ (value:[a-zA-Z0-9:/\-\\._\*]+ ws) / ('"' value:[a-zA-Z0-9:/\-\\._]+ '"' ws)
150
+ end
151
+
152
+ rule ws
153
+ [ \n\r\t]+
154
+ end
155
+ end
156
+
157
+ end
@@ -0,0 +1,106 @@
1
+ require 'optparse'
2
+ require 'fig/package'
3
+
4
+ module Fig
5
+ def parse_descriptor(descriptor)
6
+ # todo should use treetop for these:
7
+ package_name = descriptor =~ /^([^:\/]+)/ ? $1 : nil
8
+ config_name = descriptor =~ /:([^:\/]+)/ ? $1 : nil
9
+ version_name = descriptor =~ /\/([^:\/]+)/ ? $1 : nil
10
+ return package_name, config_name, version_name
11
+ end
12
+
13
+ def parse_options(argv)
14
+ options = {}
15
+
16
+ parser = OptionParser.new do |opts|
17
+ opts.banner = "Usage: fig [--debug] [--update] [--config <config>] [--get <var> | --list | <package> | - <command>]"
18
+
19
+ opts.on('-?', '-h','--help','display this help text') do
20
+ puts opts
21
+ exit 1
22
+ end
23
+
24
+ options[:debug] = false
25
+ opts.on('-d', '--debug', 'print debug info') { options[:debug] = true }
26
+
27
+ options[:update] = false
28
+ opts.on('-u', '--update', 'check remote repository for updates') { options[:update] = true; options[:retrieve] = true }
29
+
30
+ options[:update_if_missing] = false
31
+ opts.on('-m', '--update-if-missing', 'check for updates only if package is missing locally') { options[:update_if_missing] = true; options[:retrieve] = true }
32
+
33
+ options[:config] = "default"
34
+ opts.on('-c', '--config CFG', 'name of configuration to apply') { |config| options[:config] = config }
35
+
36
+ options[:echo] = nil
37
+ opts.on('-g', '--get VAR', 'print value of environment variable') { |echo| options[:echo] = echo }
38
+
39
+ options[:publish] = nil
40
+ opts.on('--publish PKG', 'install package in local and remote repositories') { |publish| options[:publish] = publish }
41
+
42
+ options[:publish_local] = nil
43
+ opts.on('--publish-local PKG', 'install package in local repositorie only') { |publish_local| options[:publish_local] = publish_local }
44
+
45
+ options[:force] = nil
46
+ opts.on('--force', 'force overwriting of an existing remote package version') { |force| options[:force] = force }
47
+
48
+ options[:resources] =[]
49
+ opts.on('--resource PATH', 'resource to include in package (when using --publish)') do |path|
50
+ options[:resources] << Resource.new(path)
51
+ end
52
+
53
+ options[:archives] =[]
54
+ opts.on('--archive PATH', 'archive to include in package (when using --publish)') do |path|
55
+ options[:archives] << Archive.new(path)
56
+ end
57
+
58
+ options[:login] = false
59
+ opts.on('-l', '--login', 'login into the FTP server as a non-anonymous user') { options[:login] = true }
60
+
61
+ options[:list] = false
62
+ opts.on('--list', 'list packages in local repository') { options[:list] = true }
63
+
64
+ options[:list_remote] = false
65
+ opts.on('--list-remote', 'list packages in remote repository') { options[:list_remote] = true }
66
+
67
+ options[:list_configs] = []
68
+ opts.on('--list-configs PKG', 'list configurations in package') { |descriptor| options[:list_configs] << descriptor }
69
+
70
+ options[:cleans] = []
71
+ opts.on('--clean PKG', 'remove package from local repository') { |descriptor| options[:cleans] << descriptor }
72
+
73
+ options[:modifiers] = []
74
+
75
+ opts.on('-i', '--include PKG', 'include package in environment') do |descriptor|
76
+ package_name, config_name, version_name = parse_descriptor(descriptor)
77
+ options[:modifiers] << Include.new(package_name, config_name, version_name, {})
78
+ end
79
+
80
+ # opts.on('-o', '--override PKG', 'override version of included package') do |descriptor|
81
+ # package_name, config_name, version_name = parse_descriptor(descriptor)
82
+ # options[:modifiers] << Include.new(package_name, config_name, version_name, {})
83
+ # end
84
+
85
+ opts.on('-s', '--set VAR=VAL', 'set environment variable') do |var_val|
86
+ var, val = var_val.split('=')
87
+ options[:modifiers] << Set.new(var, val)
88
+ end
89
+
90
+ opts.on('-p', '--append VAR=VAL', 'append environment variable') do |var_val|
91
+ var, val = var_val.split('=')
92
+ options[:modifiers] << Path.new(var, val)
93
+ end
94
+
95
+ options[:input] = nil
96
+ opts.on('--file FILE', 'fig file to read (use - for stdin)') { |path| options[:input] = path }
97
+ opts.on('--no-file', 'ignore package.fig file in current directory') { |path| options[:input] = :none }
98
+
99
+ options[:home] = ENV['FIG_HOME'] || File.expand_path("~/.fighome")
100
+ end
101
+
102
+ parser.parse!(argv)
103
+
104
+ return options, argv
105
+ end
106
+ end