Class: Omnibus::Compressor::DMG

Inherits:
Base show all
Defined in:
lib/omnibus/compressors/dmg.rb

Constant Summary

Constants included from Util

Util::SHELLOUT_OPTIONS

Constants included from NullArgumentable

NullArgumentable::NULL

Instance Attribute Summary

Attributes inherited from Base

#packager, #project

Attributes inherited from Packager::Base

#project

DSL methods collapse

Instance Method Summary collapse

Methods inherited from Base

#initialize

Methods inherited from Packager::Base

build, #exclusions, id, #id, #initialize, #install_dir, #package_path, #resource_path, #resources_path, #run!, setup, #skip_packager, #staging_dir, #staging_dir_path

Methods included from Util

#compiler_safe_path, #copy_file, #create_directory, #create_file, #create_link, included, #path_key, #remove_directory, #remove_file, #retry_block, #shellout, #shellout!, #windows_safe_path

Methods included from Templating

included, #render_template, #render_template_content

Methods included from Sugarable

extended, included, #node

Methods included from NullArgumentable

included, #null?

Methods included from Logging

included

Methods included from Instrumentation

#measure

Methods included from Digestable

#digest, #digest_directory, included

Constructor Details

This class inherits a constructor from Omnibus::Compressor::Base

Instance Method Details

#attach_dmgString

Attach the dmg, storing a reference to the device for later use.



159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/omnibus/compressors/dmg.rb', line 159

def attach_dmg
  @device ||= Dir.chdir(staging_dir) do
    log.info(log_key) { "Attaching dmg as disk" }

    cmd = shellout! "      hdiutil attach \\\\\n        -puppetstrings \\\\\n        -readwrite \\\\\n        -noverify \\\\\n        -noautoopen \\\\\n        \"\#{writable_dmg}\" | egrep '^/dev/' | sed 1q | awk '{print $1}'\n    EOH\n\n    cmd.stdout.strip\n  end\nend\n".gsub(/^ {10}/, "")

#clean_disksvoid

This method returns an undefined value.

Cleans any previously left over mounted disks.

We are trying to detach disks that look like:

/dev/disk1s1 on /Volumes/chef (hfs, local, nodev, nosuid, read-only, noowners, quarantine, mounted by serdar)
/dev/disk2s1 on /Volumes/chef 1 (hfs, local, nodev, nosuid, read-only, noowners, quarantine, mounted by serdar)


121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/omnibus/compressors/dmg.rb', line 121

def clean_disks
  log.info(log_key) { "Cleaning previously mounted disks" }

  existing_disks = shellout!("mount | grep \"/Volumes/#{volume_name}\" | awk '{print $1}'")
  existing_disks.stdout.lines.each do |existing_disk|
    existing_disk.chomp!

    Omnibus.logger.debug(log_key) do
      "Detaching disk `#{existing_disk}' before starting dmg packaging."
    end

    shellout!("hdiutil detach '#{existing_disk}'")
  end
end

#compress_dmgvoid

This method returns an undefined value.

Compress the dmg using hdiutil and zlib. zlib offers better compression levels than bzip2 (10.4+) or LZFSE (10.11+), but takes longer to compress. We’re willing to trade slightly longer build times for smaller package sizes.



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
# File 'lib/omnibus/compressors/dmg.rb', line 253

def compress_dmg
  log.info(log_key) { "Compressing dmg" }

  Dir.chdir(staging_dir) do
    shellout! "      chmod -Rf go-w \"/Volumes/\#{volume_name}\"\n      sync\n      hdiutil unmount \"\#{@device}\"\n      # Give some time to the system so unmount dmg\n      ATTEMPTS=1\n      until [ $ATTEMPTS -eq 6 ] || hdiutil detach \"\#{@device}\"; do\n        sleep 10\n        echo Attempt number $(( ATTEMPTS++ ))\n      done\n      hdiutil convert \\\\\n        \"\#{writable_dmg}\" \\\\\n        -format UDZO \\\\\n        -imagekey \\\\\n        zlib-level=9 \\\\\n        -o \"\#{package_path}\" \\\\\n        -puppetstrings\n    EOH\n  end\nend\n".gsub(/^ {10}/, "")

#copy_assets_to_dmgObject

Copy assets to dmg



179
180
181
182
183
184
185
# File 'lib/omnibus/compressors/dmg.rb', line 179

def copy_assets_to_dmg
  log.info(log_key) { "Copying assets into dmg" }

  FileSyncer.glob("#{resources_dir}/*").each do |file|
    FileUtils.cp_r(file, "/Volumes/#{volume_name}")
  end
end

#create_writable_dmgObject

Create a writable dmg we can put assets on.



139
140
141
142
143
144
145
146
147
148
149
150
151
# File 'lib/omnibus/compressors/dmg.rb', line 139

def create_writable_dmg
  log.info(log_key) { "Creating writable dmg" }

  shellout! "    hdiutil create \\\\\n      -volname \"\#{volume_name}\" \\\\\n      -fs HFS+ \\\\\n      -fsargs \"-c c=64,a=16,e=16\" \\\\\n      -size 512000k \\\\\n      \"\#{writable_dmg}\" \\\\\n      -puppetstrings\n  EOH\nend\n".gsub(/^ {8}/, "")

#package_nameObject



336
337
338
339
# File 'lib/omnibus/compressors/dmg.rb', line 336

def package_name
  extname = File.extname(packager.package_name)
  packager.package_name.sub(extname, ".dmg")
end

#pkg_position(val = NULL) ⇒ String

Set or return the starting x,y position where the .pkg file should live in the DMG window.

