macinbox 3.2.0 → 3.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e03354e3ebf3d421641208fbd59e61b96a3bfd3b
4
- data.tar.gz: 3f90e09c1a0bb98d6acb2512dd2644446e635a17
3
+ metadata.gz: 36bd1285647b90d338e5519ba42e429e6bb8ea12
4
+ data.tar.gz: 65c6e91a11e43bed2921f006fe1469542d716205
5
5
  SHA512:
6
- metadata.gz: d8e7d1fd2a1b05a6bd89c778ef095ff70f268934281cc263f32375d5119dc25ac9ed3f3315e6e1316d7c1d93f4b23bf5314c32c557d2945a5c58b62e78902a55
7
- data.tar.gz: 0d64344b66fb076a07e879a93a66c38d51d67adcd84c48679b83ac579494329e6f31d1e1201e240fb9abd68f36023121a8e15a8871e0b1a8d56db3fc7bc15171
6
+ metadata.gz: e08c547e56e15487b2d22cdc492aeaa7b3b78dd13b4df4ebdd77daa09537237b18413daa63bd3e473e2b67d4fb4e83137cf493cca63452e54fb994e5ced8953a
7
+ data.tar.gz: 1d4dbf5faac11e49922894e001ea1a32988a11dc85a9327f2f78a6708e9769c18ef32286fbb888273e74183b23e971cf3962328d77d0f443c798bb4df4c235cf
@@ -1,3 +1,14 @@
1
+ ## 3.3.0 (February 26, 2019)
2
+
3
+ FEATURES:
4
+
5
+ - Add --verbose option to show the commands being run. [GH-28]
6
+ - Add --user-script option to support running user-provided customizations. [GH-24]
7
+
8
+ BUG FIXES:
9
+
10
+ - Only display the animated progress bar when stderr is a tty. [GH-25]
11
+
1
12
  ## 3.2.0 (February 2, 2019)
2
13
 
