fig18 0.1.42-mingw32

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,216 @@
1
+ require 'stringio'
2
+
3
+ require 'fig/backtrace'
4
+ require 'fig/logging'
5
+ require 'fig/package/command'
6
+ require 'fig/package/include'
7
+ require 'fig/package/path'
8
+ require 'fig/package/set'
9
+ require 'fig/repositoryerror'
10
+
11
+ module Fig
12
+ # This class manages the program's state, including the value of all
13
+ # environment variables, and which packages have already been applied.
14
+ class Environment
15
+ DEFAULT_VERSION_NAME = 'current'
16
+
17
+ def initialize(os, repository, variables, retriever)
18
+ @os = os
19
+ @repository = repository
20
+ @variables = variables
21
+ @retrieve_vars = {}
22
+ @packages = {}
23
+ @applied_configs = {}
24
+ @retriever = retriever
25
+ end
26
+
27
+ # Returns the value of an envirionment variable
28
+ def [](name)
29
+ @variables[name]
30
+ end
31
+
32
+ # Indicates that the values from a particular envrionment variable path
33
+
34
+ def add_retrieve(name, path)
35
+ @retrieve_vars[name] = path
36
+ end
37
+
38
+ def register_package(package)
39
+ name = package.package_name
40
+ if @packages[name]
41
+ Fig::Logging.fatal %Q<There is already a package with the name "#{name}".>
42
+ raise RepositoryError.new
43
+ end
44
+ @packages[name] = package
45
+ end
46
+
47
+ def apply_config(package, config_name, backtrace)
48
+ if (@applied_configs[package.package_name] ||= []).member?(config_name)
49
+ return
50
+ end
51
+ new_backtrace = backtrace
52
+
53
+ config = package[config_name]
54
+ config.statements.each { |stmt| apply_config_statement(package, stmt, new_backtrace) }
55
+ @applied_configs[package.package_name] << config_name
56
+ end
57
+
58
+ def execute_shell(command)
59
+ with_environment do
60
+ yield command.map{|arg| expand_arg(arg)}
61
+ end
62
+ end
63
+
64
+ def execute_config(base_package, package_name, config_name, version_name, args)
65
+ package = lookup_package(package_name || base_package.package_name, version_name, Backtrace.new(nil, package_name, version_name, config_name))
66
+ result = nil
67
+ commands = package[config_name || 'default'].commands
68
+ with_environment do
69
+ # TODO nil check
70
+ commands.each do |command|
71
+ result = yield expand_arg("#{command.command} #{args.join(' ')}").gsub('@',package.directory).split(' ')
72
+ end
73
+ end
74
+ result
75
+ end
76
+
77
+ def apply_config_statement(base_package, statement, backtrace)
78
+ case statement
79
+ when Package::Path
80
+ append_variable(base_package, statement.name, statement.value)
81
+ when Package::Set
82
+ set_variable(base_package, statement.name, statement.value)
83
+ when Package::Include
84
+ include_config(base_package, statement.package_name, statement.config_name, statement.version_name, statement.overrides, backtrace)
85
+ when Package::Command
86
+ # ignore
87
+ else
88
+ fail "Unexpected statement: #{statement}"
89
+ end
90
+ end
91
+
92
+ def include_config(base_package, package_name, config_name, version_name, overrides, backtrace)
93
+ # Check to see if this include has been overridden.
94
+ if backtrace
95
+ override = backtrace.get_override(package_name || base_package.package_name)
96
+ if override
97
+ version_name = override
98
+ end
99
+ end
100
+ new_backtrace = Backtrace.new(backtrace, package_name, version_name, config_name)
101
+ overrides.each do |override|
102
+ new_backtrace.add_override(override.package_name, override.version_name)
103
+ end
104
+ package = lookup_package(package_name || base_package.package_name, version_name, new_backtrace)
105
+ apply_config(package, config_name || 'default', new_backtrace)
106
+ end
107
+
108
+ def direct_retrieve(package_name, source_path, target_path)
109
+ package = lookup_package(package_name, nil, nil)
110
+ FileUtils.mkdir_p(target_path)
111
+ FileUtils.cp_r(File.join(package.directory, source_path, '.'), target_path)
112
+ end
113
+
114
+ private
115
+
116
+ def set_variable(base_package, name, value)
117
+ @variables[name] = expand_value(base_package, name, value)
118
+ end
119
+
120
+ def append_variable(base_package, name, value)
121
+ value = expand_value(base_package, name, value)
122
+ # TODO: converting all environment variables to upcase is not a robust
123
+ # comparison. It also assumes all env vars will be in upcase
124
+ # in package.fig
125
+ prev = nil
126
+ @variables.each do |key, val|
127
+ if key.upcase == name.upcase
128
+ name = key
129
+ prev = val
130
+ end
131
+ end
132
+ if prev
133
+ @variables[name] = value + File::PATH_SEPARATOR + prev
134
+ else
135
+ @variables[name] = value
136
+ end
137
+ end
138
+
139
+ def with_environment
140
+ old_env = {}
141
+ begin
142
+ @variables.each { |key,value| old_env[key] = ENV[key]; ENV[key] = value }
143
+ yield
144
+ ensure
145
+ old_env.each { |key,value| ENV[key] = value }
146
+ end
147
+ end
148
+
149
+ def lookup_package(package_name, version_name, backtrace)
150
+ package = @packages[package_name]
151
+ if package.nil?
152
+ package = @repository.load_package(package_name, version_name || DEFAULT_VERSION_NAME)
153
+ package.backtrace = backtrace
154
+ @packages[package_name] = package
155
+ elsif version_name && version_name != package.version_name
156
+ string_handle = StringIO.new
157
+ backtrace.dump(string_handle) if backtrace
158
+ package.backtrace.dump(string_handle) if package.backtrace
159
+ stacktrace = string_handle.to_s
160
+ Fig::Logging.fatal \
161
+ "Version mismatch: #{package_name}" \
162
+ + stacktrace.empty? ? '' : "\n#{stacktrace}"
163
+ raise RepositoryError.new
164
+ end
165
+ package
166
+ end
167
+
168
+ # Replace @ symbol with the package's directory
169
+ def expand_value(base_package, name, value)
170
+ return value unless base_package && base_package.package_name
171
+ file = value.gsub(/\@/, base_package.directory)
172
+ if @retrieve_vars.member?(name)
173
+ # A '//' in the source file's path tells us to preserve path
174
+ # information after the '//' when doing a retrieve.
175
+ if file.split('//').size > 1
176
+ preserved_path = file.split('//').last
177
+ target = File.join(
178
+ @retrieve_vars[name].gsub(
179
+ /\[package\]/,
180
+ base_package.package_name
181
+ ),
182
+ preserved_path
183
+ )
184
+ else
185
+ target = File.join(
186
+ @retrieve_vars[name].gsub(
187
+ /\[package\]/,
188
+ base_package.package_name
189
+ )
190
+ )
191
+ if not File.directory?(file)
192
+ target = File.join(target, File.basename(file))
193
+ end
194
+ end
195
+ @retriever.with_package_config(
196
+ base_package.package_name, base_package.version_name
197
+ ) do
198
+ @retriever.retrieve(file, target)
199
+ end
200
+ file = target
201
+ end
202
+ file
203
+ end
204
+
205
+ def expand_arg(arg)
206
+ arg.gsub(/\@([a-zA-Z0-9\-\.]+)/) do |match|
207
+ package = @packages[$1]
208
+ if package.nil?
209
+ Fig::Logging.fatal "Package not found: #{$1}"
210
+ raise RepositoryError.new
211
+ end
212
+ package.directory
213
+ end
214
+ end
215
+ end
216
+ end
data/lib/fig/figrc.rb ADDED
@@ -0,0 +1,105 @@
1
+ require 'json'
2
+
3
+ require 'fig/applicationconfiguration'
4
+ require 'fig/configfileerror'
5
+ require 'fig/os'
6
+
7
+ REPOSITORY_CONFIGURATION = '_meta/figrc'
8
+
9
+ module Fig
10
+ class FigRC
11
+ def self.find(
12
+ override_path, repository_url, login, fig_home, disable_figrc = false
13
+ )
14
+ configuration = ApplicationConfiguration.new(repository_url)
15
+
16
+ handle_override_configuration(configuration, override_path)
17
+ handle_figrc(configuration) if not disable_figrc
18
+ handle_repository_configuration(
19
+ configuration, repository_url, login, fig_home
20
+ )
21
+
22
+ return configuration
23
+ end
24
+
25
+ private
26
+
27
+ def self.handle_override_configuration(configuration, override_path)
28
+ begin
29
+ if not override_path.nil?
30
+ configuration.push_dataset(
31
+ JSON.parse(File::open(override_path).read)
32
+ )
33
+ end
34
+ rescue JSON::ParserError => exception
35
+ translate_parse_error(exception, override_path)
36
+ end
37
+
38
+ return
39
+ end
40
+
41
+ def self.handle_figrc(configuration)
42
+ user_figrc_path = File.expand_path('~/.figrc')
43
+ return if not File.exists? user_figrc_path
44
+
45
+ begin
46
+ configuration.push_dataset(
47
+ JSON.parse(File::open(user_figrc_path).read)
48
+ )
49
+ rescue JSON::ParserError => exception
50
+ translate_parse_error(exception, user_figrc_path)
51
+ end
52
+
53
+ return
54
+ end
55
+
56
+ def self.handle_repository_configuration(
57
+ configuration, repository_url, login, fig_home
58
+ )
59
+ return if repository_url.nil?
60
+
61
+ figrc_url = "#{repository_url}/#{REPOSITORY_CONFIGURATION}"
62
+ repo_figrc_path =
63
+ File.expand_path(File.join(fig_home, REPOSITORY_CONFIGURATION))
64
+
65
+ os = OS.new(login)
66
+
67
+ repo_config_exists = nil
68
+ begin
69
+ os.download( figrc_url, repo_figrc_path )
70
+ repo_config_exists = true
71
+ rescue NotFoundError => e
72
+ repo_config_exists = false
73
+ end
74
+
75
+ return configuration if not repo_config_exists
76
+
77
+ begin
78
+ configuration.push_dataset(
79
+ JSON.parse(File.open(repo_figrc_path).read)
80
+ )
81
+ rescue JSON::ParserError => exception
82
+ translate_parse_error(exception, figrc_url)
83
+ end
84
+
85
+ return
86
+ end
87
+
88
+ def self.translate_parse_error(json_parse_error, config_file_path)
89
+ message = json_parse_error.message
90
+ message.chomp!
91
+
92
+ # JSON::ParserError tends to include final newline inside of single
93
+ # quotes, which makes error messages ugly.
94
+ message.sub!(/ \n+ ' \z /xm, %q<'>)
95
+
96
+ # Also, there's a useless source code line number in the message.
97
+ message.sub!(/ \A \d+ : \s+ /xm, %q<>)
98
+
99
+ raise ConfigFileError.new(
100
+ "Parse issue with #{config_file_path}: #{message}",
101
+ config_file_path
102
+ )
103
+ end
104
+ end
105
+ end
@@ -0,0 +1,197 @@
1
+ require 'fig/package'
2
+ require 'fig/package/archive'
3
+ require 'fig/package/command'
4
+ require 'fig/package/configuration'
5
+ require 'fig/package/include'
6
+ require 'fig/package/install'
7
+ require 'fig/package/override'
8
+ require 'fig/package/path'
9
+ require 'fig/package/publish'
10
+ require 'fig/package/resource'
11
+ require 'fig/package/retrieve'
12
+ require 'fig/package/set'
13
+
14
+ module Fig
15
+
16
+ grammar Fig
17
+ rule package
18
+ ws statements:(package_statement*) {
19
+ def to_package(package_name, version_name, directory)
20
+ Package.new(
21
+ package_name,
22
+ version_name,
23
+ directory,
24
+ statements.elements.map { |statement| statement.to_package_statement }
25
+ )
26
+ end
27
+ }
28
+ end
29
+
30
+ rule package_statement
31
+ archive / resource / retrieve / config
32
+ end
33
+
34
+ rule archive
35
+ "archive" ws url {
36
+ def to_package_statement
37
+ Package::Archive.new(url.value.text_value)
38
+ end
39
+ }
40
+ end
41
+
42
+ rule resource
43
+ "resource" ws url {
44
+ def to_package_statement
45
+ Package::Resource.new(url.value.text_value)
46
+ end
47
+ }
48
+ end
49
+
50
+ rule retrieve
51
+ "retrieve" ws var:retrieve_variable "->" path:retrieve_path ws {
52
+ def to_package_statement
53
+ Package::Retrieve.new(var.text_value, path.text_value)
54
+ end
55
+ }
56
+ end
57
+
58
+ rule retrieve_variable
59
+ [@a-zA-Z0-9/._]+
60
+ end
61
+
62
+ rule retrieve_path
63
+ [a-zA-Z0-9_/.\[\]-]+
64
+ end
65
+
66
+ rule install
67
+ "install" ws statements:config_statement* "end" ws {
68
+ def to_package_statement
69
+ Package::Install.new(statements.elements.map { |statement| statement.to_config_statement })
70
+ end
71
+ }
72
+ end
73
+
74
+ rule config
75
+ "config" ws config_name ws statements:config_statement* "end" ws {
76
+ def to_package_statement
77
+ Package::Configuration.new(config_name.text_value, statements.elements.map { |statement| statement.to_config_statement })
78
+ end
79
+ }
80
+ end
81
+
82
+ rule config_statement
83
+ include / command / path / set
84
+ end
85
+
86
+ rule include
87
+ "include" ws descriptor overrides:(override*) {
88
+ def to_config_statement
89
+ package = descriptor.respond_to?(:package) ? descriptor.package.text_value : nil
90
+ config = descriptor.get_config
91
+ version = descriptor.get_version
92
+ Package::Include.new(package, config, version, overrides.elements.map{ |e| e.to_override })
93
+ end
94
+ }
95
+ end
96
+
97
+ rule override
98
+ "override" ws package_name "/" version_name ws {
99
+ def to_override
100
+ return Package::Override.new(package_name.text_value, version_name.text_value)
101
+ end
102
+ }
103
+ end
104
+
105
+ rule path
106
+ ("append" / "path" / "add") ws name:path_name "=" value:path_value ws {
107
+ def to_config_statement
108
+ Package::Path.new(name.text_value, value.text_value)
109
+ end
110
+ }
111
+ end
112
+
113
+ rule path_name
114
+ [a-zA-Z0-9_]+
115
+ end
116
+
117
+ rule path_value
118
+ [@a-zA-Z0-9/\\._-]+
119
+ end
120
+
121
+ rule set
122
+ "set" ws name:set_name "=" value:set_value ws {
123
+ def to_config_statement
124
+ Package::Set.new(name.text_value, value.text_value)
125
+ end
126
+ }
127
+ end
128
+
129
+ rule set_name
130
+ [a-zA-Z0-9_]+
131
+ end
132
+
133
+ rule set_value
134
+ [@a-zA-Z0-9/\\._-]+
135
+ end
136
+
137
+ rule command
138
+ "command" ws string {
139
+ def to_config_statement
140
+ Package::Command.new(string.value.text_value)
141
+ end
142
+ }
143
+ end
144
+
145
+ rule string
146
+ '"' value:(!'"' . )* '"' ws
147
+ end
148
+
149
+ rule descriptor
150
+ ((package:package_name ("/" version:version_name)? (":" config:config_name)? ws) /
151
+ (":" config:config_name ws)) {
152
+ def get_version
153
+ elements.each do |element|
154
+ if element.respond_to?(:version)
155
+ return element.version.text_value
156
+ end
157
+ end
158
+ nil
159
+ end
160
+ def get_config
161
+ return self.config.text_value if self.respond_to?(:config)
162
+ elements.each do |element|
163
+ if element.respond_to?(:config)
164
+ return element.config.text_value
165
+ end
166
+ end
167
+ nil
168
+ end
169
+ }
170
+ end
171
+
172
+ rule package_name
173
+ [a-zA-Z0-9.-]+
174
+ end
175
+
176
+ rule version_name
177
+ [a-zA-Z0-9_.-]+
178
+ end
179
+
180
+ rule config_name
181
+ [a-zA-Z0-9_.-]+
182
+ end
183
+
184
+ rule name
185
+ value:[a-zA-Z0-9]+ ws
186
+ end
187
+
188
+ rule url
189
+ (value:[a-zA-Z0-9:/\\._*-]+ ws) / ('"' value:[a-zA-Z0-9:/\\._-]+ '"' ws)
190
+ end
191
+
192
+ rule ws
193
+ [ \n\r\t]+
194
+ end
195
+ end
196
+
197
+ end
@@ -0,0 +1,14 @@
1
+ require 'fig/userinputerror'
2
+
3
+ module Fig
4
+ class Log4rConfigError < UserInputError
5
+ def initialize(config_file, original_exception)
6
+ super(
7
+ %Q<Problem with #{config_file}: #{original_exception.message}>
8
+ )
9
+
10
+ @config_file = config_file
11
+ @original_exception = original_exception
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,131 @@
1
+ require 'log4r'
2
+ require 'log4r/configurator'
3
+ require 'log4r/yamlconfigurator'
4
+
5
+ require 'fig/configfileerror'
6
+ require 'fig/log4rconfigerror'
7
+
8
+ module Fig; end
9
+
10
+ module Fig::Logging
11
+ if not Log4r::Logger['initial']
12
+ @@logger = Log4r::Logger.new('initial')
13
+ end
14
+
15
+ STRING_TO_LEVEL_MAPPING = {
16
+ 'off' => Log4r::OFF,
17
+ 'fatal' => Log4r::FATAL,
18
+ 'error' => Log4r::ERROR,
19
+ 'warn' => Log4r::WARN,
20
+ 'info' => Log4r::INFO,
21
+ 'debug' => Log4r::DEBUG,
22
+ 'all' => Log4r::ALL
23
+ }
24
+
25
+ def self.initialize_pre_configuration(log_level = nil)
26
+ log_level ||= 'info'
27
+
28
+ assign_log_level(@@logger, log_level)
29
+ setup_default_outputter(@@logger)
30
+ end
31
+
32
+ def self.initialize_post_configuration(
33
+ config_file = nil,
34
+ log_level = nil,
35
+ suppress_default_configuration = false
36
+ )
37
+ if config_file
38
+ begin
39
+ case config_file
40
+ when / [.] xml \z /x
41
+ Log4r::Configurator.load_xml_file(config_file)
42
+ when / [.] ya?ml \z /x
43
+ Log4r::YamlConfigurator.load_yaml_file(config_file)
44
+ else
45
+ raise ConfigFileError, %Q<Don't know what format #{config_file} is in.>, config_file
46
+ end
47
+
48
+ if Log4r::Logger['fig'].nil?
49
+ $stderr.puts %q<A value was provided for --log-config but no "fig" logger was defined.>
50
+ end
51
+ rescue Log4r::ConfigError, ArgumentError => exception
52
+ raise Log4rConfigError.new(config_file, exception)
53
+ end
54
+ end
55
+
56
+ if Log4r::Logger['fig'].nil?
57
+ @@logger = Log4r::Logger.new('fig')
58
+ else
59
+ @@logger = Log4r::Logger['fig']
60
+ end
61
+
62
+ if not config_file and not suppress_default_configuration
63
+ assign_log_level(@@logger, 'info')
64
+ setup_default_outputter(@@logger)
65
+ end
66
+
67
+ assign_log_level(@@logger, log_level)
68
+
69
+ return
70
+ end
71
+
72
+ def self.fatal(data = nil, propagated = nil)
73
+ @@logger.fatal data, propagated
74
+ end
75
+
76
+ def self.fatal?()
77
+ return @@logger.fatal?
78
+ end
79
+
80
+ def self.error(data = nil, propagated = nil)
81
+ @@logger.error data, propagated
82
+ end
83
+
84
+ def self.error?()
85
+ return @@logger.error?
86
+ end
87
+
88
+ def self.warn(data = nil, propagated = nil)
89
+ @@logger.warn data, propagated
90
+ end
91
+
92
+ def self.warn?()
93
+ return @@logger.warn?
94
+ end
95
+
96
+ def self.info(data = nil, propagated = nil)
97
+ @@logger.info data, propagated
98
+ end
99
+
100
+ def self.info?()
101
+ return @@logger.info?
102
+ end
103
+
104
+ def self.debug(data = nil, propagated = nil)
105
+ @@logger.debug data, propagated
106
+ end
107
+
108
+ def self.debug?()
109
+ return @@logger.debug?
110
+ end
111
+
112
+ private
113
+
114
+ def self.assign_log_level(logger, string_level)
115
+ return if string_level.nil?
116
+
117
+ level = STRING_TO_LEVEL_MAPPING[string_level.downcase]
118
+ logger.level = level
119
+ logger.outputters.each { | outputter | outputter.level = level }
120
+
121
+ return
122
+ end
123
+
124
+ def self.setup_default_outputter(logger)
125
+ outputter = Log4r::Outputter.stdout
126
+ logger.add outputter
127
+ outputter.formatter = Log4r::PatternFormatter.new :pattern => '%M'
128
+
129
+ return
130
+ end
131
+ end
@@ -0,0 +1,7 @@
1
+ require 'fig/userinputerror'
2
+
3
+ module Fig
4
+ # A problem with file transfer over the network.
5
+ class NetworkError < UserInputError
6
+ end
7
+ end
@@ -0,0 +1,4 @@
1
+ module Fig
2
+ class NotFoundError < StandardError
3
+ end
4
+ end