omnibus 2.0.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.rubocop.yml +2 -0
- data/.travis.yml +0 -2
- data/CHANGELOG.md +26 -6
- data/Gemfile +7 -0
- data/Guardfile +10 -0
- data/README.md +103 -160
- data/Rakefile +6 -1
- data/docs/Building on OSX.md +66 -0
- data/docs/omnibus-build-cache.md +75 -0
- data/lib/omnibus.rb +9 -13
- data/lib/omnibus/artifact.rb +1 -13
- data/lib/omnibus/assets/README-logo.png +0 -0
- data/lib/omnibus/assets/logo.psd +0 -0
- data/lib/omnibus/builder.rb +1 -0
- data/lib/omnibus/cli/application.rb +17 -4
- data/lib/omnibus/cli/build.rb +6 -4
- data/lib/omnibus/config.rb +33 -0
- data/lib/omnibus/exceptions.rb +20 -14
- data/lib/omnibus/health_check.rb +2 -0
- data/lib/omnibus/install_path_cache.rb +106 -0
- data/lib/omnibus/library.rb +18 -1
- data/lib/omnibus/packagers/base.rb +228 -0
- data/lib/omnibus/packagers/mac_dmg.rb +215 -0
- data/lib/omnibus/packagers/mac_pkg.rb +129 -253
- data/lib/omnibus/project.rb +89 -95
- data/lib/omnibus/s3_cacher.rb +4 -7
- data/lib/omnibus/software.rb +47 -83
- data/lib/omnibus/sugar.rb +49 -0
- data/lib/omnibus/templates/.kitchen.yml.erb +3 -0
- data/lib/omnibus/templates/Berksfile.erb +4 -0
- data/lib/omnibus/templates/Gemfile.erb +1 -1
- data/lib/omnibus/templates/mac_dmg/background.png +0 -0
- data/lib/omnibus/templates/mac_dmg/icon.png +0 -0
- data/lib/omnibus/templates/mac_pkg/background.png +0 -0
- data/lib/omnibus/templates/mac_pkg/license.html.erb +1 -0
- data/lib/omnibus/templates/mac_pkg/welcome.html.erb +9 -0
- data/lib/omnibus/templates/omnibus.rb.example.erb +31 -4
- data/lib/omnibus/version.rb +1 -1
- data/omnibus.gemspec +5 -4
- data/spec/fixtures/sample/files/mac_dmg/Resources/background.png +0 -0
- data/spec/fixtures/sample/files/mac_dmg/Resources/icon.png +0 -0
- data/spec/fixtures/sample/files/mac_pkg/Resources/background.png +0 -0
- data/spec/fixtures/sample/files/mac_pkg/Resources/license.html +1 -0
- data/spec/fixtures/sample/files/mac_pkg/Resources/welcome.html +9 -0
- data/{functional/fixtures/mac_pkg/package-scripts/functional-test-project → spec/fixtures/sample/package-scripts/sample}/postinstall +0 -0
- data/spec/functional/packagers/mac_spec.rb +74 -0
- data/spec/spec_helper.rb +14 -3
- data/spec/sugar_spec.rb +20 -0
- data/spec/{artifact_spec.rb → unit/artifact_spec.rb} +2 -3
- data/spec/{build_version_spec.rb → unit/build_version_spec.rb} +0 -0
- data/spec/{config_spec.rb → unit/config_spec.rb} +4 -0
- data/spec/{fetchers → unit/fetchers}/git_fetcher_spec.rb +0 -0
- data/spec/{fetchers → unit/fetchers}/net_fetcher_spec.rb +0 -0
- data/spec/unit/install_path_cache_spec.rb +175 -0
- data/spec/unit/library_spec.rb +67 -0
- data/spec/{omnibus_spec.rb → unit/omnibus_spec.rb} +0 -0
- data/spec/{overrides_spec.rb → unit/overrides_spec.rb} +0 -0
- data/spec/{package_release_spec.rb → unit/package_release_spec.rb} +0 -0
- data/spec/unit/packagers/base_spec.rb +221 -0
- data/spec/unit/packagers/mac_pkg_spec.rb +163 -0
- data/spec/{project_spec.rb → unit/project_spec.rb} +0 -14
- data/spec/{s3_cacher_spec.rb → unit/s3_cacher_spec.rb} +0 -0
- data/spec/{software_spec.rb → unit/software_spec.rb} +0 -1
- metadata +122 -103
- data/functional/fixtures/mac_pkg/files/mac_pkg/Resources/background.png +0 -0
- data/functional/fixtures/mac_pkg/files/mac_pkg/Resources/license.html +0 -1
- data/functional/fixtures/mac_pkg/files/mac_pkg/Resources/welcome.html +0 -1
- data/functional/packagers/mac_pkg_spec.rb +0 -72
- data/lib/omnibus/clean_tasks.rb +0 -28
- data/spec/packagers/mac_pkg_spec.rb +0 -262
data/lib/omnibus/library.rb
CHANGED
@@ -27,7 +27,24 @@ module Omnibus
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def component_added(component)
|
30
|
-
@components
|
30
|
+
unless @components.find { |c| c.name == component.name }
|
31
|
+
@components << component
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def build_order
|
36
|
+
head = []
|
37
|
+
tail = []
|
38
|
+
@components.each do |component|
|
39
|
+
if head.length == 0
|
40
|
+
head << component
|
41
|
+
elsif @project.dependencies.include?(component.name)
|
42
|
+
tail << component
|
43
|
+
else
|
44
|
+
head << component
|
45
|
+
end
|
46
|
+
end
|
47
|
+
[head, tail].flatten
|
31
48
|
end
|
32
49
|
|
33
50
|
def version_map
|
@@ -0,0 +1,228 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2014 Chef Software, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
require 'fileutils'
|
19
|
+
require 'forwardable'
|
20
|
+
require 'omnibus/util'
|
21
|
+
|
22
|
+
module Omnibus
|
23
|
+
class Packager::Base
|
24
|
+
include Util
|
25
|
+
|
26
|
+
extend Forwardable
|
27
|
+
|
28
|
+
# The Omnibus::Project instance that we're packaging.
|
29
|
+
attr_reader :project
|
30
|
+
|
31
|
+
# !@method name
|
32
|
+
# @return (see Project#name)
|
33
|
+
def_delegator :@project, :name
|
34
|
+
|
35
|
+
# !@method version
|
36
|
+
# @return (see Project#build_version)
|
37
|
+
def_delegator :@project, :build_version, :version
|
38
|
+
|
39
|
+
# !@method iteration
|
40
|
+
# @return (see Project#iteration)
|
41
|
+
def_delegator :@project, :iteration, :iteration
|
42
|
+
|
43
|
+
# !@method identifier
|
44
|
+
# @return (see Project#mac_pkg_identifier)
|
45
|
+
def_delegator :@project, :mac_pkg_identifier, :identifier
|
46
|
+
|
47
|
+
# !@method install_path
|
48
|
+
# @return (see Project#install_path)
|
49
|
+
def_delegator :@project, :install_path, :install_path
|
50
|
+
|
51
|
+
# !@method scripts
|
52
|
+
# @return (see Project#package_scripts_path)
|
53
|
+
def_delegator :@project, :package_scripts_path, :scripts
|
54
|
+
|
55
|
+
# !@method files_path
|
56
|
+
# @return (see Project#files_path)
|
57
|
+
def_delegator :@project, :files_path
|
58
|
+
|
59
|
+
# !@method package_dir
|
60
|
+
# @return (see Project#package_dir)
|
61
|
+
def_delegator :@project, :package_dir
|
62
|
+
|
63
|
+
# The commands/steps to setup the file system.
|
64
|
+
def self.setup(&block)
|
65
|
+
if block_given?
|
66
|
+
@setup = block
|
67
|
+
else
|
68
|
+
@setup
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# The commands/steps to validate any arguments.
|
73
|
+
def self.validate(&block)
|
74
|
+
if block_given?
|
75
|
+
@validate = block
|
76
|
+
else
|
77
|
+
@validate
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# The commands/steps to build the package.
|
82
|
+
def self.build(&block)
|
83
|
+
if block_given?
|
84
|
+
@build = block
|
85
|
+
else
|
86
|
+
@build || fail(AbstractMethod.new("#{self.class.name}.build"))
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# The commands/steps to cleanup any temporary files/directories.
|
91
|
+
def self.clean(&block)
|
92
|
+
if block_given?
|
93
|
+
@clean = block
|
94
|
+
else
|
95
|
+
@clean
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Create a new packager object.
|
100
|
+
#
|
101
|
+
# @param [Project] project
|
102
|
+
def initialize(project)
|
103
|
+
@project = project
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# Generation methods
|
108
|
+
# ------------------------------
|
109
|
+
|
110
|
+
# Create a directory at the given +path+.
|
111
|
+
#
|
112
|
+
# @param [String] path
|
113
|
+
def create_directory(path)
|
114
|
+
FileUtils.mkdir_p(path)
|
115
|
+
path
|
116
|
+
end
|
117
|
+
|
118
|
+
# Remove the directory at the given +path+.
|
119
|
+
#
|
120
|
+
# @param [String] path
|
121
|
+
def remove_directory(path)
|
122
|
+
FileUtils.rm_rf(path)
|
123
|
+
end
|
124
|
+
|
125
|
+
# Purge the directory of all contents.
|
126
|
+
#
|
127
|
+
# @param [String] path
|
128
|
+
def purge_directory(path)
|
129
|
+
remove_directory(path)
|
130
|
+
create_directory(path)
|
131
|
+
end
|
132
|
+
|
133
|
+
# Copy the +source+ file to the +destination+.
|
134
|
+
#
|
135
|
+
# @param [String] source
|
136
|
+
# @param [String] destination
|
137
|
+
def copy_file(source, destination)
|
138
|
+
FileUtils.cp(source, destination)
|
139
|
+
destination
|
140
|
+
end
|
141
|
+
|
142
|
+
# Remove the file at the given path.
|
143
|
+
#
|
144
|
+
# @param [String] pah
|
145
|
+
def remove_file(path)
|
146
|
+
FileUtils.rm_f(path)
|
147
|
+
end
|
148
|
+
|
149
|
+
# Execute the command using shellout!
|
150
|
+
#
|
151
|
+
# @param [String] command
|
152
|
+
def execute(command)
|
153
|
+
shellout!(command, timeout: 3600, cwd: staging_dir)
|
154
|
+
end
|
155
|
+
|
156
|
+
#
|
157
|
+
# Validations
|
158
|
+
# ------------------------------
|
159
|
+
|
160
|
+
# Validate the presence of a file.
|
161
|
+
#
|
162
|
+
# @param [String] path
|
163
|
+
def assert_presence!(path)
|
164
|
+
fail MissingAsset.new(path) unless File.exist?(path)
|
165
|
+
end
|
166
|
+
|
167
|
+
# Execute this packager by running the following phases in order:
|
168
|
+
#
|
169
|
+
# - setup
|
170
|
+
# - validate
|
171
|
+
# - build
|
172
|
+
# - clean
|
173
|
+
#
|
174
|
+
def run!
|
175
|
+
instance_eval(&self.class.validate) if self.class.validate
|
176
|
+
instance_eval(&self.class.setup) if self.class.setup
|
177
|
+
instance_eval(&self.class.build) if self.class.build
|
178
|
+
instance_eval(&self.class.clean) if self.class.clean
|
179
|
+
end
|
180
|
+
|
181
|
+
# The ending name of this package on disk. +Omnibus::Project+ uses this to
|
182
|
+
# generate metadata about the package after it is built.
|
183
|
+
#
|
184
|
+
# @return [String]
|
185
|
+
def package_name
|
186
|
+
fail AbstractMethod.new("#{self.class.name}#package_name")
|
187
|
+
end
|
188
|
+
|
189
|
+
private
|
190
|
+
|
191
|
+
# The path to the directory where we can throw staged files.
|
192
|
+
#
|
193
|
+
# @return [String]
|
194
|
+
def staging_dir
|
195
|
+
File.expand_path("#{project.package_tmp}/#{underscore_name}")
|
196
|
+
end
|
197
|
+
|
198
|
+
# The path to a local resource on disk.
|
199
|
+
#
|
200
|
+
# @param [String]
|
201
|
+
# the name or path of the resource
|
202
|
+
# @return [String]
|
203
|
+
def resource(path)
|
204
|
+
File.expand_path("#{resources_path}/#{path}")
|
205
|
+
end
|
206
|
+
|
207
|
+
# The path to all the resources on the local file system.
|
208
|
+
#
|
209
|
+
# @return [String]
|
210
|
+
def resources_path
|
211
|
+
File.expand_path("#{project.files_path}/#{underscore_name}/Resources")
|
212
|
+
end
|
213
|
+
|
214
|
+
# The underscored equivalent of this class. This is mostly used by file
|
215
|
+
# paths.
|
216
|
+
#
|
217
|
+
# @return [String]
|
218
|
+
def underscore_name
|
219
|
+
@underscore_name ||= self.class.name
|
220
|
+
.split('::')
|
221
|
+
.last
|
222
|
+
.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
|
223
|
+
.gsub(/([a-z\d])([A-Z])/, '\1_\2')
|
224
|
+
.tr('-', '_')
|
225
|
+
.downcase
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
@@ -0,0 +1,215 @@
|
|
1
|
+
#
|
2
|
+
# Copyright:: Copyright (c) 2014 Chef Software, Inc.
|
3
|
+
# License:: Apache License, Version 2.0
|
4
|
+
#
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License");
|
6
|
+
# you may not use this file except in compliance with the License.
|
7
|
+
# You may obtain a copy of the License at
|
8
|
+
#
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
10
|
+
#
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
14
|
+
# See the License for the specific language governing permissions and
|
15
|
+
# limitations under the License.
|
16
|
+
#
|
17
|
+
|
18
|
+
module Omnibus
|
19
|
+
class Packager::MacDmg < Packager::Base
|
20
|
+
attr_reader :packager
|
21
|
+
|
22
|
+
validate do
|
23
|
+
assert_presence!(resource('background.png'))
|
24
|
+
assert_presence!(resource('icon.png'))
|
25
|
+
end
|
26
|
+
|
27
|
+
setup do
|
28
|
+
create_directory(dmg_stage)
|
29
|
+
copy_assets_to_dmg
|
30
|
+
end
|
31
|
+
|
32
|
+
build do
|
33
|
+
copy_assets_to_dmg
|
34
|
+
create_writable_dmg
|
35
|
+
attach_dmg
|
36
|
+
set_volume_icon
|
37
|
+
prettify_dmg
|
38
|
+
compress_dmg
|
39
|
+
set_dmg_icon
|
40
|
+
end
|
41
|
+
|
42
|
+
clean do
|
43
|
+
remove_file("#{staging_dir}/tmp.icns")
|
44
|
+
remove_file("#{staging_dir}/tmp.rsrc")
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Create a new DMG packager.
|
49
|
+
#
|
50
|
+
# @param [Packager::MacPkg] mac_packager
|
51
|
+
#
|
52
|
+
def initialize(mac_packager)
|
53
|
+
@packager = mac_packager
|
54
|
+
super(mac_packager.project)
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Copy the assets in the local omnibus project into a staging folder that
|
59
|
+
# will soon become our writable dmg.
|
60
|
+
#
|
61
|
+
def copy_assets_to_dmg
|
62
|
+
# Copy the compiled pkg into the dmg
|
63
|
+
copy_file(packager.final_pkg, "#{dmg_stage}/#{project.name}.pkg")
|
64
|
+
|
65
|
+
# Copy support files
|
66
|
+
support = create_directory("#{dmg_stage}/.support")
|
67
|
+
copy_file(resource('background.png'), "#{support}/background.png")
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Create a writable dmg we can put assets on.
|
72
|
+
#
|
73
|
+
def create_writable_dmg
|
74
|
+
execute <<-EOH.gsub(/^ {8}/, '')
|
75
|
+
hdiutil create \\
|
76
|
+
-srcfolder "#{dmg_stage}" \\
|
77
|
+
-volname "#{project.name}" \\
|
78
|
+
-fs HFS+ \\
|
79
|
+
-fsargs "-c c=64,a=16,e=16" \\
|
80
|
+
-format UDRW \\
|
81
|
+
-size 512000k \\
|
82
|
+
"#{writable_dmg}"
|
83
|
+
EOH
|
84
|
+
end
|
85
|
+
|
86
|
+
#
|
87
|
+
# Attach the dmg, storing a reference to the device for later use.
|
88
|
+
#
|
89
|
+
def attach_dmg
|
90
|
+
@device = execute(<<-EOH.gsub(/^ {8}/, '')).stdout.strip
|
91
|
+
hdiutil attach \\
|
92
|
+
-readwrite \\
|
93
|
+
-noverify \\
|
94
|
+
-noautoopen \\
|
95
|
+
"#{writable_dmg}" | egrep '^/dev/' | sed 1q | awk '{print $1}'
|
96
|
+
EOH
|
97
|
+
end
|
98
|
+
|
99
|
+
#
|
100
|
+
# Create the icon for the volume using sips.
|
101
|
+
#
|
102
|
+
def set_volume_icon
|
103
|
+
execute <<-EOH.gsub(/^ {8}/, '')
|
104
|
+
# Generate the icns
|
105
|
+
mkdir tmp.iconset
|
106
|
+
sips -z 16 16 #{resource('icon.png')} --out tmp.iconset/icon_16x16.png
|
107
|
+
sips -z 32 32 #{resource('icon.png')} --out tmp.iconset/icon_16x16@2x.png
|
108
|
+
sips -z 32 32 #{resource('icon.png')} --out tmp.iconset/icon_32x32.png
|
109
|
+
sips -z 64 64 #{resource('icon.png')} --out tmp.iconset/icon_32x32@2x.png
|
110
|
+
sips -z 128 128 #{resource('icon.png')} --out tmp.iconset/icon_128x128.png
|
111
|
+
sips -z 256 256 #{resource('icon.png')} --out tmp.iconset/icon_128x128@2x.png
|
112
|
+
sips -z 256 256 #{resource('icon.png')} --out tmp.iconset/icon_256x256.png
|
113
|
+
sips -z 512 512 #{resource('icon.png')} --out tmp.iconset/icon_256x256@2x.png
|
114
|
+
sips -z 512 512 #{resource('icon.png')} --out tmp.iconset/icon_512x512.png
|
115
|
+
sips -z 1024 1024 #{resource('icon.png')} --out tmp.iconset/icon_512x512@2x.png
|
116
|
+
iconutil -c icns tmp.iconset
|
117
|
+
|
118
|
+
# Copy it over
|
119
|
+
cp tmp.icns "/Volumes/#{project.name}/.VolumeIcon.icns"
|
120
|
+
|
121
|
+
# Source the icon
|
122
|
+
SetFile -a C "/Volumes/#{project.name}"
|
123
|
+
EOH
|
124
|
+
end
|
125
|
+
|
126
|
+
#
|
127
|
+
# Use Applescript to setup the DMG with pretty logos and colors.
|
128
|
+
#
|
129
|
+
def prettify_dmg
|
130
|
+
execute <<-EOH.gsub(/ ^{8}/, '')
|
131
|
+
echo '
|
132
|
+
tell application "Finder"
|
133
|
+
tell disk "'#{project.name}'"
|
134
|
+
open
|
135
|
+
set current view of container window to icon view
|
136
|
+
set toolbar visible of container window to false
|
137
|
+
set statusbar visible of container window to false
|
138
|
+
set the bounds of container window to {#{project.config[:dmg_window_bounds]}}
|
139
|
+
set theViewOptions to the icon view options of container window
|
140
|
+
set arrangement of theViewOptions to not arranged
|
141
|
+
set icon size of theViewOptions to 72
|
142
|
+
set background picture of theViewOptions to file ".support:'background.png'"
|
143
|
+
delay 5
|
144
|
+
set position of item "'#{project.name}.pkg'" of container window to {#{project.config[:dmg_pkg_position]}}
|
145
|
+
update without registering applications
|
146
|
+
delay 5
|
147
|
+
end tell
|
148
|
+
end tell
|
149
|
+
' | osascript
|
150
|
+
EOH
|
151
|
+
end
|
152
|
+
|
153
|
+
#
|
154
|
+
# Compress the dmg using hdiutil and zlib.
|
155
|
+
#
|
156
|
+
def compress_dmg
|
157
|
+
execute <<-EOH.gsub(/ ^{8}/, '')
|
158
|
+
chmod -Rf go-w /Volumes/#{project.name}
|
159
|
+
sync
|
160
|
+
hdiutil detach "#{@device}"
|
161
|
+
hdiutil convert \\
|
162
|
+
"#{writable_dmg}" \\
|
163
|
+
-format UDZO \\
|
164
|
+
-imagekey zlib-level=9 \\
|
165
|
+
-o "#{final_dmg}"
|
166
|
+
rm -rf "#{writable_dmg}"
|
167
|
+
EOH
|
168
|
+
end
|
169
|
+
|
170
|
+
#
|
171
|
+
# Set the dmg icon to our custom icon.
|
172
|
+
#
|
173
|
+
def set_dmg_icon
|
174
|
+
execute <<-EOH.gsub(/^ {8}/, '')
|
175
|
+
# Convert the png to an icon
|
176
|
+
sips -i "#{resource('icon.png')}"
|
177
|
+
|
178
|
+
# Extract the icon into its own resource
|
179
|
+
DeRez -only icns "#{resource('icon.png')}" > tmp.rsrc
|
180
|
+
|
181
|
+
# Append the icon reosurce to the DMG
|
182
|
+
Rez -append tmp.rsrc -o "#{final_dmg}"
|
183
|
+
|
184
|
+
# Source the icon
|
185
|
+
SetFile -a C "#{final_dmg}"
|
186
|
+
EOH
|
187
|
+
end
|
188
|
+
|
189
|
+
# @see Base#package_name
|
190
|
+
def package_name
|
191
|
+
"#{name}-#{version}-#{iteration}.dmg"
|
192
|
+
end
|
193
|
+
|
194
|
+
# The path to the folder that we should stage.
|
195
|
+
#
|
196
|
+
# @return [String]
|
197
|
+
def dmg_stage
|
198
|
+
File.expand_path("#{staging_dir}/dmg")
|
199
|
+
end
|
200
|
+
|
201
|
+
# The path to the writable dmg on disk.
|
202
|
+
#
|
203
|
+
# @return [String]
|
204
|
+
def writable_dmg
|
205
|
+
File.expand_path("#{staging_dir}/#{name}-writable.dmg")
|
206
|
+
end
|
207
|
+
|
208
|
+
# The path where the final dmg will be produced.
|
209
|
+
#
|
210
|
+
# @return [String]
|
211
|
+
def final_dmg
|
212
|
+
File.expand_path("#{project.package_dir}/#{name}-#{version}-#{iteration}.dmg")
|
213
|
+
end
|
214
|
+
end
|
215
|
+
end
|