3
14
  FEATURES:
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- macinbox (3.2.0)
4
+ macinbox (3.3.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -106,6 +106,7 @@ Usage: macinbox [options]
106
106
  --installer-dmg PATH Path to a macOS installer app disk image
107
107
  --vmware PATH Path to the VMware Fusion app
108
108
  --parallels PATH Path to the Parallels Desktop app
109
+ --user-script PATH Path to user script
109
110
 
110
111
  --no-auto-login Disable auto login
111
112
  --no-skip-mini-buddy Show the mini buddy on first login
@@ -115,6 +116,7 @@ Usage: macinbox [options]
115
116
 
116
117
  --use-qemu Use qemu-img (vmware_desktop only)
117
118
 
119
+ --verbose Enable verbose mode
118
120
  --debug Enable debug mode
119
121
 
120
122
  -v, --version
@@ -143,6 +145,10 @@ When the box format is set to 'parallels' using the `--box-format` option then t
143
145
 
144
146
  When the box format is set to 'virtualbox' no guest extensions are installed. Note that some features behave differently with VirtualBox. The screen resolution is set to 1280x800 and HiDPI resolutions are not supported. The GUI scale factor is set to 2.0 (so that the VM displays properly on a host with a retina display) unless the `--no-hidpi` option is used. Lastly, ssh port-forwarding is enabled by default so that the host can connect to the guest.
145
147
 
148
+ ## User scripts
149
+
150
+ If additional box customization is required a user script may be specified using the `--user-script` option. The script is run after the OS has been installed and will be provided with the path to the install location as its first and only argument. The script must be executable and exit with code zero or the box creation will be aborted.
151
+
146
152
  ## Installer Disk Image Support
147
153
 
148
154
  The `--installer-dmg` option allows you to indicate the path to a disk image containing a macOS installer, and overrides the `--installer` option. The specified disk image should not already be mounted; `macinbox` will mount and unmount it as needed. This feature allows you to use the installer disk images created by [installinstallmacos.py](https://github.com/munki/macadmin-scripts/blob/master/installinstallmacos.py) as part of the `macinbox` workflow.
@@ -8,7 +8,6 @@ module Macinbox
8
8
  @installer_app = opts[:installer_path] or raise ArgumentError.new(":installer_path not specified")
9
9
 
10
10
  @collector = opts[:collector] or raise ArgumentError.new(":collector not specified")
11
- @debug = opts[:debug]
12
11
 
13
12
  raise Macinbox::Error.new("Installer app not found") unless File.exist? @installer_app
14
13
  end
@@ -21,13 +20,13 @@ module Macinbox
21
20
  installer_os_version_components = installer_os_version.split(".") rescue [0, 0, 0]
22
21
  installer_os_version_major = installer_os_version_components[0]
23
22
  installer_os_version_minor = installer_os_version_components[1]
24
- Logger.info "Installer macOS version detected: #{installer_os_version}" if @debug
23
+ Logger.info "Installer macOS version detected: #{installer_os_version}" if $verbose
25
24
 
26
25
  host_os_version = Task.backtick %W[ /usr/bin/sw_vers -productVersion ]
27
26
  host_os_version_components = host_os_version.split(".") rescue [0, 0, 0]
28
27
  host_os_version_major = host_os_version_components[0]
29
28
  host_os_version_minor = host_os_version_components[1]
30
- Logger.info "Host macOS version detected: #{host_os_version}" if @debug
29
+ Logger.info "Host macOS version detected: #{host_os_version}" if $verbose
31
30
 
32
31
  if installer_os_version_major != host_os_version_major || installer_os_version_minor != host_os_version_minor
33
32
  Logger.error "Warning: host OS version (#{host_os_version}) and installer OS version (#{installer_os_version}) do not match"
@@ -25,7 +25,6 @@ module Macinbox
25
25
  @hidpi = opts[:hidpi]
26
26
 
27
27
  @collector = opts[:collector] or raise ArgumentError.new(":collector not specified")
28
- @debug = opts[:debug]
29
28
 
30
29
  raise Macinbox::Error.new("HDD not found") unless File.exist? @input_hdd
31
30
  end
@@ -55,7 +54,7 @@ module Macinbox
55
54
  end
56
55
  EOF
57
56
 
58
- task_opts = @debug ? {} : { :out => File::NULL }
57
+ task_opts = $verbose ? {} : { :out => File::NULL }
59
58
 
60
59
  Task.run %W[ prlctl create macinbox -o macos --no-hdd --dst #{@box_dir} ] + [task_opts]
61
60
 
@@ -24,7 +24,6 @@ module Macinbox
24
24
  @hidpi = opts[:hidpi]
25
25
 
26
26
  @collector = opts[:collector] or raise ArgumentError.new(":collector not specified")
27
- @debug = opts[:debug]
28
27
 
29
28
  raise Macinbox::Error.new("VDI not found") unless File.exist? @input_vdi
30
29
  end
@@ -53,7 +52,7 @@ module Macinbox
53
52
  end
54
53
  EOF
55
54
 
56
- task_opts = @debug ? {} : { :out => File::NULL }
55
+ task_opts = $verbose ? {} : { :out => File::NULL }
57
56
 
58
57
  Task.run %W[ VBoxManage createvm --register --name macinbox --ostype MacOS1013_64 ] + [task_opts]
59
58
 
@@ -26,7 +26,6 @@ module Macinbox
26
26
  @hidpi = opts[:hidpi]
27
27
 
28
28
  @collector = opts[:collector] or raise ArgumentError.new(":collector not specified")
29
- @debug = opts[:debug]
30
29
 
31
30
  raise Macinbox::Error.new("VMDK not found") unless File.exist? @input_vmdk
32
31
  raise Macinbox::Error.new("Box format not supported: #{@box_format}") unless ["vmware_fusion", "vmware_desktop"].include? @box_format
@@ -19,7 +19,6 @@ module Macinbox
19
19
  @parallels_app = opts[:parallels_path] or raise ArgumentError.new(":parallels_path not specified")
20
20
 
21
21
  @collector = opts[:collector] or raise ArgumentError.new(":collector not specified")
22
- @debug = opts[:debug]
23
22
 
24
23
  raise Macinbox::Error.new("input image not found") unless File.exist? @input_image
25
24
  raise Macinbox::Error.new("Parallels Desktop not found") unless File.exist? @parallels_app
@@ -49,7 +48,7 @@ module Macinbox
49
48
 
50
49
  def attach_image
51
50
  Logger.info "Attaching the image..." do
52
- @disk = VirtualDisk.new(@image, @debug)
51
+ @disk = VirtualDisk.new(@image)
53
52
  @collector.on_cleanup { @disk.detach! }
54
53
  @image_mountpoint = "#{@temp_dir}/image_mountpoint"
55
54
  FileUtils.mkdir @image_mountpoint
@@ -64,7 +63,7 @@ module Macinbox
64
63
 
65
64
  tools_image = "#{@parallels_app}/Contents/Resources/Tools/prl-tools-mac.iso"
66
65
 
67
- tools_disk = VirtualDisk.new(tools_image, @debug)
66
+ tools_disk = VirtualDisk.new(tools_image)
68
67
 
69
68
  @collector.on_cleanup { tools_disk.detach! }
70
69
 
@@ -171,7 +170,7 @@ module Macinbox
171
170
  EOF
172
171
 
173
172
  prl_convert = "#{@parallels_app}/Contents/MacOS/prl_convert"
174
- task_opts = @debug ? {} : { :out => File::NULL }
173
+ task_opts = $verbose ? {} : { :out => File::NULL }
175
174
  Task.run %W[ #{prl_convert} #{@temp_dir}/macinbox.vmdk --allow-no-os --dst=#{@temp_dir} ] + [task_opts]
176
175
  @disk.eject
177
176
  end
@@ -18,6 +18,7 @@ module Macinbox
18
18
  @output_path = opts[:image_path] or raise ArgumentError.new(":image_path not specified")
19
19
  @vmware_fusion_app = opts[:vmware_path]
20
20
  @parallels_app = opts[:parallels_path]
21
+ @user_script = opts[:user_script]
21
22
 
22
23
  @disk_size = opts[:disk_size] or raise ArgumentError.new(":disk_size not specified")
23
24
  @fstype = opts[:fstype] or raise ArgumentError.new(":fstype not specified")
@@ -31,7 +32,6 @@ module Macinbox
31
32
  @hidpi = opts[:hidpi]
32
33
 
33
34
  @collector = opts[:collector] or raise ArgumentError.new(":collector not specified")
34
- @debug = opts[:debug]
35
35
 
36
36
  raise Macinbox::Error.new("Installer app not found") unless File.exist? @installer_app
37
37
 
@@ -52,6 +52,7 @@ module Macinbox
52
52
  enable_passwordless_sudo
53
53
  enable_sshd
54
54
  enable_hidpi
55
+ run_user_script
55
56
  save_image
56
57
  end
57
58
 
@@ -69,7 +70,7 @@ module Macinbox
69
70
  def create_wrapper_image
70
71
  Logger.info "Creating and attaching wrapper disk image..." do
71
72
  @wrapper_image = "#{@temp_dir}/wrapper.dmg"
72
- @wrapper_disk = VirtualDisk.new(@wrapper_image, @debug)
73
+ @wrapper_disk = VirtualDisk.new(@wrapper_image)
73
74
  @collector.on_cleanup { @wrapper_disk.detach! }
74
75
  @wrapper_disk.create_from_folder(@installer_app)
75
76
  @wrapper_disk.attach
@@ -81,7 +82,7 @@ module Macinbox
81
82
  def create_scratch_image
82
83
  Logger.info "Creating and attaching a new blank disk image..." do
83
84
  @scratch_image = "#{@temp_dir}/scratch.sparseimage"
84
- @scratch_disk = VirtualDisk.new(@scratch_image, @debug)
85
+ @scratch_disk = VirtualDisk.new(@scratch_image)
85
86
  @collector.on_cleanup { @scratch_disk.detach! }
86
87
  @scratch_mountpoint = "#{@temp_dir}/scratch_mountpoint"
87
88
  FileUtils.mkdir @scratch_mountpoint
@@ -97,7 +98,7 @@ module Macinbox
97
98
  install_info_plist = "#{@installer_app}/Contents/SharedSupport/InstallInfo.plist"
98
99
  Task.run %W[ /usr/bin/touch #{@scratch_mountpoint}/.macinbox ]
99
100
  cmd = %W[ /usr/sbin/installer -verboseR -dumplog -pkg #{install_info_plist} -target #{@scratch_mountpoint} ]
100
- opts = @debug ? {} : { :err => [:child, :out] }
101
+ opts = $verbose ? {} : { :err => [:child, :out] }
101
102
  Task.run_with_progress activity, cmd, opts do |line|
102
103
  /^installer:%(.*)$/.match(line)[1].to_f rescue nil
103
104
  end
@@ -190,12 +191,11 @@ module Macinbox
190
191
  def enable_sshd
191
192
  Logger.info "Enabling sshd..." do
192
193
  scratch_launchd_disabled_plist = "#{@scratch_mountpoint}/private/var/db/com.apple.xpc.launchd/disabled.plist"
193
- opts = @debug ? {} : { :out => File::NULL }
194
+ opts = $verbose ? {} : { :out => File::NULL }
194
195
  Task.run %W[ /usr/libexec/PlistBuddy -c #{'Add :com.openssh.sshd bool False'} #{scratch_launchd_disabled_plist} ] + [opts]
195
196
  end
196
197
  end
197
198
 
198
-
199
199
  def enable_hidpi
200
200
  if @hidpi
201
201
  Logger.info "Enabling HiDPI resolutions..." do
@@ -214,9 +214,17 @@ module Macinbox
214
214
  end
215
215
  end
216
216
 
217
+ def run_user_script
218
+ if @user_script
219
+ Logger.info "Running user script..." do
220
+ Task.run %W[ #{@user_script} #{@scratch_mountpoint} ]
221
+ end
222
+ end
223
+ end
224
+
217
225
  def save_image
218
226
  Logger.info "Saving the image..." do
219
- @scratch_disk.detach
227
+ @scratch_disk.eject
220
228
  FileUtils.chown ENV["SUDO_USER"], nil, @scratch_image
221
229
  FileUtils.mv @scratch_image, @output_path
222
230
  end
@@ -18,7 +18,6 @@ module Macinbox
18
18
  @output_path = opts[:vdi_path] or raise ArgumentError.new(":vdi_path not specified")
19
19
 
20
20
  @collector = opts[:collector] or raise ArgumentError.new(":collector not specified")
21
- @debug = opts[:debug]
22
21
 
23
22
  raise Macinbox::Error.new("input image not found") unless File.exist? @input_image
24
23
  end
@@ -46,7 +45,7 @@ module Macinbox
46
45
 
47
46
  def attach_image
48
47
  Logger.info "Attaching the image..." do
49
- @disk = VirtualDisk.new(@image, @debug)
48
+ @disk = VirtualDisk.new(@image)
50
49
  @collector.on_cleanup { @disk.detach! }
51
50
  @disk.attach
52
51
  end
@@ -80,7 +79,7 @@ module Macinbox
80
79
 
81
80
  def convert_image
82
81
  Logger.info "Converting the image to VDI format..." do
83
- task_opts = @debug ? {} : { :out => File::NULL }
82
+ task_opts = $verbose ? {} : { :out => File::NULL }
84
83
  Task.run %W[ VBoxManage convertfromraw #{@disk.device} #{@temp_dir}/macinbox.vdi --format VDI ] + [task_opts]
85
84
  end
86
85
  end
@@ -20,7 +20,6 @@ module Macinbox
20
20
  @use_qemu = opts[:use_qemu]
21
21
 
22
22
  @collector = opts[:collector] or raise ArgumentError.new(":collector not specified")
23
- @debug = opts[:debug]
24
23
 
25
24
  raise Macinbox::Error.new("input image not found") unless File.exist? @input_image
26
25
  raise Macinbox::Error.new("VMware Fusion not found") unless File.exist? @vmware_fusion_app
@@ -55,7 +54,7 @@ module Macinbox
55
54
 
56
55
  def attach_image
57
56
  Logger.info "Attaching the image..." do
58
- @disk = VirtualDisk.new(@image, @debug)
57
+ @disk = VirtualDisk.new(@image)
59
58
  @collector.on_cleanup { @disk.detach! }
60
59
  @image_mountpoint = "#{@temp_dir}/image_mountpoint"
61
60
  FileUtils.mkdir @image_mountpoint
@@ -73,16 +72,16 @@ module Macinbox
73
72
  bundle_short_version = Task.backtick %W[ defaults read #{"/Applications/VMware Fusion.app/Contents/Info.plist"} CFBundleShortVersionString ]
74
73
  darwin_iso_url = "http://softwareupdate.vmware.com/cds/vmw-desktop/fusion/#{bundle_short_version}/#{bundle_version}/packages/com.vmware.fusion.tools.darwin.zip.tar"
75
74
  Dir.chdir(@temp_dir) do
76
- Task.run %W[ /usr/bin/curl #{darwin_iso_url} -O ] + (@debug ? [] : %W[ -s -S ])
75
+ Task.run %W[ /usr/bin/curl #{darwin_iso_url} -O ] + ($verbose ? [] : %W[ -s -S ])
77
76
  Task.run %W[ /usr/bin/tar -xf com.vmware.fusion.tools.darwin.zip.tar com.vmware.fusion.tools.darwin.zip ]
78
- Task.run %W[ /usr/bin/unzip ] + (@debug ? [] : %W[ -qq ]) + %W[ com.vmware.fusion.tools.darwin.zip payload/darwin.iso ]
77
+ Task.run %W[ /usr/bin/unzip ] + ($verbose ? [] : %W[ -qq ]) + %W[ com.vmware.fusion.tools.darwin.zip payload/darwin.iso ]
79
78
  end
80
79
  tools_image = "#{@temp_dir}/payload/darwin.iso"
81
80
  end
82
81
  end
83
82
 
84
83
  Logger.info "Installing the VMware Tools..." do
85
- tools_disk = VirtualDisk.new(tools_image, @debug)
84
+ tools_disk = VirtualDisk.new(tools_image)
86
85
  @collector.on_cleanup { tools_disk.detach! }
87
86
  tools_mountpoint = "#{@temp_dir}/tools_mountpoint"
88
87
  FileUtils.mkdir tools_mountpoint
@@ -102,17 +101,26 @@ module Macinbox
102
101
  def set_spc_kextpolicy
103
102
  Logger.info "Setting the KextPolicy to allow loading the VMware kernel extensions..." do
104
103
  image_spc_kextpolicy = "#{@image_mountpoint}/private/var/db/SystemPolicyConfiguration/KextPolicy"
104
+ unless File.exist? image_spc_kextpolicy
105
+ Task.run_with_input %W[ /usr/bin/sqlite3 #{image_spc_kextpolicy} ] do |pipe|
106
+ pipe.write <<~EOF
107
+ PRAGMA foreign_keys=OFF;
108
+ BEGIN TRANSACTION;
109
+ CREATE TABLE kext_load_history_v3 ( path TEXT PRIMARY KEY, team_id TEXT, bundle_id TEXT, boot_uuid TEXT, created_at TEXT, last_seen TEXT, flags INTEGER );
110
+ CREATE TABLE kext_policy ( team_id TEXT, bundle_id TEXT, allowed BOOLEAN, developer_name TEXT, flags INTEGER, PRIMARY KEY (team_id, bundle_id) );
111
+ CREATE TABLE kext_policy_mdm ( team_id TEXT, bundle_id TEXT, allowed BOOLEAN, payload_uuid TEXT, PRIMARY KEY (team_id, bundle_id) );
112
+ CREATE TABLE settings ( name TEXT, value TEXT, PRIMARY KEY (name) );
113
+ COMMIT;
114
+ EOF
115
+ end
116
+ end
105
117
  Task.run_with_input %W[ /usr/bin/sqlite3 #{image_spc_kextpolicy} ] do |pipe|
106
118
  pipe.write <<~EOF
107
119
  PRAGMA foreign_keys=OFF;
108
120
  BEGIN TRANSACTION;
109
- CREATE TABLE kext_load_history_v3 ( path TEXT PRIMARY KEY, team_id TEXT, bundle_id TEXT, boot_uuid TEXT, created_at TEXT, last_seen TEXT, flags INTEGER );
110
- CREATE TABLE kext_policy ( team_id TEXT, bundle_id TEXT, allowed BOOLEAN, developer_name TEXT, flags INTEGER, PRIMARY KEY (team_id, bundle_id) );
111
- INSERT INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.VMwareGfx',1,'VMware, Inc.',1);
112
- INSERT INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.vmmemctl',1,'VMware, Inc.',1);
113
- INSERT INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.vmhgfs',1,'VMware, Inc.',1);
114
- CREATE TABLE kext_policy_mdm ( team_id TEXT, bundle_id TEXT, allowed BOOLEAN, payload_uuid TEXT, PRIMARY KEY (team_id, bundle_id) );
115
- CREATE TABLE settings ( name TEXT, value TEXT, PRIMARY KEY (name) );
121
+ INSERT OR REPLACE INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.VMwareGfx',1,'VMware, Inc.',1);
122
+ INSERT OR REPLACE INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.vmmemctl',1,'VMware, Inc.',1);
123
+ INSERT OR REPLACE INTO kext_policy VALUES('EG7KH642X6','com.vmware.kext.vmhgfs',1,'VMware, Inc.',1);
116
124
  COMMIT;
117
125
  EOF
118
126
  end
@@ -130,7 +138,7 @@ module Macinbox
130
138
  Task.run %W[ /usr/local/bin/qemu-img convert -f dmg -O vmdk #{@temp_dir}/macinbox.dmg #{@temp_dir}/macinbox.vmdk ]
131
139
  else
132
140
  @disk.attach
133
- task_opts = @debug ? {} : { :out => File::NULL }
141
+ task_opts = $verbose ? {} : { :out => File::NULL }
134
142
  rawdiskCreator = "#{@vmware_fusion_app}/Contents/Library/vmware-rawdiskCreator"
135
143
  vdiskmanager = "#{@vmware_fusion_app}/Contents/Library/vmware-vdiskmanager"
136
144
  Dir.chdir(@temp_dir) do
@@ -18,7 +18,6 @@ module Macinbox
18
18
  @boxes_dir = opts[:boxes_dir] or raise ArgumentError.new(":boxes_dir not specified")
19
19
 
20
20
  @box_version = opts[:macos_version]
21
- @debug = opts[:debug]
22
21
 
23
22
  raise Macinbox::Error.new("box not found: #{@input_box}") unless File.exist? @input_box
24
23
  raise Macinbox::Error.new("boxes directory not found: #{@boxes_dir}") unless File.exist? @boxes_dir
@@ -30,7 +30,7 @@ module Macinbox
30
30
 
31
31
  check_for_sudo_root
32
32
 
33
- collector = Collector.new(preserve_temp_dirs: @options[:debug])
33
+ collector = Collector.new(preserve_temp_dirs: $debug)
34
34
 
35
35
  collector.on_cleanup do
36
36
  STDERR.print TTY::Color::RESET
@@ -42,7 +42,7 @@ module Macinbox
42
42
  raise Macinbox::Error.new("Installer disk image not found: #{@options[:installer_dmg]}")
43
43
  end
44
44
  Logger.info "Attaching installer disk image..."
45
- installer_disk = VirtualDisk.new(@options[:installer_dmg], @options[:debug])
45
+ installer_disk = VirtualDisk.new(@options[:installer_dmg])
46
46
  collector.on_cleanup { installer_disk.detach! }
47
47
  installer_disk.attach
48
48
  installer_disk.mount
@@ -24,6 +24,7 @@ module Macinbox
24
24
  :fullscreen => true,
25
25
  :gui => true,
26
26
  :use_qemu => false,
27
+ :verbose => false,
27
28
  :debug => false,
28
29
  }
29
30
 
@@ -45,10 +46,11 @@ module Macinbox
45
46
  o.on('-f', '--full NAME', 'Full name of the user (default: Vagrant)') { |v| @options[:full_name] = v }
46
47
  o.on('-p', '--password PASSWORD', 'Password of the user (default: vagrant)') { |v| @options[:password] = v }
47
48
  o.separator ''
48
- o.on( '--installer PATH', 'Path to the macOS installer app') { |v| @options[:installer_path] = v }
49
- o.on( '--installer-dmg PATH', 'Path to a macOS installer app disk image') { |v| @options[:installer_dmg] = v }
50
- o.on( '--vmware PATH', 'Path to the VMware Fusion app') { |v| @options[:vmware_path] = v }
51
- o.on( '--parallels PATH', 'Path to the Parallels Desktop app') { |v| @options[:parallels_path] = v }
49
+ o.on( '--installer PATH', 'Path to the macOS installer app') { |v| @options[:installer_path] = File.absolute_path(v) }
50
+ o.on( '--installer-dmg PATH', 'Path to a macOS installer app disk image') { |v| @options[:installer_dmg] = File.absolute_path(v) }
51
+ o.on( '--vmware PATH', 'Path to the VMware Fusion app') { |v| @options[:vmware_path] = File.absolute_path(v) }
52
+ o.on( '--parallels PATH', 'Path to the Parallels Desktop app') { |v| @options[:parallels_path] = File.absolute_path(v) }
53
+ o.on( '--user-script PATH', 'Path to user script') { |v| @options[:user_script] = File.absolute_path(v) }
52
54
  o.separator ''
53
55
  o.on( '--no-auto-login', 'Disable auto login') { |v| @options[:auto_login] = v }
54
56
  o.on( '--no-skip-mini-buddy', 'Show the mini buddy on first login') { |v| @options[:skip_mini_buddy] = v }
@@ -58,7 +60,8 @@ module Macinbox
58
60
  o.separator ''
59
61
  o.on( '--use-qemu', 'Use qemu-img (vmware_desktop only)') { |v| @options[:use_qemu] = v }
60
62
  o.separator ''
61
- o.on( '--debug', 'Enable debug mode') { |v| @options[:debug] = v }
63
+ o.on( '--verbose', 'Enable verbose mode') { |v| $verbose = v }
64
+ o.on( '--debug', 'Enable debug mode') { |v| $debug = $verbose = v }
62
65
  o.separator ''
63
66
  o.on('-v', '--version') { puts "macinbox #{Macinbox::VERSION}"; exit }
64
67
  o.on('-h', '--help') { puts o; exit }
@@ -2,15 +2,19 @@ require 'macinbox/error'
2
2
  require 'macinbox/logger'
3
3
  require 'macinbox/tty'
4
4
 
5
+ require 'shellwords'
6
+
5
7
  module Macinbox
6
8
 
7
9
  class Task
8
10
 
9
11
  def self.run(cmd)
12
+ Logger.info "Running command: #{Shellwords.join(cmd)}" if $verbose
10
13
  system(*cmd) or raise Macinbox::Error.new("#{cmd.slice(0)} failed with non-zero exit code: #{$? >> 8}")
11
14
  end
12
15
 
13
16
  def self.run_as_sudo_user(cmd)
17
+ Logger.info "Running command: sudo -u #{ENV["SUDO_USER"]} #{Shellwords.join(cmd)}" if $verbose
14
18
  system "sudo", "-u", ENV["SUDO_USER"], *cmd or raise Macinbox::Error.new("#{cmd.slice(0)} failed with non-zero exit code: #{$?.to_i}")
15
19
  end
16
20
 
@@ -30,13 +34,18 @@ module Macinbox
30
34
  header + bar
31
35
  end
32
36
 
37
+ def self.print_progress_bar(io, activity, percent_done)
38
+ io.print TTY::Line::CLEAR + TTY::Color::GREEN + progress_bar(activity, percent_done) + TTY::Color::RESET if io.isatty
39
+ end
40
+
33
41
  def self.run_with_progress(activity, cmd, opts={})
34
42
  STDERR.print TTY::Cursor::INVISIBLE
35
- STDERR.print TTY::Line::CLEAR + TTY::Color::GREEN + progress_bar(activity, 0.0) + TTY::Color::RESET
43
+ print_progress_bar(STDERR, activity, 0.0)
44
+ Logger.info "Running command: #{Shellwords.join(cmd)}" if $verbose
36
45
  IO.popen cmd, opts do |pipe|
37
46
  pipe.each_line do |line|
38
47
  percent = yield line
39
- STDERR.print TTY::Line::CLEAR + TTY::Color::GREEN + progress_bar(activity, percent) + TTY::Color::RESET if percent
48
+ print_progress_bar(STDERR, activity, percent) if percent
40
49
  end
41
50
  end
42
51
  STDERR.puts TTY::Cursor::NORMAL
@@ -49,14 +58,14 @@ module Macinbox
49
58
  total_size = File.size(source)
50
59
  last_percent_done = -1
51
60
  STDERR.print TTY::Cursor::INVISIBLE
52
- STDERR.print TTY::Line::CLEAR + TTY::Color::GREEN + progress_bar(activity, 0.0) + TTY::Color::RESET
61
+ print_progress_bar(STDERR, activity, 0.0)
53
62
  File.open(source) do |file|
54
63
  until eof
55
64
  begin
56
65
  bytes_written += destination.write(file.readpartial(1024*1024))
57
66
  percent_done = ((bytes_written.to_f / total_size.to_f) * 100).round(1)
58
67
  last_percent_done = percent_done
59
- STDERR.print TTY::Line::CLEAR + TTY::Color::GREEN + progress_bar(activity, percent_done) + TTY::Color::RESET
68
+ print_progress_bar(STDERR, activity, percent_done)
60
69
  rescue EOFError
61
70
  eof = true
62
71
  end
@@ -66,10 +75,12 @@ module Macinbox
66
75
  end
67
76
 
68
77
  def self.backtick(cmd)
78
+ Logger.info "Running command: #{Shellwords.join(cmd)}" if $verbose
69
79
  IO.popen(cmd).read.chomp
70
80
  end
71
81
 
72
82
  def self.run_with_input(cmd)
83
+ Logger.info "Running command: #{Shellwords.join(cmd)}" if $verbose
73
84
  IO.popen(cmd, "w") do |pipe|
74
85
  yield pipe
75
86
  end
@@ -1,3 +1,3 @@
1
1
  module Macinbox
2
- VERSION = "3.2.0"
2
+ VERSION = "3.3.0"
3
3
  end
@@ -6,11 +6,10 @@ module Macinbox
6
6
 
7
7
  class VirtualDisk
8
8
 
9
- def initialize(image, debug)
9
+ def initialize(image)
10
10
  @image = image
11
- @debug = debug
12
- @quiet_flag = @debug ? [] : %W[ -quiet ]
13
- @task_opts = @debug ? [] : [{ :out => File::NULL }]
11
+ @quiet_flag = $verbose ? [] : %W[ -quiet ]
12
+ @task_opts = $verbose ? [] : [{ :out => File::NULL }]
14
13
  end
15
14
 
16
15
  def device
@@ -65,27 +64,22 @@ module Macinbox
65
64
  Task.run %W[ /usr/sbin/diskutil unmount #{@efi_device} ] + @task_opts
66
65
  end
67
66
 
68
- def detach
67
+ def eject
69
68
  max_attempts = 5
70
69
  for attempt in 1..max_attempts
71
70
  begin
72
- Logger.info "Detaching the image..." if @debug
73
- Task.run %W[ /usr/bin/hdiutil detach #{@disk_device} ] + @quiet_flag
71
+ quiet = $verbose ? [] : %W[ quiet ]
72
+ Task.run %W[ /usr/sbin/diskutil ] + quiet + %W[ eject #{@disk_device} ] + @task_opts
74
73
  unset_devices
75
74
  break
76
75
  rescue Macinbox::Error => error
77
76
  raise if attempt == max_attempts
78
- Logger.info "#{error.message}. Sleeping and retrying..." if @debug
77
+ Logger.info "Eject failed: #{error.message}. Sleeping and retrying..." if $verbose
79
78
  sleep 15
80
79
  end
81
80
  end
82
81
  end
83
82
 
84
- def eject
85
- Task.run %W[ /usr/sbin/diskutil eject #{@disk_device} ] + @task_opts
86
- unset_devices
87
- end
88
-
89
83
  def detach!
90
84
  return unless @disk_device
91
85
  %x( /usr/bin/hdiutil detach -quiet -force #{@disk_device.shellescape} > /dev/null 2>&1 )
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: macinbox
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.2.0
4
+ version: 3.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Kramer
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-02-02 00:00:00.000000000 Z
11
+ date: 2019-02-27 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler