fig 0.1.39 → 0.1.41

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
@@ -107,7 +107,7 @@ grammar Fig
107
107
  end
108
108
 
109
109
  rule descriptor
110
- ((package:package_name ("/" version:version_name)? (":" config:config_name)? ws) /
110
+ ((package:package_name ("/" version:version_name)? (":" config:config_name)? ws) /
111
111
  (":" config:config_name ws)) {
112
112
  def get_version
113
113
  elements.each do |element|
@@ -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
@@ -6,101 +6,238 @@ module Fig
6
6
  # todo should use treetop for these:
7
7
  package_name = descriptor =~ /^([^:\/]+)/ ? $1 : nil
8
8
  config_name = descriptor =~ /:([^:\/]+)/ ? $1 : nil
9
- version_name = descriptor =~ /\/([^:\/]+)/ ? $1 : nil
9
+ version_name = descriptor =~ /\/([^:\/]+)/ ? $1 : nil
10
10
  return package_name, config_name, version_name
11
11
  end
12
12
 
13
+ USAGE = <<EOF
14
+
15
+ Usage: fig [--debug] [--update] [--config <config>] [--get <var> | --list | <package> | -- <command>]
16
+
17
+ Relevant env vars: FIG_REMOTE_URL (required), FIG_HOME (path to local repository cache, defaults
18
+ to $HOME/.fighome).
19
+
20
+ EOF
21
+
22
+ LOG_LEVELS = %w[ off fatal error warn info debug all ]
23
+ LOG_ALIASES = { 'warning' => 'warn' }
24
+
25
+ # Returns hash of option values, the remainders of argv, and an exit code if
26
+ # full program processing occured in this method, otherwise nil.
13
27
  def parse_options(argv)
14
28
  options = {}
15
29
 
16
30
  parser = OptionParser.new do |opts|
17
- opts.banner = "Usage: fig [--debug] [--update] [--config <config>] [--get <var> | --list | <package> | - <command>]"
18
-
31
+ opts.banner = USAGE
19
32
  opts.on('-?', '-h','--help','display this help text') do
20
- puts opts
21
- exit 1
22
- end
33
+ puts opts.help
34
+ puts "\n -- end of fig options; everything following is a command to run in the fig environment.\n\n"
35
+ return nil, nil, 0
36
+ end
23
37
 
24
- options[:debug] = false
25
- opts.on('-d', '--debug', 'print debug info') { options[:debug] = true }
38
+ opts.on('-v', '--version', 'Print fig version') do
39
+ line = nil
26
40
 
27
- options[:update] = false
28
- opts.on('-u', '--update', 'check remote repository for updates') { options[:update] = true; options[:retrieve] = true }
41
+ begin
42
+ File.open(
43
+ "#{File.expand_path(File.dirname(__FILE__) + '/../../VERSION')}"
44
+ ) do |file|
45
+ line = file.gets
46
+ end
47
+ rescue
48
+ $stderr.puts 'Could not retrieve version number. Something has mucked with your gem install.'
49
+ return nil, nil, 1
50
+ end
29
51
 
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 }
52
+ if line !~ /\d+\.\d+\.\d+/
53
+ $stderr.puts %Q<"#{line}" does not look like a version number. Something has mucked with your gem install.>
54
+ return nil, nil, 1
55
+ end
32
56
 
33
- options[:config] = "default"
34
- opts.on('-c', '--config CFG', 'name of configuration to apply') { |config| options[:config] = config }
57
+ puts File.basename($0) + ' v' + line
35
58
 
36
- options[:echo] = nil
37
- opts.on('-g', '--get VAR', 'print value of environment variable') { |echo| options[:echo] = echo }
59
+ return nil, nil, 0
60
+ end
38
61
 
39
- options[:publish] = nil
40
- opts.on('--publish PKG', 'install package in local and remote repositories') { |publish| options[:publish] = publish }
62
+ options[:modifiers] = []
63
+ opts.on(
64
+ '-p',
65
+ '--append VAR=VAL',
66
+ 'append (actually, prepend) VAL to environment var VAR, delimited by separator'
67
+ ) do |var_val|
68
+ var, val = var_val.split('=')
69
+ options[:modifiers] << Path.new(var, val)
70
+ end
41
71
 
42
- options[:publish_local] = nil
43
- opts.on('--publish-local PKG', 'install package in local repositorie only') { |publish_local| options[:publish_local] = publish_local }
72
+ options[:archives] = []
73
+ opts.on(
74
+ '--archive FULLPATH',
75
+ 'include FULLPATH archive in package (when using --publish)'
76
+ ) do |path|
77
+ options[:archives] << Archive.new(path)
78
+ end
44
79
 
45
- options[:force] = nil
46
- opts.on('--force', 'force overwriting of an existing remote package version') { |force| options[:force] = force }
80
+ options[:cleans] = []
81
+ opts.on('--clean PKG', 'remove package from $FIG_HOME') do |descriptor|
82
+ options[:cleans] << descriptor
83
+ end
47
84
 
48
- options[:resources] =[]
49
- opts.on('--resource PATH', 'resource to include in package (when using --publish)') do |path|
50
- options[:resources] << Resource.new(path)
85
+ options[:config] = 'default'
86
+ opts.on(
87
+ '-c',
88
+ '--config CFG',
89
+ %q<apply configuration CFG, default is 'default'>
90
+ ) do |config|
91
+ options[:config] = config
51
92
  end
52
93
 
53
- options[:archives] =[]
54
- opts.on('--archive PATH', 'archive to include in package (when using --publish)') do |path|
55
- options[:archives] << Archive.new(path)
94
+ options[:debug] = false
95
+ opts.on('-d', '--debug', 'print debug info') do
96
+ options[:debug] = true
56
97
  end
57
98
 
58
- options[:login] = false
59
- opts.on('-l', '--login', 'login into the FTP server as a non-anonymous user') { options[:login] = true }
99
+ options[:input] = nil
100
+ opts.on(
101
+ '--file FILE',
102
+ %q<read fig file FILE. Use '-' for stdin. See also --no-file>
103
+ ) do |path|
104
+ options[:input] = path
105
+ end
106
+
107
+ options[:force] = nil
108
+ opts.on(
109
+ '--force',
110
+ 'force-overwrite existing version of a package to the remote repo'
111
+ ) do |force|
112
+ options[:force] = force
113
+ end
114
+
115
+ options[:echo] = nil
116
+ opts.on(
117
+ '-g',
118
+ '--get VAR',
119
+ 'print value of environment variable VAR'
120
+ ) do |echo|
121
+ options[:echo] = echo
122
+ end
123
+
124
+ opts.on(
125
+ '-i',
126
+ '--include PKG',
127
+ 'include PKG (with any variable prepends) in environment'
128
+ ) do |descriptor|
129
+ package_name, config_name, version_name = parse_descriptor(descriptor)
130
+ options[:modifiers] << Include.new(package_name, config_name, version_name, {})
131
+ end
60
132
 
61
133
  options[:list] = false
62
- opts.on('--list', 'list packages in local repository') { options[:list] = true }
134
+ opts.on('--list', 'list packages in $FIG_HOME') do
135
+ options[:list] = true
136
+ end
137
+
138
+ options[:list_configs] = []
139
+ opts.on(
140
+ '--list-configs PKG', 'list configurations in package'
141
+ ) do |descriptor|
142
+ options[:list_configs] << descriptor
143
+ end
63
144
 
64
145
  options[:list_remote] = false
65
- opts.on('--list-remote', 'list packages in remote repository') { options[:list_remote] = true }
146
+ opts.on('--list-remote', 'list packages in remote repo') do
147
+ options[:list_remote] = true
148
+ end
66
149
 
67
- options[:list_configs] = []
68
- opts.on('--list-configs PKG', 'list configurations in package') { |descriptor| options[:list_configs] << descriptor }
150
+ options[:login] = false
151
+ opts.on(
152
+ '-l', '--login', 'login to remote repo as a non-anonymous user'
153
+ ) do
154
+ options[:login] = true
155
+ end
69
156
 
70
- options[:cleans] = []
71
- opts.on('--clean PKG', 'remove package from local repository') { |descriptor| options[:cleans] << descriptor }
157
+ opts.on(
158
+ '--no-file', 'ignore package.fig file in current directory'
159
+ ) do |path|
160
+ options[:input] = :none
161
+ end
72
162
 
73
- options[:modifiers] = []
163
+ options[:publish] = nil
164
+ opts.on(
165
+ '--publish PKG', 'install PKG in $FIG_HOME and in remote repo'
166
+ ) do |publish|
167
+ options[:publish] = publish
168
+ end
74
169
 
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, {})
170
+ options[:publish_local] = nil
171
+ opts.on(
172
+ '--publish-local PKG', 'install package only in $FIG_HOME'
173
+ ) do |publish_local|
174
+ options[:publish_local] = publish_local
78
175
  end
79
176
 
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
177
+ options[:resources] =[]
178
+ opts.on(
179
+ '--resource FULLPATH',
180
+ 'include FULLPATH resource in package (when using --publish)'
181
+ ) do |path|
182
+ options[:resources] << Resource.new(path)
183
+ end
84
184
 
85
- opts.on('-s', '--set VAR=VAL', 'set environment variable') do |var_val|
185
+ opts.on(
186
+ '-s', '--set VAR=VAL', 'set environment variable VAR to VAL'
187
+ ) do |var_val|
86
188
  var, val = var_val.split('=')
87
- options[:modifiers] << Set.new(var, val)
189
+ options[:modifiers] << Set.new(var, val)
88
190
  end
89
191
 
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)
192
+ options[:update] = false
193
+ opts.on(
194
+ '-u',
195
+ '--update',
196
+ 'check remote repo for updates and download to $FIG_HOME as necessary'
197
+ ) do
198
+ options[:update] = true; options[:retrieve] = true
93
199
  end
94
200
 
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 }
201
+ options[:update_if_missing] = false
202
+ opts.on(
203
+ '-m',
204
+ '--update-if-missing',
205
+ 'check remote repo for updates only if package missing from $FIG_HOME'
206
+ ) do
207
+ options[:update_if_missing] = true; options[:retrieve] = true
208
+ end
209
+
210
+ opts.on(
211
+ '--figrc PATH', 'add PATH to configuration used for Fig'
212
+ ) do |path|
213
+ options[:figrc] = path
214
+ end
215
+
216
+ opts.on('--no-figrc', 'ignore ~/.figrc') { options[:no_figrc] = true }
217
+
218
+ opts.on(
219
+ '--log-config PATH', 'use PATH file as configuration for Log4r'
220
+ ) do |path|
221
+ options[:log_config] = path
222
+ end
223
+
224
+ level_list = LOG_LEVELS.join(', ')
225
+ opts.on(
226
+ '--log-level LEVEL',
227
+ LOG_LEVELS,
228
+ LOG_ALIASES,
229
+ 'set logging level to LEVEL',
230
+ " (#{level_list})"
231
+ ) do |log_level|
232
+ options[:log_level] = log_level
233
+ end
98
234
 
99
- options[:home] = ENV['FIG_HOME'] || File.expand_path("~/.fighome")
235
+ options[:home] = ENV['FIG_HOME'] || File.expand_path('~/.fighome')
100
236
  end
101
237
 
238
+ # Need to catch the exception thrown from parser and retranslate into a fig exception
102
239
  parser.parse!(argv)
103
240
 
104
- return options, argv
241
+ return options, argv, nil
105
242
  end
106
243
  end