Module: ChocTop::Dmg
- Included in:
- Configuration
- Defined in:
- lib/choctop/dmg.rb
Instance Method Summary collapse
- #add_eula ⇒ Object
- #add_file_to_dmg_src_folder(path, options) ⇒ Object
- #add_link_to_dmg_src_folder(path, options) ⇒ Object
- #background_bounds ⇒ Object
- #configure_applications_icon ⇒ Object
- #configure_dmg_window ⇒ Object
- #configure_volume_icon ⇒ Object
- #convert_dmg_readonly ⇒ Object
-
#copy_files ⇒ Object
Two-phase copy: first to a tmp folder (to prevent recursion); then tmp folder to
dmg_src_folder
. - #detach_dmg ⇒ Object
- #include_applications_icon? ⇒ Boolean
- #make_dmg ⇒ Object
- #prepare_files ⇒ Object
- #run_applescript(applescript, tmp_file = "choctop-script") ⇒ Object
- #set_position_of_files ⇒ Object
- #set_position_of_shortcuts ⇒ Object
- #statusbar_height ⇒ Object
- #tmp_dmg_src_folder ⇒ Object
- #volume_background ⇒ Object
- #window_bounds ⇒ Object
- #window_position ⇒ Object
Instance Method Details
#add_eula ⇒ Object
185 186 187 188 189 190 191 192 |
# File 'lib/choctop/dmg.rb', line 185 def add_eula # TODO support EULA # hdiutil unflatten $@ # /Developer/Tools/DeRez -useDF SLAResources.rsrc > build/temp/sla.r # /Developer/Tools/Rez -a build/temp/sla.r -o $@ # hdiutil flatten $@ end |
#add_file_to_dmg_src_folder(path, options) ⇒ Object
194 195 196 197 198 199 200 201 |
# File 'lib/choctop/dmg.rb', line 194 def add_file_to_dmg_src_folder(path, ) target = File.join(tmp_dmg_src_folder, [:name]) sh ::Escape.shell_command(['cp', '-r', path, target]) if [:exclude] exclude_list = [:exclude].is_a?(Array) ? [:exclude] : [[:exclude].to_s] exclude_list.each { |exclude| sh ::Escape.shell_command(['rm', '-rf', File.join(target, exclude)]) } end end |
#add_link_to_dmg_src_folder(path, options) ⇒ Object
203 204 205 206 207 208 209 210 |
# File 'lib/choctop/dmg.rb', line 203 def add_link_to_dmg_src_folder(path, ) plist_name = [:name].gsub(/\.webloc$/, '') plist_target = File.join(tmp_dmg_src_folder, plist_name) target = File.join(tmp_dmg_src_folder, [:name]) sh ::Escape.shell_command(['defaults', 'write', plist_target, 'URL', [:url]]) sh ::Escape.shell_command(['plutil', '-convert', 'xml1', '-o', target, "#{plist_target}.plist"]) sh ::Escape.shell_command(['rm', "#{plist_target}.plist"]) end |
#background_bounds ⇒ Object
73 74 75 76 77 |
# File 'lib/choctop/dmg.rb', line 73 def background_bounds return [400, 300] unless background_file background = OSX::NSImage.alloc.initByReferencingFile(background_file).size.to_a [background.first, background.last + ] end |
#configure_applications_icon ⇒ Object
151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 |
# File 'lib/choctop/dmg.rb', line 151 def configure_applications_icon run_applescript <<-SCRIPT.gsub(/^ /, ''), "apps_icon_script" tell application "Finder" set applications_folder to displayed name of (path to applications folder) -- i18n set dest to disk "#{name}" set src to folder applications_folder of startup disk make new alias at dest to src end tell SCRIPT if applications_icon applications_path = "#{volume_path}/Applications" OSX::NSApplicationLoad() image = OSX::NSImage.alloc.initWithContentsOfFile(applications_icon) OSX::NSWorkspace.sharedWorkspace.(image, applications_path, nil) end end |
#configure_dmg_window ⇒ Object
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/choctop/dmg.rb', line 88 def configure_dmg_window if background_file target_background = "#{volume_path}/#{volume_background}" FileUtils.mkdir_p(File.dirname(target_background)) FileUtils.cp(background_file, target_background) end script = <<-SCRIPT.gsub(/^ /, '') tell application "Finder" set applications_folder to displayed name of (path to applications folder) -- i18n set mountpoint to POSIX file ("#{volume_path}" as string) as alias tell folder mountpoint open tell container window set toolbar visible to false set statusbar visible to false -- doesn't do anything at DMG open time set current view to icon view delay 1 -- Sync set the bounds to {#{window_bounds.join(", ")}} end tell delay 1 -- Sync set icon size of the icon view options of container window to #{icon_size} set text size of the icon view options of container window to #{icon_text_size} set arrangement of the icon view options of container window to not arranged #{set_position_of_files} #{set_position_of_shortcuts} close open set the bounds of the container window to {#{window_bounds.join(", ")}} set background picture of the icon view options of container window to file "#{volume_background.gsub(/\//,':')}" update without registering applications delay 5 -- Sync close end tell -- Sync delay 5 end tell SCRIPT puts "script: #{script}" run_applescript(script) sh "SetFile -a V '#{target_background}'" if background_file end |
#configure_volume_icon ⇒ Object
81 82 83 84 85 86 |
# File 'lib/choctop/dmg.rb', line 81 def configure_volume_icon if volume_icon FileUtils.cp(volume_icon, "#{volume_path}/.VolumeIcon.icns") sh "SetFile -a C '#{volume_path}'" end end |
#convert_dmg_readonly ⇒ Object
179 180 181 182 183 |
# File 'lib/choctop/dmg.rb', line 179 def convert_dmg_readonly tmp_path = "/tmp/rw.dmg" FileUtils.mv(pkg, tmp_path) sh "hdiutil convert '#{tmp_path}' -format UDZO -imagekey zlib-level=9 -o '#{pkg}'" end |
#copy_files ⇒ Object
Two-phase copy: first to a tmp folder (to prevent recursion); then tmp folder to dmg_src_folder
28 29 30 31 32 33 34 35 36 37 38 39 40 |
# File 'lib/choctop/dmg.rb', line 28 def copy_files FileUtils.mkdir_p(tmp_dmg_src_folder) files.each do |path, | if [:link] add_link_to_dmg_src_folder(path, ) else add_file_to_dmg_src_folder(path, ) end end FileUtils.rm_r(dmg_src_folder) if File.exists? dmg_src_folder FileUtils.mkdir_p(dmg_src_folder) Dir["#{tmp_dmg_src_folder}/*"].each { |f| FileUtils.cp_r(f, dmg_src_folder) } end |
#detach_dmg ⇒ Object
168 169 170 171 172 173 174 175 176 177 |
# File 'lib/choctop/dmg.rb', line 168 def detach_dmg mounted_paths = `hdiutil info | grep '#{volume_path}' | grep "Apple_HFS"`.split("\n").map { |e| e.split(" ").first } mounted_paths.each do |path| begin sh "hdiutil detach '#{path}' -quiet -force" rescue StandardError => e p e end end end |
#include_applications_icon? ⇒ Boolean
147 148 149 |
# File 'lib/choctop/dmg.rb', line 147 def include_applications_icon? target =~ /.app$/ end |
#make_dmg ⇒ Object
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 |
# File 'lib/choctop/dmg.rb', line 42 def make_dmg prepare_files copy_files FileUtils.mkdir_p build_path FileUtils.mkdir_p mountpoint # TODO can we remove random mountpoints? FileUtils.rm_f(pkg) # make sure destination pkg doesn't already exist, or hdiutil will barf sh "hdiutil create -format UDRW -quiet -volname '#{name}' -srcfolder '#{dmg_src_folder}' '#{pkg}'" sh "hdiutil attach '#{pkg}' -mountpoint '#{volume_path}' -noautoopen -quiet" sh "bless --folder '#{volume_path}' --openfolder '#{volume_path}'" sh "sleep 1" puts "volume_icon: #{volume_icon.inspect}" puts "include_applications_icon?: #{include_applications_icon?.inspect}" configure_volume_icon configure_applications_icon if include_applications_icon? configure_dmg_window end |
#prepare_files ⇒ Object
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/choctop/dmg.rb', line 3 def prepare_files self.files = files.inject({}) do |files, file| path_or_helper, = file path = case path_or_helper when Symbol send path_or_helper when Proc path_or_helper.call else path_or_helper end if path && File.exists?(path) files[path] = [:name] ||= File.basename(path) end if path =~ %r{\.webloc$} files[path] = [:name] ||= File.basename(path) [:link] = true end files end end |
#run_applescript(applescript, tmp_file = "choctop-script") ⇒ Object
212 213 214 215 216 217 218 219 220 221 222 223 224 |
# File 'lib/choctop/dmg.rb', line 212 def run_applescript(applescript, tmp_file = "choctop-script") File.open(scriptfile = "/tmp/#{tmp_file}", "w") do |f| f << applescript end sh("osascript #{scriptfile}") do |ok, res| if ! ok p res puts volume_path exit 1 end end applescript end |
#set_position_of_files ⇒ Object
130 131 132 133 134 135 136 137 |
# File 'lib/choctop/dmg.rb', line 130 def set_position_of_files files.map do || path, = target = [:name] position = [:position].join(", ") %Q{set position of item "#{target}" to {#{position}}} end.join("\n") end |
#set_position_of_shortcuts ⇒ Object
139 140 141 142 143 144 145 |
# File 'lib/choctop/dmg.rb', line 139 def set_position_of_shortcuts if include_applications_icon? %Q{set position of item applications_folder to {#{applications_icon_position.join(", ")}}} else "" end end |
#statusbar_height ⇒ Object
79 |
# File 'lib/choctop/dmg.rb', line 79 def ; 20; end |
#tmp_dmg_src_folder ⇒ Object
226 227 228 229 230 231 |
# File 'lib/choctop/dmg.rb', line 226 def tmp_dmg_src_folder @tmp_dmg_src_folder ||= begin require 'tmpdir' File.join(Dir.tmpdir, Time.now.to_i.to_s) # probably unique folder end end |
#volume_background ⇒ Object
60 61 62 |
# File 'lib/choctop/dmg.rb', line 60 def volume_background ".background/background#{File.extname(background_file)}" end |
#window_bounds ⇒ Object
68 69 70 71 |
# File 'lib/choctop/dmg.rb', line 68 def window_bounds window_position + window_position.zip(background_bounds).map { |w, b| w + b } end |
#window_position ⇒ Object
64 65 66 |
# File 'lib/choctop/dmg.rb', line 64 def window_position [50, 100] end |