Module: Echoes::Installer
- Defined in:
- lib/echoes/installer.rb
Overview
Puts a thin wrapper Echoes.app / EchoesEmbed.app into ~/Applications/ so the user can launch echoes from Spotlight, Dock, or Cmd-Space without digging into the gem’s install path. The wrapper’s only job is to exec into the real launcher inside the gem — the gem’s launcher already does all the interesting work (arch forcing on Apple Silicon, Ruby probing, $LOAD_PATH bootstrap).
The gem path is baked into the wrapper at install time. After ‘gem update echoes` the user should re-run `echoes install` to refresh the shortcut to the new gem location.
Constant Summary collapse
- USER_APPS_DIR =
File.('~/Applications')
- BUNDLES =
%w[Echoes.app EchoesEmbed.app].freeze
Class Method Summary collapse
- .default_source_root ⇒ Object
-
.install(source_root: default_source_root, target_dir: USER_APPS_DIR) ⇒ Object
‘source_root` is the directory containing the .app bundles — normally the gem’s own root, computed from this file’s path.
- .uninstall(target_dir: USER_APPS_DIR) ⇒ Object
- .write_wrapper(source_bundle, target_bundle) ⇒ Object
Class Method Details
.default_source_root ⇒ Object
68 69 70 71 72 |
# File 'lib/echoes/installer.rb', line 68 def default_source_root # File is at <gem-root>/lib/echoes/installer.rb; two `..`s land # at the gem root where Echoes.app / EchoesEmbed.app live. File.('../..', __dir__) end |
.install(source_root: default_source_root, target_dir: USER_APPS_DIR) ⇒ Object
‘source_root` is the directory containing the .app bundles —normally the gem’s own root, computed from this file’s path. Overridable for tests.
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/echoes/installer.rb', line 26 def install(source_root: default_source_root, target_dir: USER_APPS_DIR) FileUtils.mkdir_p(target_dir) installed = [] BUNDLES.each do |bundle| source = File.join(source_root, bundle) unless Dir.exist?(source) warn "echoes install: #{bundle} not found at #{source} (skipping)" next end target = File.join(target_dir, bundle) write_wrapper(source, target) installed << target end if installed.empty? puts 'echoes install: nothing to do.' else puts 'Installed:' installed.each { |t| puts " #{t}" } puts puts 'Re-run `echoes install` after `gem update echoes` to refresh the shortcuts.' end installed end |
.uninstall(target_dir: USER_APPS_DIR) ⇒ Object
52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/echoes/installer.rb', line 52 def uninstall(target_dir: USER_APPS_DIR) removed = [] BUNDLES.each do |bundle| target = File.join(target_dir, bundle) next unless Dir.exist?(target) FileUtils.remove_entry(target) removed << target end if removed.empty? puts 'echoes uninstall: nothing to remove.' else removed.each { |t| puts "Removed #{t}" } end removed end |
.write_wrapper(source_bundle, target_bundle) ⇒ Object
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 |
# File 'lib/echoes/installer.rb', line 74 def write_wrapper(source_bundle, target_bundle) bundle_name = File.basename(target_bundle) executable = bundle_name.delete_suffix('.app') FileUtils.mkdir_p(File.join(target_bundle, 'Contents', 'MacOS')) source_plist = File.join(source_bundle, 'Contents', 'Info.plist') if File.exist?(source_plist) FileUtils.cp(source_plist, File.join(target_bundle, 'Contents', 'Info.plist')) end script_path = File.join(target_bundle, 'Contents', 'MacOS', executable) File.write(script_path, <<~SHELL) #!/bin/bash # Auto-generated by `echoes install`. Re-run after `gem update # echoes` so this points at the current installed location. exec "#{source_bundle}/Contents/MacOS/#{executable}" SHELL File.chmod(0o755, script_path) end |