fig 0.1.38-java

Sign up to get free protection for your applications and to get access to all the features.
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