Module: ChocTop::Dmg

Defined in:
lib/choctop/dmg.rb

Instance Method Summary collapse

Instance Method Details

#add_eulaObject



174
175
176
177
178
179
180
181
# File 'lib/choctop/dmg.rb', line 174

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

#background_boundsObject



64
65
66
67
68
# File 'lib/choctop/dmg.rb', line 64

def background_bounds
  return [400, 300] unless background_file
  background = OSX::NSImage.alloc.initByReferencingFile(background_file).size.to_a
  [background.first, background.last + statusbar_height]
end

#codesignObject



3
4
5
6
# File 'lib/choctop/dmg.rb', line 3

def codesign
  sh "codesign -v -s 'Zetetic LLC' '#{src_folder}/#{target}'"
  sh "codesign -dv '#{src_folder}/#{target}'"
end

#configure_applications_iconObject



140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
# File 'lib/choctop/dmg.rb', line 140

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.setIcon_forFile_options(image, applications_path, nil)
  end
end

#configure_dmg_windowObject



79
80
81
82
83
84
85
86
87
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
# File 'lib/choctop/dmg.rb', line 79

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}
           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
  run_applescript(script)
  sh "SetFile -a V '#{target_background}'" if background_file
end

#configure_volume_iconObject



72
73
74
75
76
77
# File 'lib/choctop/dmg.rb', line 72

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_readonlyObject



168
169
170
171
172
# File 'lib/choctop/dmg.rb', line 168

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_filesObject



24
25
26
27
28
29
30
# File 'lib/choctop/dmg.rb', line 24

def copy_files
  FileUtils.rm_rf(src_folder)
  FileUtils.mkdir_p(src_folder)
  files.each do |path, options|
    FileUtils.cp_r(path, src_folder)
  end
end

#detach_dmgObject



157
158
159
160
161
162
163
164
165
166
# File 'lib/choctop/dmg.rb', line 157

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

Returns:

  • (Boolean)


135
136
137
138
# File 'lib/choctop/dmg.rb', line 135

def include_applications_icon?
  puts "target: #{target.inspect}"
  target =~ /.app$/
end

#make_dmgObject



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/choctop/dmg.rb', line 32

def make_dmg
  prepare_files
  copy_files
  codesign if codesign_identity
  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 '#{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_filesObject



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/choctop/dmg.rb', line 8

def prepare_files
  self.files = files.inject({}) do |files, file|
    path_or_helper, options = file
    path = case path_or_helper
      when Symbol
        send path_or_helper
      when Proc
        path_or_helper.call
      else
        path_or_helper
    end
    files[path] = options if path && File.exists?(path) && File.basename(path) != '.'
    files
  end
end

#run_applescript(applescript, tmp_file = "choctop-script") ⇒ Object



183
184
185
186
187
188
189
190
191
192
193
194
195
# File 'lib/choctop/dmg.rb', line 183

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_filesObject



118
119
120
121
122
123
124
125
# File 'lib/choctop/dmg.rb', line 118

def set_position_of_files
  files.map do |file_options|
    path, options = file_options
    target        = File.basename(path)
    position      = options[:position].join(", ")
    %Q{set position of item "#{target}" to {#{position}}}
  end.join("\n")
end

#set_position_of_shortcutsObject



127
128
129
130
131
132
133
# File 'lib/choctop/dmg.rb', line 127

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_heightObject



70
# File 'lib/choctop/dmg.rb', line 70

def statusbar_height; 20; end

#volume_backgroundObject



51
52
53
# File 'lib/choctop/dmg.rb', line 51

def volume_background
  ".background/background#{File.extname(background_file)}"
end

#window_boundsObject



59
60
61
62
# File 'lib/choctop/dmg.rb', line 59

def window_bounds
  window_position + 
  window_position.zip(background_bounds).map { |w, b| w + b }
end

#window_positionObject



55
56
57
# File 'lib/choctop/dmg.rb', line 55

def window_position
  [50, 100]
end