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/LICENSE +27 -0
- data/README.md +229 -0
- data/bin/fig +190 -0
- data/bin/fig-download +20 -0
- data/lib/fig.rb +0 -0
- data/lib/fig/backtrace.rb +50 -0
- data/lib/fig/environment.rb +192 -0
- data/lib/fig/grammar.treetop +157 -0
- data/lib/fig/options.rb +106 -0
- data/lib/fig/os.rb +396 -0
- data/lib/fig/package.rb +220 -0
- data/lib/fig/parser.rb +27 -0
- data/lib/fig/repository.rb +241 -0
- data/lib/fig/retriever.rb +107 -0
- data/lib/fig/windows.rb +46 -0
- metadata +159 -0
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
|
data/lib/fig/options.rb
ADDED
@@ -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
|