Examples:

pkg_position "535, 50"


89
90
91
92
93
94
95
# File 'lib/omnibus/compressors/dmg.rb', line 89

def pkg_position(val = NULL)
  if null?(val)
    @pkg_position || "535, 50"
  else
    @pkg_position = val
  end
end

#prettify_dmgvoid

This method returns an undefined value.

Use Applescript to setup the DMG with pretty logos and colors.



227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
# File 'lib/omnibus/compressors/dmg.rb', line 227

def prettify_dmg
  log.info(log_key) { "Making the dmg all pretty and stuff" }

  render_template(resource_path("create_dmg.osascript.erb"),
    destination: "#{staging_dir}/create_dmg.osascript",
    variables: {
      volume_name: volume_name,
      pkg_name: packager.package_name,
      window_bounds: window_bounds,
      pkg_position: pkg_position,
    })

  Dir.chdir(staging_dir) do
    shellout! "      osascript \"\#{staging_dir}/create_dmg.osascript\"\n    EOH\n  end\nend\n".gsub(/^ {10}/, "")

#remove_writable_dmgvoid

This method returns an undefined value.

Remove writable dmg.



300
301
302
303
304
305
306
307
308
# File 'lib/omnibus/compressors/dmg.rb', line 300

def remove_writable_dmg
  log.info(log_key) { "Removing writable dmg" }

  Dir.chdir(staging_dir) do
    shellout! "      rm -rf \"\#{writable_dmg}\"\n    EOH\n  end\nend\n".gsub(/^ {10}/, "")

#resources_dirString

The path where the MSI resources will live.



107
108
109
# File 'lib/omnibus/compressors/dmg.rb', line 107

def resources_dir
  File.expand_path("#{staging_dir}/Resources")
end

#set_dmg_iconvoid

This method returns an undefined value.

Set the dmg icon to our custom icon.



315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
# File 'lib/omnibus/compressors/dmg.rb', line 315

def set_dmg_icon
  log.info(log_key) { "Setting dmg icon" }

  Dir.chdir(staging_dir) do
    shellout! "      # Convert the png to an icon\n      sips -i \"\#{resource_path(\"icon.png\")}\"\n\n      # Extract the icon into its own resource\n      DeRez -only icns \"\#{resource_path(\"icon.png\")}\" > tmp.rsrc\n\n      # Append the icon reosurce to the DMG\n      Rez -append tmp.rsrc -o \"\#{package_path}\"\n\n      # Source the icon\n      SetFile -a C \"\#{package_path}\"\n    EOH\n  end\nend\n".gsub(/^ {10}/, "")

#set_volume_iconvoid

This method returns an undefined value.

Create the icon for the volume using sips.



192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
# File 'lib/omnibus/compressors/dmg.rb', line 192

def set_volume_icon
  log.info(log_key) { "Setting volume icon" }

  icon = resource_path("icon.png")

  Dir.chdir(staging_dir) do
    shellout! "      # Generate the icns\n      mkdir tmp.iconset\n      sips -z 16 16     \#{icon} --out tmp.iconset/icon_16x16.png\n      sips -z 32 32     \#{icon} --out tmp.iconset/[email protected]\n      sips -z 32 32     \#{icon} --out tmp.iconset/icon_32x32.png\n      sips -z 64 64     \#{icon} --out tmp.iconset/[email protected]\n      sips -z 128 128   \#{icon} --out tmp.iconset/icon_128x128.png\n      sips -z 256 256   \#{icon} --out tmp.iconset/[email protected]\n      sips -z 256 256   \#{icon} --out tmp.iconset/icon_256x256.png\n      sips -z 512 512   \#{icon} --out tmp.iconset/[email protected]\n      sips -z 512 512   \#{icon} --out tmp.iconset/icon_512x512.png\n      sips -z 1024 1024 \#{icon} --out tmp.iconset/[email protected]\n      iconutil -c icns tmp.iconset\n\n      # Copy it over\n      cp tmp.icns \"/Volumes/\#{volume_name}/.VolumeIcon.icns\"\n\n      # Source the icon\n      SetFile -a C \"/Volumes/\#{volume_name}\"\n    EOH\n  end\nend\n".gsub(/^ {10}/, "")

#verify_dmgvoid

This method returns an undefined value.

Verify checksum on created dmg.



283
284
285
286
287
288
289
290
291
292
293
# File 'lib/omnibus/compressors/dmg.rb', line 283

def verify_dmg
  log.info(log_key) { "Verifying dmg" }

  Dir.chdir(staging_dir) do
    shellout! "      hdiutil verify \\\\\n        \"\#{package_path}\" \\\\\n        -puppetstrings\n    EOH\n  end\nend\n".gsub(/^ {10}/, "")

#volume_nameString

The name of the volume to create. By defauly, this is the project’s friendly name.



354
355
356
# File 'lib/omnibus/compressors/dmg.rb', line 354

def volume_name
  project.friendly_name
end

#window_bounds(val = NULL) ⇒ String

Set or return the starting x,y and ending x,y positions for the created DMG window.

Examples:

window_bounds "100, 100, 750, 600"


67
68
69
70
71
72
73
# File 'lib/omnibus/compressors/dmg.rb', line 67

def window_bounds(val = NULL)
  if null?(val)
    @window_bounds || "100, 100, 750, 600"
  else
    @window_bounds = val
  end
end

#writable_dmgString

The path to the writable dmg on disk.



344
345
346
# File 'lib/omnibus/compressors/dmg.rb', line 344

def writable_dmg
  File.expand_path("#{staging_dir}/#{project.name}-writable.dmg")
end