pmsrb 0.1.0 → 0.2.0
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/Manifest.txt +2 -1
- data/lib/pmsrb.rb +55 -11
- data/lib/pmsrb/memory_profile.rb +155 -0
- data/lib/pmsrb/platform.rb +12 -0
- data/lib/pmsrb/version.rb +1 -1
- data/spec/pmsrb_spec.rb +26 -0
- metadata +3 -2
data/Manifest.txt
CHANGED
@@ -9,6 +9,7 @@ lib/pmsrb.rb
|
|
9
9
|
lib/pmsrb/platform.rb
|
10
10
|
lib/pmsrb/progressbar.rb
|
11
11
|
lib/pmsrb/version.rb
|
12
|
+
lib/pmsrb/memory_profile.rb
|
12
13
|
log/debug.log
|
13
14
|
script/destroy
|
14
15
|
script/generate
|
@@ -20,4 +21,4 @@ spec/spec_helper.rb
|
|
20
21
|
tasks/deployment.rake
|
21
22
|
tasks/environment.rake
|
22
23
|
tasks/rspec.rake
|
23
|
-
tasks/website.rake
|
24
|
+
tasks/website.rake
|
data/lib/pmsrb.rb
CHANGED
@@ -23,7 +23,13 @@ module PMS
|
|
23
23
|
|
24
24
|
class Vendor
|
25
25
|
def run(&block)
|
26
|
+
@cleanup_tasks = []
|
26
27
|
instance_eval(&block)
|
28
|
+
@cleanup_tasks.each {|x| x.call}
|
29
|
+
end
|
30
|
+
|
31
|
+
def cleanup(&block)
|
32
|
+
@cleanup_tasks << block
|
27
33
|
end
|
28
34
|
|
29
35
|
def download(url, storage_dir=nil)
|
@@ -67,8 +73,41 @@ module PMS
|
|
67
73
|
|
68
74
|
def extract
|
69
75
|
puts "extracting #{@current_file}"
|
70
|
-
|
71
|
-
|
76
|
+
file = @current_file.split("/").pop
|
77
|
+
case(file)
|
78
|
+
when /tar.gz$/, /tgz$/: extract_tgz
|
79
|
+
when /zip$/: extract_zip
|
80
|
+
when /dmg$/: extract_dmg
|
81
|
+
when /tar.bz2$/, /tbz2$/: extract_tbz2
|
82
|
+
else raise Exception.new("Unknown file type '#{extension}' for '#{@current_file}' in extraction")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def extract_tbz2
|
87
|
+
pwd = File.expand_path(FileUtils.pwd)
|
88
|
+
FileUtils.cd @working_directory
|
89
|
+
|
90
|
+
`tar xvjpf #{@current_file[(@working_directory.length+1)..-1]}`
|
91
|
+
|
92
|
+
FileUtils.cd pwd
|
93
|
+
end
|
94
|
+
|
95
|
+
def extract_dmg
|
96
|
+
fname=@current_file
|
97
|
+
`hdiutil attach '#{fname}' -mountpoint '#{@working_directory}/dmg_tmp_mount'`
|
98
|
+
|
99
|
+
Dir["#{@working_directory}/dmg_tmp_mount/**/*"].each do |file|
|
100
|
+
next if File.symlink?(file)
|
101
|
+
next if File.directory?(file)
|
102
|
+
dest_path = file.sub("/dmg_tmp_mount","").split("/")[0...-1].join("/")
|
103
|
+
FileUtils.mkdir_p(dest_path)
|
104
|
+
FileUtils.cp(file, dest_path)
|
105
|
+
end
|
106
|
+
|
107
|
+
|
108
|
+
cleanup do
|
109
|
+
`hdiutil detach '#{@working_directory}/dmg_tmp_mount' -force`
|
110
|
+
end
|
72
111
|
end
|
73
112
|
|
74
113
|
def extract_tgz
|
@@ -118,16 +157,23 @@ module PMS
|
|
118
157
|
def cp(pattern, newdir)
|
119
158
|
newdir = "#{@working_directory}/#{newdir}"
|
120
159
|
files = Dir["#{@working_directory}/#{pattern}"]
|
160
|
+
puts "'#{@working_directory}/#{pattern}' => '#{newdir}'"
|
121
161
|
|
122
162
|
if files.length == 1
|
123
163
|
file = files[0]
|
124
164
|
FileUtils.mkdir_p File.dirname(newdir)
|
125
|
-
|
165
|
+
unless FileTest.directory?(file) || File.symlink?(file)
|
166
|
+
puts "'#{file}' => '#{newdir}'"
|
167
|
+
FileUtils.cp_r file, newdir
|
168
|
+
end
|
126
169
|
else
|
127
170
|
files.each do |file|
|
128
171
|
dest = newdir + (File.dirname(file))[@working_directory.length..-1]
|
129
172
|
FileUtils.mkdir_p dest
|
130
|
-
|
173
|
+
unless FileTest.directory?(file) || File.symlink?(file)
|
174
|
+
puts "'#{file}' => '#{dest}'"
|
175
|
+
FileUtils.cp file, dest
|
176
|
+
end
|
131
177
|
end
|
132
178
|
end
|
133
179
|
end
|
@@ -171,13 +217,11 @@ module PMS
|
|
171
217
|
|
172
218
|
def archive(filelist, archive)
|
173
219
|
filelist = expand_filelist filelist
|
174
|
-
puts "archiving #{filelist}"
|
175
|
-
|
176
|
-
archive_tgz filelist, archive
|
177
|
-
|
178
|
-
|
179
|
-
else
|
180
|
-
raise Exception.new("archive type '#{archive}' is not supported")
|
220
|
+
puts "archiving #{filelist.inspect}"
|
221
|
+
case(archive)
|
222
|
+
when /\.tgz$/, /\.tar\.gz$/: archive_tgz filelist, archive
|
223
|
+
when /\.zip$/: archive_zip filelist, archive
|
224
|
+
else raise Exception.new("archive type '#{archive}' is not supported")
|
181
225
|
end
|
182
226
|
end
|
183
227
|
|
@@ -0,0 +1,155 @@
|
|
1
|
+
include ObjectSpace
|
2
|
+
|
3
|
+
MEMORY_PROFILE_BAD_SIZE_METHOD = {FileTest => true, File => true, File::Stat => true}
|
4
|
+
|
5
|
+
class Object
|
6
|
+
def memory_profile_size_of_object(seen={})
|
7
|
+
return 0 if seen.has_key? object_id
|
8
|
+
seen[object_id] = true
|
9
|
+
count = 1
|
10
|
+
if kind_of? Hash
|
11
|
+
each_pair do |key,value|
|
12
|
+
count += key.memory_profile_size_of_object(seen)
|
13
|
+
count += value.memory_profile_size_of_object(seen)
|
14
|
+
end
|
15
|
+
elsif kind_of? Array
|
16
|
+
count += size
|
17
|
+
each do |element|
|
18
|
+
count += element.memory_profile_size_of_object(seen)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
count += instance_variables.size
|
23
|
+
instance_variables.each do |var|
|
24
|
+
count += instance_variable_get(var.to_sym).memory_profile_size_of_object(seen)
|
25
|
+
end
|
26
|
+
|
27
|
+
count
|
28
|
+
end
|
29
|
+
|
30
|
+
def memory_profile_inspect(seen={},level=0)
|
31
|
+
return object_id.to_s if seen.has_key? object_id
|
32
|
+
seen[object_id] = true
|
33
|
+
result = ' '*level
|
34
|
+
if kind_of? Hash
|
35
|
+
result += "{\n" + ' '*level
|
36
|
+
each_pair do |key,value|
|
37
|
+
result += key.memory_profile_inspect(seen,level+1) + "=>\n"
|
38
|
+
result += value.memory_profile_inspect(seen,level+2) + ",\n" + ' '*level
|
39
|
+
end
|
40
|
+
result += "}\n" + ' '*level
|
41
|
+
elsif kind_of? Array
|
42
|
+
result += "[\n" + ' '*level
|
43
|
+
each do |element|
|
44
|
+
result += element.memory_profile_inspect(seen,level+1) + ",\n" + ' '*level
|
45
|
+
end
|
46
|
+
result += "]\n" + ' '*level
|
47
|
+
elsif kind_of? String
|
48
|
+
result += self
|
49
|
+
elsif kind_of? Numeric
|
50
|
+
result += self.to_s
|
51
|
+
elsif kind_of? Class
|
52
|
+
result += to_s
|
53
|
+
else
|
54
|
+
result += "---"+self.class.to_s + "---\n" + ' '*level
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
instance_variables.each do |var|
|
59
|
+
result += var + "=" + instance_variable_get(var.to_sym).memory_profile_inspect(seen,level+1) + "\n" + ' '*level
|
60
|
+
end
|
61
|
+
|
62
|
+
result
|
63
|
+
end
|
64
|
+
|
65
|
+
end
|
66
|
+
|
67
|
+
module MemoryProfile
|
68
|
+
LOG_FILE = "/tmp/memory_profile.log"
|
69
|
+
|
70
|
+
def MemoryProfile::report
|
71
|
+
Dir.chdir "/tmp"
|
72
|
+
ObjectSpace::garbage_collect
|
73
|
+
sleep 10 # Give the GC thread a chance
|
74
|
+
all = []
|
75
|
+
ObjectSpace.each_object do |obj|
|
76
|
+
next if obj.object_id == all.object_id
|
77
|
+
|
78
|
+
all << obj
|
79
|
+
end
|
80
|
+
|
81
|
+
tally = Hash.new(0)
|
82
|
+
max_obj = nil
|
83
|
+
max_count = 0
|
84
|
+
all.each do |obj|
|
85
|
+
count = obj.memory_profile_size_of_object
|
86
|
+
if max_count < count
|
87
|
+
max_obj = obj
|
88
|
+
max_count = count
|
89
|
+
end
|
90
|
+
|
91
|
+
tally[obj.class]+=count
|
92
|
+
end
|
93
|
+
|
94
|
+
open( LOG_FILE, 'a') do |outf|
|
95
|
+
outf.puts '+'*70
|
96
|
+
tally.keys.sort{|a,b|
|
97
|
+
if tally[a] == tally[b]
|
98
|
+
a.to_s <=> b.to_s
|
99
|
+
else
|
100
|
+
-1*(tally[a]<=>tally[b])
|
101
|
+
end
|
102
|
+
}.each do |klass|
|
103
|
+
outf.puts "#{klass}\t#{tally[klass]}"
|
104
|
+
end
|
105
|
+
|
106
|
+
outf.puts '-'*70
|
107
|
+
outf.puts "Max obj was #{max_obj.class} at #{max_count}"
|
108
|
+
outf.puts "Maximum object is..."
|
109
|
+
outf.puts max_obj.memory_profile_inspect
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def MemoryProfile::simple_count
|
114
|
+
Dir.chdir "/tmp"
|
115
|
+
ObjectSpace::garbage_collect
|
116
|
+
sleep 10 # Give the GC thread a chance
|
117
|
+
|
118
|
+
tally = Hash.new(0)
|
119
|
+
ObjectSpace.each_object do |obj|
|
120
|
+
next if obj.object_id == tally.object_id
|
121
|
+
tally[obj.class]+=1
|
122
|
+
end
|
123
|
+
|
124
|
+
open( LOG_FILE, 'a') do |outf|
|
125
|
+
outf.puts '='*70
|
126
|
+
outf.puts "MemoryProfile report for #{$0}"
|
127
|
+
outf.puts `cat /proc/#{Process.pid}/status`
|
128
|
+
|
129
|
+
tally.keys.sort{|a,b|
|
130
|
+
if tally[a] == tally[b]
|
131
|
+
a.to_s <=> b.to_s
|
132
|
+
else
|
133
|
+
-1*(tally[a]<=>tally[b])
|
134
|
+
end
|
135
|
+
}.each do |klass|
|
136
|
+
outf.puts "#{klass}\t#{tally[klass]}"
|
137
|
+
end
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
if $0 == __FILE__ then
|
143
|
+
File.unlink MemoryProfile::LOG_FILE if FileTest.exist? MemoryProfile::LOG_FILE
|
144
|
+
|
145
|
+
at_exit{ system("cat #{MemoryProfile::LOG_FILE}")}
|
146
|
+
end
|
147
|
+
|
148
|
+
at_exit{
|
149
|
+
MemoryProfile::simple_count
|
150
|
+
MemoryProfile::report
|
151
|
+
}
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
|
data/lib/pmsrb/platform.rb
CHANGED
@@ -4,6 +4,18 @@
|
|
4
4
|
#
|
5
5
|
# Platform.new("mswin").short_name => windows, since we are creating an instance.
|
6
6
|
class Platform
|
7
|
+
def self.mac
|
8
|
+
yield if(mac?)
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.windows
|
12
|
+
yield if(windows?)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.linux
|
16
|
+
yield if(linux?)
|
17
|
+
end
|
18
|
+
|
7
19
|
def self.mac?
|
8
20
|
PLATFORM =~ /darwin/
|
9
21
|
end
|
data/lib/pmsrb/version.rb
CHANGED
data/spec/pmsrb_spec.rb
CHANGED
@@ -272,4 +272,30 @@ describe "The pmsrb dsl" do
|
|
272
272
|
creds.pass.should == "pass"
|
273
273
|
FileUtils.rm_r(ENV["HOME"]+"/.test_pmsrb")
|
274
274
|
end
|
275
|
+
|
276
|
+
it "extracts DMG files" do
|
277
|
+
Platform.mac do
|
278
|
+
vendor do
|
279
|
+
working_directory working_dir
|
280
|
+
download "http://www.vojousoftware.com/download/attime.dmg"
|
281
|
+
extract
|
282
|
+
File.exists?(working_dir+"/dmg_tmp_mount").should == true
|
283
|
+
File.exists?(working_dir+"/ReadMe.rtf").should == true
|
284
|
+
end
|
285
|
+
File.exists?(working_dir+"/dmg_tmp_mount").should == false
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
it "fails extracting unknown file types" do
|
290
|
+
lambda {
|
291
|
+
vendor do
|
292
|
+
@current_file = "random.bad.extension"
|
293
|
+
extract
|
294
|
+
end
|
295
|
+
}.should raise_error
|
296
|
+
end
|
297
|
+
|
298
|
+
it "can extract .tar.bz2" do
|
299
|
+
Vendor.new.methods.include?("extract_tbz2").should == true
|
300
|
+
end
|
275
301
|
end
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: pmsrb
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.
|
7
|
-
date: 2008-
|
6
|
+
version: 0.2.0
|
7
|
+
date: 2008-05-26 00:00:00 -06:00
|
8
8
|
summary: pmsrb is a binary (p)ackage (m)anagement (s)ystem meant for gracefully handling the differences in binary distribution on different platforms.
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -42,6 +42,7 @@ files:
|
|
42
42
|
- lib/pmsrb/platform.rb
|
43
43
|
- lib/pmsrb/progressbar.rb
|
44
44
|
- lib/pmsrb/version.rb
|
45
|
+
- lib/pmsrb/memory_profile.rb
|
45
46
|
- log/debug.log
|
46
47
|
- script/destroy
|
47
48
|
- script/generate
|