class Omnibus::Packager::MSI

Public Instance Methods

bundle_msi(val = false) click to toggle source

Signal that we’re building a bundle rather than a single package

@example

bundle_msi true

@param [TrueClass, FalseClass] value

whether we're a bundle or not

@return [TrueClass, FalseClass]

whether we're a bundle or not
# File lib/omnibus/packagers/msi.rb, line 226
def bundle_msi(val = false)
  unless val.is_a?(TrueClass) || val.is_a?(FalseClass)
    raise InvalidValue.new(:bundle_msi, "be TrueClass or FalseClass")
  end

  @bundle_msi ||= val
end
bundle_name() click to toggle source
# File lib/omnibus/packagers/msi.rb, line 347
def bundle_name
  "#{project.package_name}-#{project.build_version}-#{project.build_iteration}-#{Config.windows_arch}.exe"
end
candle_command(is_bundle: false) click to toggle source

Get the shell command to complie the project WIX files

@return [String]

# File lib/omnibus/packagers/msi.rb, line 506
    def candle_command(is_bundle: false)
      if is_bundle
        <<-EOH.split.join(" ").squeeze(" ").strip
        candle.exe
          -nologo
          #{wix_candle_flags}
          -ext WixBalExtension
          #{wix_extension_switches(wix_candle_extensions)}
          -dOmnibusCacheDir="#{windows_safe_path(File.expand_path(Config.cache_dir))}"
          "#{windows_safe_path(staging_dir, "bundle.wxs")}"
        EOH
      else
        <<-EOH.split.join(" ").squeeze(" ").strip
          candle.exe
            -nologo
            #{wix_candle_flags}
            #{wix_extension_switches(wix_candle_extensions)}
            -dProjectSourceDir="#{windows_safe_path(project.install_dir)}" "project-files.wxs"
            "#{windows_safe_path(staging_dir, "source.wxs")}"
        EOH
      end
    end
fast_msi(val = false) click to toggle source

Signal that we’re building a zip-based MSI

@example

fast_msi true

@param [TrueClass, FalseClass] value

whether we're building a zip-based MSI or not

@return [TrueClass, FalseClass]

whether we're building a zip-based MSI or not
# File lib/omnibus/packagers/msi.rb, line 246
def fast_msi(val = false)
  unless val.is_a?(TrueClass) || val.is_a?(FalseClass)
    raise InvalidValue.new(:fast_msi, "be TrueClass or FalseClass")
  end

  @fast_msi ||= val
end
gem_path(glob = NULL) click to toggle source

Discovers a path to a gem/file included in a gem under the install directory.

@example

gem_path 'chef-[0-9]*-mingw32' -> 'some/path/to/gems/chef-version-mingw32'

@param [String] glob

a ruby acceptable glob path such as with **, *, [] etc.

@return [String] path relative to the project’s install_dir

Raises exception the glob matches 0 or more than 1 file/directory.

# File lib/omnibus/packagers/msi.rb, line 291
def gem_path(glob = NULL)
  unless glob.is_a?(String) || null?(glob)
    raise InvalidValue.new(:glob, "be an String")
  end

  install_path = Pathname.new(project.install_dir)

  # Find path in which the Chef gem is installed
  search_pattern = install_path.join("**", "gems")
  search_pattern = search_pattern.join(glob) unless null?(glob)
  file_paths = Pathname.glob(search_pattern).find

  raise "Could not find `#{search_pattern}'!" if file_paths.none?
  raise "Multiple possible matches of `#{search_pattern}'! : #{file_paths}" if file_paths.count > 1

  file_paths.first.relative_path_from(install_path).to_s
end
heat_command() click to toggle source

Get the shell command to run heat in order to create a a WIX manifest of project files to be packaged into the MSI

@return [String]

# File lib/omnibus/packagers/msi.rb, line 481
    def heat_command
      if fast_msi
        <<-EOH.split.join(" ").squeeze(" ").strip
          heat.exe file "#{zip_name}.zip"
          -cg ProjectDir
          -dr INSTALLLOCATION
          -nologo -sfrag -srd -sreg -gg
          -out "project-files.wxs"
        EOH
      else
        <<-EOH.split.join(" ").squeeze(" ").strip
          heat.exe dir "#{windows_safe_path(project.install_dir)}"
            -nologo -srd -sreg -gg -cg ProjectDir
            -dr PROJECTLOCATION
            -var "var.ProjectSourceDir"
            -out "project-files.wxs"
        EOH
      end
    end
light_command(out_file, is_bundle: false) click to toggle source

Get the shell command to link the project WIX object files

@return [String]

