pmsrb 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ == 0.0.1 2008-04-14
2
+
3
+ * 3 major enhancements:
4
+ * Downloading
5
+ * Extracting
6
+ * Uploading
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2008 FIXME full name
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,23 @@
1
+ History.txt
2
+ License.txt
3
+ Manifest.txt
4
+ README.txt
5
+ Rakefile
6
+ config/hoe.rb
7
+ config/requirements.rb
8
+ lib/pmsrb.rb
9
+ lib/pmsrb/platform.rb
10
+ lib/pmsrb/progressbar.rb
11
+ lib/pmsrb/version.rb
12
+ log/debug.log
13
+ script/destroy
14
+ script/generate
15
+ script/txt2html
16
+ setup.rb
17
+ spec/pmsrb_spec.rb
18
+ spec/spec.opts
19
+ spec/spec_helper.rb
20
+ tasks/deployment.rake
21
+ tasks/environment.rake
22
+ tasks/rspec.rake
23
+ tasks/website.rake
@@ -0,0 +1,73 @@
1
+ = pmsrb
2
+
3
+ http://pmsrb.rubyforge.org
4
+
5
+ == DESCRIPTION:
6
+
7
+ pmsrb is a binary (p)ackage (m)anagement (s)ystem meant for gracefully handling the differences in binary distribution on different platforms. This is useful when you rely on a large C/C++ library and would like to distribute the binaries in a cross-platform way.
8
+
9
+ For example different linux distros use RPM, deb, etc. OSX often needs to compile an xcode project to install a binary. Windows is actually much cleaner in this occasion.
10
+
11
+ We could rely on the user installing these binary packages, but often times problems arise when someone installs version 1.4.6 by mistake, and your bindings are built against 1.4.7.
12
+
13
+ On top of this there are sometimes issues you need to hack around when using swig on source libraries. That means that the binaries you distribute may be different than the ones that are publicly available.
14
+
15
+ This library handles all these edge cases, and automates maintenance on upgrading, platform support, etc.
16
+
17
+ == FEATURES/PROBLEMS:
18
+
19
+ There are no problems whatsoever. But let me know if you find some.
20
+
21
+ PMS supports:
22
+ *downloading from ftp/http
23
+ *uploading via scp,ftp
24
+ *extracting to .tgz, .zip
25
+ *archiving to .tgz, .zip
26
+ *building(via shell commands)
27
+ *delicious low fat Platform
28
+
29
+ == SYNOPSIS:
30
+
31
+ PMS::vendor do
32
+ working_directory File.dirname(__FILE__)+"/tmp"
33
+ if Platform.windows?
34
+ download "http://bullet.googlecode.com/files/bullet-#{Bulletrb::VERSION::VENDOR}.zip"
35
+ else
36
+ download "http://bullet.googlecode.com/files/bullet-#{Bulletrb::VERSION::VENDOR}.tgz"
37
+ end
38
+ extract
39
+ build "./configure", "jam" if Platform.linux? || Platform.mac?
40
+ end
41
+
42
+ == REQUIREMENTS:
43
+
44
+ Windows, Mac, or Linux. Ruby 1.8.
45
+
46
+ == INSTALL:
47
+
48
+ sudo gem install pmsrb
49
+
50
+ == LICENSE:
51
+
52
+ (The MIT License)
53
+
54
+ Copyright (c) 2008 FIX
55
+
56
+ Permission is hereby granted, free of charge, to any person obtaining
57
+ a copy of this software and associated documentation files (the
58
+ 'Software'), to deal in the Software without restriction, including
59
+ without limitation the rights to use, copy, modify, merge, publish,
60
+ distribute, sublicense, and/or sell copies of the Software, and to
61
+ permit persons to whom the Software is furnished to do so, subject to
62
+ the following conditions:
63
+
64
+ The above copyright notice and this permission notice shall be
65
+ included in all copies or substantial portions of the Software.
66
+
67
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
68
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
69
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
70
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
71
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
72
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
73
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,4 @@
1
+ require 'config/requirements'
2
+ require 'config/hoe' # setup Hoe + all gem configuration
3
+
4
+ Dir['tasks/**/*.rake'].each { |rake| load rake }
@@ -0,0 +1,73 @@
1
+ require 'pmsrb/version'
2
+
3
+ AUTHOR = ['Martyn Garcia', 'Mikkel Garcia'] # can also be an array of Authors
4
+ EMAIL = ""
5
+ DESCRIPTION = "pmsrb is a binary (p)ackage (m)anagement (s)ystem meant for gracefully handling the differences in binary distribution on different platforms."
6
+ GEM_NAME = 'pmsrb' # what ppl will type to install your gem
7
+ RUBYFORGE_PROJECT = 'pmsrb' # The unix name for your project
8
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
9
+ DOWNLOAD_PATH = "http://rubyforge.org/projects/#{RUBYFORGE_PROJECT}"
10
+
11
+ @config_file = "~/.rubyforge/user-config.yml"
12
+ @config = nil
13
+ RUBYFORGE_USERNAME = "unknown"
14
+ def rubyforge_username
15
+ unless @config
16
+ begin
17
+ @config = YAML.load(File.read(File.expand_path(@config_file)))
18
+ rescue
19
+ puts <<-EOS
20
+ ERROR: No rubyforge config file found: #{@config_file}
21
+ Run 'rubyforge setup' to prepare your env for access to Rubyforge
22
+ - See http://newgem.rubyforge.org/rubyforge.html for more details
23
+ EOS
24
+ exit
25
+ end
26
+ end
27
+ RUBYFORGE_USERNAME.replace @config["username"]
28
+ end
29
+
30
+
31
+ REV = nil
32
+ # UNCOMMENT IF REQUIRED:
33
+ # REV = `svn info`.each {|line| if line =~ /^Revision:/ then k,v = line.split(': '); break v.chomp; else next; end} rescue nil
34
+ VERS = Pmsrb::VERSION::STRING + (REV ? ".#{REV}" : "")
35
+ RDOC_OPTS = ['--quiet', '--title', 'pmsrb documentation',
36
+ "--opname", "index.html",
37
+ "--line-numbers",
38
+ "--main", "README",
39
+ "--inline-source"]
40
+
41
+ class Hoe
42
+ def extra_deps
43
+ @extra_deps.reject! { |x| Array(x).first == 'hoe' }
44
+ @extra_deps
45
+ end
46
+ end
47
+
48
+ # Generate all the Rake tasks
49
+ # Run 'rake -T' to see list of generated tasks (from gem root directory)
50
+ hoe = Hoe.new(GEM_NAME, VERS) do |p|
51
+ p.developer(AUTHOR, EMAIL)
52
+ p.description = DESCRIPTION
53
+ p.summary = DESCRIPTION
54
+ p.url = HOMEPATH
55
+ p.rubyforge_name = RUBYFORGE_PROJECT if RUBYFORGE_PROJECT
56
+ p.test_globs = ["test/**/test_*.rb"]
57
+ p.clean_globs |= ['**/.*.sw?', '*.gem', '.config', '**/.DS_Store'] #An array of file patterns to delete on clean.
58
+
59
+ # == Optional
60
+ p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
61
+
62
+ # An array of rubygem dependencies [name, version], e.g. [ ['active_support', '>= 1.3.1'] ]
63
+ p.extra_deps = [['archive-tar-minitar', '>= 0.5.2'],
64
+ ['rubyzip', '>= 0.9.1']]
65
+
66
+ #p.spec_extras = {} # A hash of extra values to set in the gemspec.
67
+
68
+ end
69
+
70
+ CHANGES = hoe.paragraphs_of('History.txt', 0..1).join("\\n\\n")
71
+ PATH = (RUBYFORGE_PROJECT == GEM_NAME) ? RUBYFORGE_PROJECT : "#{RUBYFORGE_PROJECT}/#{GEM_NAME}"
72
+ hoe.remote_rdoc_dir = File.join(PATH.gsub(/^#{RUBYFORGE_PROJECT}\/?/,''), 'rdoc')
73
+ hoe.rsync_args = '-av --delete --ignore-errors'
@@ -0,0 +1,17 @@
1
+ require 'fileutils'
2
+ include FileUtils
3
+
4
+ require 'rubygems'
5
+ %w[rake hoe newgem rubigen].each do |req_gem|
6
+ begin
7
+ require req_gem
8
+ rescue LoadError
9
+ puts "This Rakefile requires the '#{req_gem}' RubyGem."
10
+ puts "Installation: gem install #{req_gem} -y"
11
+ exit
12
+ end
13
+ end
14
+
15
+ $:.unshift(File.join(File.dirname(__FILE__), %w[.. lib]))
16
+
17
+ require 'pmsrb'
@@ -0,0 +1,310 @@
1
+ $:.unshift File.dirname(__FILE__)
2
+
3
+ require 'pmsrb/platform'
4
+ require 'pmsrb/progressbar'
5
+
6
+ require 'net/ftp'
7
+ require 'open-uri'
8
+
9
+ require 'rubygems'
10
+ require 'fileutils'
11
+
12
+ require 'zlib'
13
+ require 'archive/tar/minitar'
14
+
15
+ require 'zip/zipfilesystem'
16
+
17
+ module PMS
18
+ def vendor(&block)
19
+ vendor = Vendor.new
20
+ vendor.run(&block)
21
+ return vendor
22
+ end
23
+
24
+ class Vendor
25
+ def run(&block)
26
+ instance_eval(&block)
27
+ end
28
+
29
+ def download(url, storage_dir=nil)
30
+ working_directory(storage_dir) unless storage_dir.nil?
31
+ raise Exception.new("Working directory not defined") if @working_directory.nil?
32
+
33
+ filename = url.split("/")[-1]
34
+
35
+ unless(File.exists?@working_directory+"/"+filename)
36
+ puts "downloading #{url}"
37
+ FileUtils.mkdir_p @working_directory
38
+
39
+ pbar = nil
40
+
41
+ # Called before file transfer
42
+ content_length_proc = lambda do |size|
43
+ if size && 0 < size
44
+ pbar = ProgressBar.new("Download", size)
45
+ pbar.file_transfer_mode
46
+ end
47
+ end
48
+
49
+ # Called during file transfer
50
+ progress_proc = lambda do |bytes_transferred|
51
+ pbar.set(bytes_transferred) if pbar
52
+ end
53
+
54
+ open(url,:content_length_proc => content_length_proc,:progress_proc => progress_proc) do |result|
55
+ File.open(@working_directory+"/"+filename, "wb") do |file|
56
+ result.each do |bytes|
57
+ file.write(bytes)
58
+ end
59
+ end
60
+ pbar.finish if pbar
61
+ end
62
+
63
+ end
64
+
65
+ @current_file = @working_directory+"/"+filename
66
+ end
67
+
68
+ def extract
69
+ puts "extracting #{@current_file}"
70
+ extract_tgz if /.tar.gz$/ === @current_file || /.tgz$/ === @current_file
71
+ extract_zip if /.zip$/ === @current_file
72
+ end
73
+
74
+ def extract_tgz
75
+ pwd = File.expand_path(FileUtils.pwd)
76
+ FileUtils.cd @working_directory
77
+
78
+ #This is breaking on a large tar archive unfortunately. So we resort to cli
79
+ #file = File.open(@current_file, 'rb')
80
+ #tgz = Zlib::GzipReader.new(file)
81
+ #Archive::Tar::Minitar.unpack tgz, @working_directory
82
+
83
+ `tar xzvf #{@current_file[(@working_directory.length+1)..-1]}`
84
+
85
+ FileUtils.cd pwd
86
+ end
87
+
88
+ def extract_zip
89
+ Zip::ZipFile.open(@current_file) do |zipfile|
90
+ zipfile.each do |file|
91
+ fpath = File.join(@working_directory, file.name)
92
+ FileUtils.mkdir_p(File.dirname(fpath))
93
+ zipfile.extract file, fpath
94
+ end
95
+ end
96
+ end
97
+
98
+ def working_directory(dir)
99
+ @working_directory = dir
100
+ end
101
+
102
+ def cd(dir)
103
+ @working_directory += "/#{dir}"
104
+ end
105
+
106
+ def build(*commands)
107
+ pwd = File.expand_path(FileUtils.pwd)
108
+ FileUtils.cd @working_directory
109
+
110
+ puts "running #{commands.join(' && ')}"
111
+
112
+ output = system(commands.join(" &&"))
113
+ FileUtils.cd pwd
114
+
115
+ return output
116
+ end
117
+
118
+ def cp(pattern, newdir)
119
+ newdir = "#{@working_directory}/#{newdir}"
120
+ files = Dir["#{@working_directory}/#{pattern}"]
121
+
122
+ if files.length == 1
123
+ file = files[0]
124
+ FileUtils.mkdir_p File.dirname(newdir)
125
+ FileUtils.cp_r file, newdir unless FileTest.directory? file
126
+ else
127
+ files.each do |file|
128
+ dest = newdir + (File.dirname(file))[@working_directory.length..-1]
129
+ FileUtils.mkdir_p dest
130
+ FileUtils.cp file, dest unless FileTest.directory? file
131
+ end
132
+ end
133
+ end
134
+
135
+ def install(pattern, newdir)
136
+ FileUtils.rm_r "#{@working_directory}/#{newdir}" if File.exists? "#{@working_directory}/#{newdir}"
137
+ cp pattern, newdir
138
+ end
139
+
140
+ def touch(file)
141
+ FileUtils.touch(File.join(@working_directory,file))
142
+ end
143
+
144
+ def rm(file)
145
+ FileUtils.rm(File.join(@working_directory, file))
146
+ end
147
+
148
+ def upload(filename, &block)
149
+ raise Exception.new("Working directory not defined") if @working_directory.nil?
150
+
151
+ fullpath = File.join(@working_directory, filename)
152
+ raise Exception.new("No file '#{filename}' found in '#{@working_directory}'") unless File.exists?(fullpath)
153
+
154
+ transfer = FTPTransfer.new
155
+ transfer.run(&block)
156
+ transfer.upload(fullpath, filename)
157
+ end
158
+
159
+ def expand_filelist filelist
160
+ retv = nil
161
+ pwd = File.expand_path(FileUtils.pwd)
162
+ FileUtils.cd @working_directory
163
+ if filelist.is_a? Array
164
+ retv = filelist
165
+ else
166
+ retv = Dir.glob(filelist)
167
+ end
168
+ FileUtils.cd pwd
169
+ return retv
170
+ end
171
+
172
+ def archive(filelist, archive)
173
+ filelist = expand_filelist filelist
174
+ puts "archiving #{filelist}"
175
+ if /.tgz$/ === archive || /.tar.gz$/ === archive
176
+ archive_tgz filelist, archive
177
+ elsif /.zip$/ === archive
178
+ archive_zip filelist, archive
179
+ else
180
+ raise Exception.new("archive type '#{archive}' is not supported")
181
+ end
182
+ end
183
+
184
+ def archive_tgz(filelist, archive)
185
+ verify_archive_files(filelist, archive)
186
+
187
+ pwd = File.expand_path(FileUtils.pwd)
188
+ FileUtils.cd @working_directory
189
+ File.open("#{archive}", 'wb') do |archivefile|
190
+ tgz = Zlib::GzipWriter.new(archivefile)
191
+ Archive::Tar::Minitar.pack filelist, tgz
192
+ end
193
+ FileUtils.cd pwd
194
+ end
195
+
196
+ def archive_zip(filelist, archive)
197
+ verify_archive_files(filelist, archive)
198
+
199
+ zf = Zip::ZipFile.new(File.join(FileUtils.pwd, @working_directory, archive), true)
200
+
201
+ filelist.each do |file|
202
+ full_path_to_file = File.join(FileUtils.pwd, @working_directory,file)
203
+ if File.file? full_path_to_file
204
+ zf.add(file, full_path_to_file)
205
+ end
206
+ end
207
+
208
+ zf.close
209
+ end
210
+
211
+ def verify_archive_files(filelist, archive)
212
+ raise Exception.new("archive '#{archive}' already exists") if File.exists?(File.join(@working_directory,archive))
213
+ filelist.each do |file|
214
+ raise Exception.new("file '#{file}' in filelist for archive '#{archive}' does not exist") unless File.exists?(File.join(@working_directory,file))
215
+ end
216
+ end
217
+ end
218
+
219
+ class FTPTransfer
220
+ def run(&block)
221
+ instance_eval(&block)
222
+ end
223
+
224
+ #Credential files are very simple, in the form of:
225
+ # username <user>
226
+ # password <password>
227
+ def credentials(filename)
228
+ credentials = Credentials.new(filename)
229
+ @user = credentials.user
230
+ @pass = credentials.pass
231
+ return credentials
232
+ end
233
+
234
+ def username(name)
235
+ @user = name
236
+ end
237
+
238
+ def password(pass)
239
+ @pass = pass
240
+ end
241
+
242
+ def host(host)
243
+ @host = host
244
+ end
245
+
246
+ def target_directory(path)
247
+ @target_directory = path
248
+ end
249
+
250
+ def cd(ftp, dir)
251
+ ftp.chdir dir
252
+ end
253
+
254
+ def mkdir_p(ftp, dir)
255
+ path = dir.split("/")
256
+ pwd = ftp.pwd
257
+ path.each do |dir|
258
+ begin
259
+ ftp.mkdir dir
260
+ cd ftp, dir
261
+ rescue Net::FTPPermError
262
+ cd ftp, dir
263
+ end
264
+ end
265
+ cd ftp, pwd
266
+ end
267
+
268
+ def upload(fullpath, filename)
269
+ Net::FTP.open(@host) do |ftp|
270
+ puts "uploading #{fullpath}"
271
+ pbar = ProgressBar.new("Upload", File.size(fullpath))
272
+ pbar.file_transfer_mode
273
+ ftp.login(@user,@pass)
274
+ mkdir_p ftp, @target_directory
275
+ cd ftp, @target_directory
276
+ ftp.putbinaryfile(fullpath, filename, 1024) do |data|
277
+ pbar.set(pbar.current+data.length)
278
+ end
279
+ pbar.finish
280
+ end
281
+ end
282
+
283
+ end
284
+
285
+ class Credentials
286
+ attr_reader :user, :pass
287
+ def initialize(filename)
288
+ filepath=ENV["HOME"]+"/"+filename
289
+ if(File.exists?(filepath))
290
+ File.open(filepath).each do |line|
291
+ line.chomp!
292
+ op, arg = line.split(" ")
293
+ if op.strip =~ /user/
294
+ @user = arg
295
+ elsif op.strip == 'password'
296
+ @pass = arg
297
+ end
298
+ end
299
+ else
300
+ # pmsrb file not defined
301
+ puts "'#{filepath}' not found. Create it to autoconnect with '#{@host}': \n username <user>\n password <pass>\nto skip this dialog."
302
+ puts "Username for #{@host}'s ftp:"
303
+ @user = gets.chomp
304
+ puts "password: "
305
+ @pass = gets.chomp
306
+ end
307
+ end
308
+ end
309
+
310
+ end