fig 0.1.39 → 0.1.41

Sign up to get free protection for your applications and to get access to all the features.
@@ -10,23 +10,24 @@ require 'net/netrc'
10
10
  require 'tempfile'
11
11
  require 'highline/import'
12
12
 
13
- module Fig
14
- class NotFoundException < Exception
15
- end
13
+ require 'fig/logging'
14
+ require 'fig/networkerror'
15
+ require 'fig/notfounderror'
16
16
 
17
+ module Fig
17
18
  class OS
18
19
  def initialize(login)
19
20
  @login = login
20
- @username = ENV["FIG_USERNAME"]
21
- @password = ENV["FIG_PASSWORD"]
21
+ @username = ENV['FIG_USERNAME']
22
+ @password = ENV['FIG_PASSWORD']
22
23
  end
23
24
 
24
25
  def get_username()
25
- @username ||= ask("Username: ") { |q| q.echo = true }
26
+ @username ||= ask('Username: ') { |q| q.echo = true }
26
27
  end
27
-
28
+
28
29
  def get_password()
29
- @password ||= ask("Password: ") { |q| q.echo = false }
30
+ @password ||= ask('Password: ') { |q| q.echo = false }
30
31
  end
31
32
 
32
33
  def ftp_login(ftp, host)
@@ -37,7 +38,7 @@ module Fig
37
38
  @password = rc.password
38
39
  end
39
40
  ftp.login(get_username, get_password)
40
- else
41
+ else
41
42
  ftp.login()
42
43
  end
43
44
  ftp.passive = true
@@ -46,36 +47,36 @@ module Fig
46
47
  def list(dir)
47
48
  Dir.entries(dir) - ['.','..']
48
49
  end
49
-
50
+
50
51
  def exist?(path)
51
52
  File.exist?(path)
52
53
  end
53
-
54
+
54
55
  def mtime(path)
55
56
  File.mtime(path)
56
57
  end
57
-
58
+
58
59
  def read(path)
59
60
  File.read(path)
60
61
  end
61
-
62
+
62
63
  def write(path, content)
63
- File.open(path, "wb") { |f| f.binmode; f << content }
64
+ File.open(path, 'wb') { |f| f.binmode; f << content }
64
65
  end
65
-
66
+
66
67
  SUCCESS = 0
67
68
  NOT_MODIFIED = 3
68
69
  NOT_FOUND = 4
69
-
70
+
70
71
  def download_list(url)
71
72
  begin
72
73
  uri = URI.parse(url)
73
- rescue
74
- $stderr.puts "Unable to parse url: '#{url}'"
75
- exit 10
74
+ rescue
75
+ Logging.fatal %Q<Unable to parse url: "#{url}">
76
+ raise NetworkError.new
76
77
  end
77
78
  case uri.scheme
78
- when "ftp"
79
+ when 'ftp'
79
80
  ftp = Net::FTP.new(uri.host)
80
81
  ftp_login(ftp, uri.host)
81
82
  ftp.chdir(uri.path)
@@ -83,12 +84,12 @@ module Fig
83
84
  ftp.close
84
85
 
85
86
  download_ftp_list(uri, dirs)
86
- when "ssh"
87
+ when 'ssh'
87
88
  packages = []
88
89
  Net::SSH.start(uri.host, uri.user) do |ssh|
89
90
  ls = ssh.exec!("[ -d #{uri.path} ] && find #{uri.path}")
90
91
  if not ls.nil?
91
- ls = ls.gsub(uri.path + "/", "").gsub(uri.path, "").split("\n")
92
+ ls = ls.gsub(uri.path + '/', '').gsub(uri.path, '').split("\n")
92
93
  ls.each do |line|
93
94
  parts = line.gsub(/\\/, '/').sub(/^\.\//, '').sub(/:$/, '').chomp().split('/')
94
95
  packages << parts.join('/') if parts.size == 2
@@ -97,16 +98,16 @@ module Fig
97
98
  end
98
99
  packages
99
100
  else
100
- $stderr.puts "Protocol not supported: #{url}"
101
- exit 10
101
+ Logging.fatal "Protocol not supported: #{url}"
102
+ raise NetworkError.new
102
103
  end
103
104
  end
104
105
 
105
106
  def download_ftp_list(uri, dirs)
106
107
  # Run a bunch of these in parallel since they're slow as hell
107
- num_threads = (ENV["FIG_FTP_THREADS"] || "16").to_i
108
+ num_threads = (ENV['FIG_FTP_THREADS'] || '16').to_i
108
109
  threads = []
109
- all_packages = []
110
+ all_packages = []
110
111
  (0..num_threads-1).each { |num| all_packages[num] = [] }
111
112
  (0..num_threads-1).each do |num|
112
113
  threads << Thread.new do
@@ -137,46 +138,49 @@ module Fig
137
138
  FileUtils.mkdir_p(File.dirname(path))
138
139
  uri = URI.parse(url)
139
140
  case uri.scheme
140
- when "ftp"
141
+ when 'ftp'
141
142
  ftp = Net::FTP.new(uri.host)
142
143
  ftp_login(ftp, uri.host)
143
144
  begin
144
145
  if File.exist?(path) && ftp.mtime(uri.path) <= File.mtime(path)
146
+ Logging.debug "#{path} is up to date."
145
147
  return false
146
- else
147
- $stderr.puts "downloading #{url}"
148
+ else
149
+ log_download(url, path)
148
150
  ftp.getbinaryfile(uri.path, path, 256*1024)
149
151
  return true
150
152
  end
151
- rescue Net::FTPPermError
152
- raise NotFoundException.new
153
+ rescue Net::FTPPermError => e
154
+ Logging.warn e
155
+ raise NotFoundError.new
153
156
  end
154
- when "http"
157
+ when 'http'
155
158
  http = Net::HTTP.new(uri.host)
156
- $stderr.puts "downloading #{url}"
157
- File.open(path, "wb") do |file|
159
+ log_download(url, path)
160
+ File.open(path, 'wb') do |file|
158
161
  file.binmode
159
162
  http.get(uri.path) do |block|
160
163
  file.write(block)
161
164
  end
162
165
  end
163
- when "ssh"
166
+ when 'ssh'
164
167
  # TODO need better way to do conditional download
165
- # timestamp = `ssh #{uri.user + '@' if uri.user}#{uri.host} "ruby -e 'puts File.mtime(\\"#{uri.path}\\").to_i'"`.to_i
166
- timestamp = File.exist?(path) ? File.mtime(path).to_i : 0
168
+ timestamp = File.exist?(path) ? File.mtime(path).to_i : 0
169
+ # Requires that remote installation of fig be at the same location as the local machine.
167
170
  cmd = `which fig-download`.strip + " #{timestamp} #{uri.path}"
171
+ log_download(url, path)
168
172
  ssh_download(uri.user, uri.host, path, cmd)
169
173
  else
170
- $stderr.puts "Unknown protocol: #{url}"
171
- exit 10
174
+ Logging.fatal "Unknown protocol: #{url}"
175
+ raise NetworkError.new
172
176
  end
173
- end
174
-
177
+ end
178
+
175
179
  def download_resource(url, dir)
176
180
  FileUtils.mkdir_p(dir)
177
181
  download(url, File.join(dir, URI.parse(url).path.split('/').last))
178
182
  end
179
-
183
+
180
184
  def download_archive(url, dir)
181
185
  FileUtils.mkdir_p(dir)
182
186
  basename = URI.parse(url).path.split('/').last
@@ -192,25 +196,25 @@ module Fig
192
196
  when /\.zip$/
193
197
  unpack_archive(dir, path)
194
198
  else
195
- $stderr.puts "Unknown archive type: #{basename}"
196
- exit 10
199
+ Logging.fatal "Unknown archive type: #{basename}"
200
+ raise NetworkError.new
197
201
  end
198
202
  end
199
-
203
+
200
204
  def upload(local_file, remote_file, user)
201
- puts "uploading #{local_file} to #{remote_file}"
205
+ Logging.debug "Uploading #{local_file} to #{remote_file}."
202
206
  uri = URI.parse(remote_file)
203
207
  case uri.scheme
204
- when "ssh"
208
+ when 'ssh'
205
209
  ssh_upload(uri.user, uri.host, local_file, remote_file)
206
- when "ftp"
210
+ when 'ftp'
207
211
  # fail unless system "curl -T #{local_file} --create-dirs --ftp-create-dirs #{remote_file}"
208
212
  require 'net/ftp'
209
- ftp_uri = URI.parse(ENV["FIG_REMOTE_URL"])
213
+ ftp_uri = URI.parse(ENV['FIG_REMOTE_URL'])
210
214
  ftp_root_path = ftp_uri.path
211
- ftp_root_dirs = ftp_uri.path.split("/")
212
- remote_publish_path = uri.path[0, uri.path.rindex("/")]
213
- remote_publish_dirs = remote_publish_path.split("/")
215
+ ftp_root_dirs = ftp_uri.path.split('/')
216
+ remote_publish_path = uri.path[0, uri.path.rindex('/')]
217
+ remote_publish_dirs = remote_publish_path.split('/')
214
218
  # Use array subtraction to deduce which project/version folder to upload to,
215
219
  # i.e. [1,2,3] - [2,3,4] = [1]
216
220
  remote_project_dirs = remote_publish_dirs - ftp_root_dirs
@@ -231,26 +235,17 @@ module Fig
231
235
  end
232
236
  end
233
237
  end
234
-
238
+
235
239
  def clear_directory(dir)
236
240
  FileUtils.rm_rf(dir)
237
241
  FileUtils.mkdir_p(dir)
238
242
  end
239
243
 
240
- def exec(dir,command)
241
- Dir.chdir(dir) {
242
- unless system command
243
- $stderr.puts "Command failed"
244
- exit 10
245
- end
246
- }
247
- end
248
-
249
244
  def copy(source, target, msg = nil)
250
245
  if File.directory?(source)
251
246
  FileUtils.mkdir_p(target)
252
247
  Dir.foreach(source) do |child|
253
- if child != "." and child != ".."
248
+ if child != '.' and child != '..'
254
249
  copy(File.join(source, child), File.join(target, child), msg)
255
250
  end
256
251
  end
@@ -267,9 +262,9 @@ module Fig
267
262
  def move_file(dir, from, to)
268
263
  Dir.chdir(dir) { FileUtils.mv(from, to, :force => true) }
269
264
  end
270
-
265
+
271
266
  def log_info(msg)
272
- $stderr.puts msg
267
+ Logging.info msg
273
268
  end
274
269
 
275
270
  # Expects files_to_archive as an Array of filenames.
@@ -339,8 +334,8 @@ module Fig
339
334
  end
340
335
 
341
336
  def shell_exec_windows(cmd)
342
- #command = ["C:/WINDOWS/system32/cmd.exe", "/C", "call"] + cmd
343
- command = ["cmd.exe", "/C"] + cmd
337
+ #command = ['C:/WINDOWS/system32/cmd.exe', '/C', 'call'] + cmd
338
+ command = ['cmd.exe', '/C'] + cmd
344
339
  command = command.join(' ')
345
340
  Kernel.exec(command)
346
341
  end
@@ -349,13 +344,13 @@ module Fig
349
344
  # cmd = The command to be run on the remote host.
350
345
  def ssh_download(user, host, path, cmd)
351
346
  return_code = nil
352
- tempfile = Tempfile.new("tmp")
347
+ tempfile = Tempfile.new('tmp')
353
348
  Net::SSH.start(host, user) do |ssh|
354
349
  ssh.open_channel do |channel|
355
350
  channel.exec(cmd)
356
351
  channel.on_data() { |ch, data| tempfile << data }
357
- channel.on_extended_data() { |ch, type, data| $stderr.puts "SSH Download ERROR: #{data}" }
358
- channel.on_request("exit-status") { |ch, request|
352
+ channel.on_extended_data() { |ch, type, data| Logging.error "SSH Download ERROR: #{data}" }
353
+ channel.on_request('exit-status') { |ch, request|
359
354
  return_code = request.read_long
360
355
  }
361
356
  end
@@ -369,15 +364,14 @@ module Fig
369
364
  return false
370
365
  when NOT_FOUND
371
366
  tempfile.delete
372
- $stderr.puts "File not found: #{path}"
373
- exit 10
367
+ raise NotFoundError.new
374
368
  when SUCCESS
375
369
  FileUtils.mv(tempfile.path, path)
376
370
  return true
377
371
  else
378
372
  tempfile.delete
379
- $stderr.puts "Unable to download file: #{return_code}"
380
- exit 1
373
+ Logging.fatal "Unable to download file #{path}: #{return_code}"
374
+ raise NetworkError.new
381
375
  end
382
376
  end
383
377
 
@@ -392,5 +386,10 @@ module Fig
392
386
  end
393
387
  end
394
388
 
389
+ private
390
+
391
+ def log_download(url, path)
392
+ Logging.debug "Downloading #{url} to #{path}."
393
+ end
395
394
  end
396
395
  end
@@ -1,22 +1,25 @@
1
+ require 'fig/logging'
2
+ require 'fig/packageerror'
3
+
1
4
  module Fig
2
5
  class Package
3
6
  attr_reader :package_name, :version_name, :directory, :statements
4
7
  attr_accessor :backtrace
5
-
6
- def initialize(package_name, version_name, directory, statements)
8
+
9
+ def initialize(package_name, version_name, directory, statements)
7
10
  @package_name = package_name
8
11
  @version_name = version_name
9
12
  @directory = directory
10
13
  @statements = statements
11
14
  @backtrace = nil
12
15
  end
13
-
16
+
14
17
  def [](config_name)
15
18
  @statements.each do |stmt|
16
19
  return stmt if stmt.is_a?(Configuration) && stmt.name == config_name
17
20
  end
18
- $stderr.puts "Configuration not found: #{@package_name}/#{@version_name}:#{config_name}"
19
- exit 10
21
+ Fig::Logging.fatal "Configuration not found: #{@package_name}/#{@version_name}:#{config_name}"
22
+ raise PackageError.new
20
23
  end
21
24
 
22
25
  def configs
@@ -32,11 +35,11 @@ module Fig
32
35
  def archive_urls
33
36
  @statements.select{|s| s.is_a?(Archive)}.map{|s|s.url}
34
37
  end
35
-
38
+
36
39
  def resource_urls
37
40
  @statements.select{|s| s.is_a?(Resource)}.map{|s|s.url}
38
41
  end
39
-
42
+
40
43
  def unparse
41
44
  @statements.map { |statement| statement.unparse('') }.join("\n")
42
45
  end
@@ -46,34 +49,34 @@ module Fig
46
49
  end
47
50
 
48
51
  def to_s
49
- @package_name + "/" + @version_name
52
+ @package_name + '/' + @version_name
50
53
  end
51
54
  end
52
-
55
+
53
56
  class Archive
54
57
  attr_reader :url
55
-
58
+
56
59
  def initialize(url)
57
60
  @url = url
58
61
  end
59
-
62
+
60
63
  def unparse(indent)
61
- "#{indent}archive \"#{url}\""
64
+ %Q<#{indent}archive "#{url}">
62
65
  end
63
66
  end
64
-
67
+
65
68
  class Resource
66
69
  attr_reader :url
67
-
70
+
68
71
  def initialize(url)
69
72
  @url = url
70
73
  end
71
-
74
+
72
75
  def unparse(indent)
73
76
  "#{indent}resource #{url}"
74
77
  end
75
78
  end
76
-
79
+
77
80
  class Retrieve
78
81
  attr_reader :var, :path
79
82
 
@@ -94,7 +97,7 @@ module Fig
94
97
  @local_name = local_name
95
98
  @remote_name = remote_name
96
99
  end
97
-
100
+
98
101
  def unparse(indent)
99
102
  "#{indent}publish #{@local_name}->#{@remote_name}"
100
103
  end
@@ -110,9 +113,9 @@ module Fig
110
113
  body = @statements.map { |statement| statement.unparse(indent+' ') }.join("\n")
111
114
  suffix = "#{indent}end"
112
115
  return [prefix, body, suffix].join("\n")
113
- end
116
+ end
114
117
  end
115
-
118
+
116
119
  class Configuration
117
120
  attr_reader :name, :statements
118
121
 
@@ -127,14 +130,11 @@ module Fig
127
130
 
128
131
  def commands
129
132
  result = statements.select { |statement| statement.is_a?(Command) }
130
- # if result.empty?
131
- # raise "No commands found for config: #{@name}"
132
- # end
133
133
  result
134
134
  end
135
135
 
136
136
  def unparse(indent)
137
- unparse_statements(indent, "config #{@name}", @statements, "end")
137
+ unparse_statements(indent, "config #{@name}", @statements, 'end')
138
138
  end
139
139
  end
140
140
 
@@ -145,7 +145,7 @@ module Fig
145
145
  @name = name
146
146
  @value = value
147
147
  end
148
-
148
+
149
149
  def unparse(indent)
150
150
  "#{indent}append #{name}=#{value}"
151
151
  end
@@ -158,7 +158,7 @@ module Fig
158
158
  @name = name
159
159
  @value = value
160
160
  end
161
-
161
+
162
162
  def unparse(indent)
163
163
  "#{indent}set #{name}=#{value}"
164
164
  end
@@ -175,7 +175,7 @@ module Fig
175
175
  end
176
176
 
177
177
  def unparse(indent)
178
- descriptor = ""
178
+ descriptor = ''
179
179
  descriptor += @package_name if @package_name
180
180
  descriptor += "/#{@version_name}" if @version_name
181
181
  descriptor += ":#{@config_name}" if @config_name
@@ -188,14 +188,14 @@ module Fig
188
188
 
189
189
  class Override
190
190
  attr_reader :package_name, :version_name
191
-
191
+
192
192
  def initialize(package_name, version_name)
193
193
  @package_name = package_name
194
194
  @version_name = version_name
195
195
  end
196
196
 
197
197
  def unparse()
198
- return " override " + @package_name + "/" + @version_name
198
+ return ' override ' + @package_name + '/' + @version_name
199
199
  end
200
200
  end
201
201
 
@@ -207,7 +207,7 @@ module Fig
207
207
  end
208
208
 
209
209
  def unparse(indent)
210
- "#{indent}command \"#{@command}\""
210
+ %Q<#{indent}command "#{@command}">
211
211
  end
212
212
  end
213
213
 
@@ -216,5 +216,5 @@ end
216
216
  def unparse_statements(indent, prefix, statements, suffix)
217
217
  body = @statements.map { |statement| statement.unparse(indent+' ') }.join("\n")
218
218
  return ["\n#{indent}#{prefix}", body, "#{indent}#{suffix}"].join("\n")
219
- end
219
+ end
220
220