# File lib/omnibus/packagers/msi.rb, line 534
    def light_command(out_file, is_bundle: false)
      if is_bundle
        <<-EOH.split.join(" ").squeeze(" ").strip
        light.exe
          -nologo
          #{wix_light_delay_validation}
          -ext WixUIExtension
          -ext WixBalExtension
          #{wix_extension_switches(wix_light_extensions)}
          -cultures:#{localization}
          -loc "#{windows_safe_path(staging_dir, "localization-#{localization}.wxl")}"
          bundle.wixobj
          -out "#{out_file}"
        EOH
      else
        <<-EOH.split.join(" ").squeeze(" ").strip
          light.exe
            -nologo
            #{wix_light_delay_validation}
            -ext WixUIExtension
            #{wix_extension_switches(wix_light_extensions)}
            -cultures:#{localization}
            -loc "#{windows_safe_path(staging_dir, "localization-#{localization}.wxl")}"
            project-files.wixobj source.wixobj
            -out "#{out_file}"
        EOH
      end
    end
localization(val = "en-us") click to toggle source

Set or retrieve the localization. Take a look at this list of valid localizations.

@example

localization 'de-de'

@param [String] val

the localization to set

@return [String]

the set localization
# File lib/omnibus/packagers/msi.rb, line 269
def localization(val = "en-us")
  unless val.is_a?(String)
    raise InvalidValue.new(:localization, "be a String")
  end

  @localization ||= val
end
msi_display_version() click to toggle source

