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.

Returns:

  • (String)

    the name of the attached device



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! <<-EOH.gsub(/^ {10}/, "")
      hdiutil attach \\
        -puppetstrings \\
        -readwrite \\
        -noverify \\
        -noautoopen \\
        "#{writable_dmg}" | egrep '^/dev/' | sed 1q | awk '{print $1}'
    EOH

    cmd.stdout.strip
  end
end

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

#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! <<-EOH.gsub(/^ {8}/, "")
    hdiutil create \\
      -volname "#{volume_name}" \\
      -fs HFS+ \\
      -fsargs "-c c=64,a=16,e=16" \\
      -size 512000k \\
      "#{writable_dmg}" \\
      -puppetstrings
  EOH
end

#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"

Parameters:

  • val (String) (defaults to: NULL)

    the PKG position inside the DMG

Returns:

  • (String)

    the PKG position inside the DMG



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! <<-EOH.gsub(/^ {10}/, "")
      osascript "#{staging_dir}/create_dmg.osascript"
    EOH
  end
end

#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! <<-EOH.gsub(/^ {10}/, "")
      rm -rf "#{writable_dmg}"
    EOH
  end
end

#resources_dirString

The path where the MSI resources will live.

Returns:

  • (String)


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! <<-EOH.gsub(/^ {10}/, "")
      # Convert the png to an icon
      sips -i "#{resource_path("icon.png")}"

      # Extract the icon into its own resource
      DeRez -only icns "#{resource_path("icon.png")}" > tmp.rsrc

      # Append the icon reosurce to the DMG
      Rez -append tmp.rsrc -o "#{package_path}"

      # Source the icon
      SetFile -a C "#{package_path}"
    EOH
  end
end

#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! <<-EOH.gsub(/^ {10}/, "")
      # Generate the icns
      mkdir tmp.iconset
      sips -z 16 16     #{icon} --out tmp.iconset/icon_16x16.png
      sips -z 32 32     #{icon} --out tmp.iconset/[email protected]
      sips -z 32 32     #{icon} --out tmp.iconset/icon_32x32.png
      sips -z 64 64     #{icon} --out tmp.iconset/[email protected]
      sips -z 128 128   #{icon} --out tmp.iconset/icon_128x128.png
      sips -z 256 256   #{icon} --out tmp.iconset/[email protected]
      sips -z 256 256   #{icon} --out tmp.iconset/icon_256x256.png
      sips -z 512 512   #{icon} --out tmp.iconset/[email protected]
      sips -z 512 512   #{icon} --out tmp.iconset/icon_512x512.png
      sips -z 1024 1024 #{icon} --out tmp.iconset/[email protected]
      iconutil -c icns tmp.iconset

      # Copy it over
      cp tmp.icns "/Volumes/#{volume_name}/.VolumeIcon.icns"

      # Source the icon
      SetFile -a C "/Volumes/#{volume_name}"
    EOH
  end
end

#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! <<-EOH.gsub(/^ {10}/, "")
      hdiutil verify \\
        "#{package_path}" \\
        -puppetstrings
    EOH
  end
end

#volume_nameString

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

Returns:

  • (String)


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"

Parameters:

  • val (String) (defaults to: NULL)

    the DMG window bounds

Returns:

  • (String)

    the DMG window bounds



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.

Returns:

  • (String)


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

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