The display version calculated from the {Project#build_version}.

@see windows_package_version an explanation of the breakdown

@return [String]

# File lib/omnibus/packagers/msi.rb, line 570
def msi_display_version
  versions = project.build_version.split(/[.+-]/)
  "#{versions[0]}.#{versions[1]}.#{versions[2]}"
end
msi_name() click to toggle source
# File lib/omnibus/packagers/msi.rb, line 343
def msi_name
  "#{project.package_name}-#{project.build_version}-#{project.build_iteration}-#{Config.windows_arch}.msi"
end
package_name() click to toggle source

@see Base#package_name

# File lib/omnibus/packagers/msi.rb, line 339
def package_name
  bundle_msi ? bundle_name : msi_name
end
parameters(val = NULL) click to toggle source

Set or retrieve the custom msi building parameters.

@example

parameters {
  'MagicParam' => 'ABCD-1234'
}

@param [Hash] val

the parameters to set

@return [Hash]

the set parameters
# File lib/omnibus/packagers/msi.rb, line 135
def parameters(val = NULL)
  if null?(val)
    @parameters || {}
  else
    unless val.is_a?(Hash)
      raise InvalidValue.new(:parameters, "be a Hash")
    end

    @parameters = val
  end
end
resources_dir() click to toggle source

The path where the MSI resources will live.

@return [String]

# File lib/omnibus/packagers/msi.rb, line 356
def resources_dir
  File.expand_path("#{staging_dir}/Resources")
end
upgrade_code(val = NULL) click to toggle source

Set or retrieve the upgrade code.

@example

upgrade_code 'ABCD-1234'

@param [Hash] val

the UpgradeCode to set

@return [Hash]

the set UpgradeCode
# File lib/omnibus/packagers/msi.rb, line 108
def upgrade_code(val = NULL)
  if null?(val)
    @upgrade_code || raise(MissingRequiredAttribute.new(self, :upgrade_code, "2CD7259C-776D-4DDB-A4C8-6E544E580AA1"))
  else
    unless val.is_a?(String)
      raise InvalidValue.new(:upgrade_code, "be a String")
    end

    @upgrade_code = val
  end
end
wix_candle_extension(extension) click to toggle source

Set the wix candle extensions to load

@example

wix_candle_extension 'WixUtilExtension'

@param [String] extension

A list of extensions to load

@return [Array]

The list of extensions that will be loaded
# File lib/omnibus/packagers/msi.rb, line 206
def wix_candle_extension(extension)
  unless extension.is_a?(String)
    raise InvalidValue.new(:wix_candle_extension, "be an String")
  end

  wix_candle_extensions << extension
end
wix_candle_extensions() click to toggle source

Returns the extensions to use for candle

@return [Array]

the extensions that will be loaded for candle
# File lib/omnibus/packagers/msi.rb, line 591
def wix_candle_extensions
  @wix_candle_extensions ||= []
end
wix_candle_flags() click to toggle source

Returns the options to use for candle

@return [Array]

the extensions that will be loaded for candle
# File lib/omnibus/packagers/msi.rb, line 601
def wix_candle_flags
  # we support x86 or x64.  No Itanium support (ia64).
  @wix_candle_flags ||= "-arch " + (Config.windows_arch.to_sym == :x86 ? "x86" : "x64")
end
wix_extension_switches(arr) click to toggle source

Takes an array of wix extension names and creates a string that can be passed to wix to load those.

for example,

‘a’, ‘b’

> “-ext ‘a’ -ext ‘b’”

@return [String]

# File lib/omnibus/packagers/msi.rb, line 615
def wix_extension_switches(arr)
  "#{arr.map { |e| "-ext '#{e}'" }.join(" ")}"
end
wix_light_delay_validation(val = false) click to toggle source

Signal delay validation for wix light

@example

wix_light_deplay_validation true

@param [TrueClass, FalseClass] value

whether to delay validation or not

@return [String]

whether we're a bundle or not
# File lib/omnibus/packagers/msi.rb, line 180
def wix_light_delay_validation(val = false)
  unless val.is_a?(TrueClass) || val.is_a?(FalseClass)
    raise InvalidValue.new(:iwix_light_delay_validation, "be TrueClass or FalseClass")
  end

  @delay_validation ||= val
  unless @delay_validation
    return ""
  end

  "-sval"
end
wix_light_extension(extension) click to toggle source

Set the wix light extensions to load

@example

wix_light_extension 'WixUtilExtension'

@param [String] extension

A list of extensions to load

@return [Array]

The list of extensions that will be loaded
# File lib/omnibus/packagers/msi.rb, line 160
def wix_light_extension(extension)
  unless extension.is_a?(String)
    raise InvalidValue.new(:wix_light_extension, "be an String")
  end

  wix_light_extensions << extension
end
wix_light_extensions() click to toggle source

Returns the extensions to use for light

@return [Array]

the extensions that will be loaded for light
# File lib/omnibus/packagers/msi.rb, line 581
def wix_light_extensions
  @wix_light_extensions ||= []
end
write_bundle_file() click to toggle source

Write the bundle file into the staging directory.

@return [void]

# File lib/omnibus/packagers/msi.rb, line 446
def write_bundle_file
  render_template(resource_path("bundle.wxs.erb"),
    destination: "#{staging_dir}/bundle.wxs",
    variables: {
      name: project.package_name,
      friendly_name: project.friendly_name,
      maintainer: project.maintainer,
      upgrade_code: upgrade_code,
      parameters: parameters,
      version: windows_package_version,
      display_version: msi_display_version,
      msi: windows_safe_path(Config.package_dir, msi_name),
    })
end
write_localization_file() click to toggle source

Write the localization file into the staging directory.

@return [void]

# File lib/omnibus/packagers/msi.rb, line 365
def write_localization_file
  render_template(resource_path("localization-#{localization}.wxl.erb"),
    destination: "#{staging_dir}/localization-#{localization}.wxl",
    variables: {
      name: project.package_name,
      friendly_name: project.friendly_name,
      maintainer: project.maintainer,
    })
end
write_parameters_file() click to toggle source

Write the parameters file into the staging directory.

@return [void]

# File lib/omnibus/packagers/msi.rb, line 380
def write_parameters_file
  render_template(resource_path("parameters.wxi.erb"),
    destination: "#{staging_dir}/parameters.wxi",
    variables: {
      name: project.package_name,
      friendly_name: project.friendly_name,
      maintainer: project.maintainer,
      upgrade_code: upgrade_code,
      parameters: parameters,
      version: windows_package_version,
      display_version: msi_display_version,
    })
end
write_source_file() click to toggle source

Write the source file into the staging directory.

@return [void]

# File lib/omnibus/packagers/msi.rb, line 399
def write_source_file
  paths = []

  # Remove C:/
  install_dir = project.install_dir.split("/")[1..-1].join("/")

  # Grab all parent paths
  Pathname.new(install_dir).ascend do |path|
    paths << path.to_s
  end

  # Create the hierarchy
  hierarchy = paths.reverse.inject({}) do |hash, path|
    hash[File.basename(path)] = path.gsub(/[^[:alnum:]]/, "").upcase + "LOCATION"
    hash
  end

  # The last item in the path MUST be named PROJECTLOCATION or else space
  # robots will cause permanent damage to you and your family.
  hierarchy[hierarchy.keys.last] = "PROJECTLOCATION"

  # If the path hierarchy is > 1, the customizable installation directory
  # should default to the second-to-last item in the hierarchy. If the
  # hierarchy is smaller than that, then just use the system drive.
  wix_install_dir = if hierarchy.size > 1
                      hierarchy.to_a[-2][1]
                    else
                      "WINDOWSVOLUME"
                    end

  render_template(resource_path("source.wxs.erb"),
    destination: "#{staging_dir}/source.wxs",
    variables: {
      name: project.package_name,
      friendly_name: project.friendly_name,
      maintainer: project.maintainer,
      hierarchy: hierarchy,
      fastmsi: fast_msi,
      wix_install_dir: wix_install_dir,
    })
end
zip_command() click to toggle source

Get the shell command to create a zip file that contains the contents of the project install directory

@return [String]

# File lib/omnibus/packagers/msi.rb, line 467
    def zip_command
      <<-EOH.split.join(" ").squeeze(" ").strip
      7z a -r
      #{windows_safe_path(staging_dir)}\\#{zip_name}.zip
      #{windows_safe_path(project.install_dir)}\\*
      EOH
    end
zip_name(val = NULL) click to toggle source

Provide a custom zip name

@example

zip_name 'chef'

@param [TrueClass, FalseClass] value

whether we're building a zip-based MSI or not

@return [TrueClass, FalseClass]

whether we're building a zip-based MSI or not
# File lib/omnibus/packagers/msi.rb, line 321
def zip_name(val = NULL)
  if null?(val)
    @zip_name || project.name
  else
    unless val.is_a?(String)
      raise InvalidValue.new(:zip_name, "be an String")
    end

    @zip_name = val
  end
end