|
| 1 | +class Warpclip < Formula |
| 2 | + desc "Remote-to-local clipboard integration for terminal users" |
| 3 | + homepage "https://github.com/mquinnv/warpclip" |
| 4 | + url "https://github.com/mquinnv/warpclip/archive/refs/tags/v2.1.8.tar.gz" |
| 5 | + sha256 "f8c292ded0cb59a615c704d6fda6b713a70c1ab85ccc3dbac49dacf2998706a3" |
| 6 | + license "MIT" |
| 7 | + head "https://github.com/mquinnv/warpclip.git", branch: "main" |
| 8 | + |
| 9 | + livecheck do |
| 10 | + url :stable |
| 11 | + regex(/^v(\d+\.\d+\.\d+)$/i) |
| 12 | + end |
| 13 | + |
| 14 | + depends_on :macos |
| 15 | + depends_on "netcat" |
| 16 | + depends_on "go" => :build |
| 17 | + |
| 18 | + def install |
| 19 | + # Build from Go source with version information |
| 20 | + system "go", "build", |
| 21 | + "-ldflags", "-X main.Version=#{version}", |
| 22 | + "-o", "warpclip", |
| 23 | + "./cmd/warpclip" |
| 24 | + |
| 25 | + system "go", "build", |
| 26 | + "-ldflags", "-X main.Version=#{version}", |
| 27 | + "-o", "warpclipd", |
| 28 | + "./cmd/warpclipd" |
| 29 | + |
| 30 | + # Install the main command-line tool and server daemon |
| 31 | + bin.install "warpclip" |
| 32 | + bin.install "warpclipd" |
| 33 | + |
| 34 | + # Set the proper permissions |
| 35 | + chmod 0755, bin/"warpclip" |
| 36 | + chmod 0755, bin/"warpclipd" |
| 37 | + |
| 38 | + # Install example files to share directory |
| 39 | + share.install "etc/com.user.warpclip.plist" |
| 40 | + share.install "examples/ssh_config" => "warpclip-ssh-config-example" |
| 41 | + end |
| 42 | + |
| 43 | + def post_install |
| 44 | + # Create log files with proper permissions |
| 45 | + ["#{Dir.home}/.warpclip.log", |
| 46 | + "#{Dir.home}/.warpclip.debug.log", |
| 47 | + "#{Dir.home}/.warpclip.out.log", |
| 48 | + "#{Dir.home}/.warpclip.error.log"].each do |f| |
| 49 | + unless File.exist?(f) |
| 50 | + touch f |
| 51 | + chmod 0600, f |
| 52 | + end |
| 53 | + end |
| 54 | + |
| 55 | + # Setup SSH config |
| 56 | + setup_ssh_config |
| 57 | + |
| 58 | + # Print instructions for loading the service |
| 59 | + ohai "WarpClip installation complete. Start the service with:" |
| 60 | + puts " brew services start warpclip" |
| 61 | + end |
| 62 | + |
| 63 | + def setup_ssh_config |
| 64 | + ssh_config_path = "#{Dir.home}/.ssh/config" |
| 65 | + ssh_dir = "#{Dir.home}/.ssh" |
| 66 | + success = true |
| 67 | + |
| 68 | + # First check if RemoteForward is already configured before making any changes |
| 69 | + if File.exist?(ssh_config_path) && File.readable?(ssh_config_path) |
| 70 | + begin |
| 71 | + config_content = File.read(ssh_config_path) |
| 72 | + rescue |
| 73 | + config_content = "" |
| 74 | + end |
| 75 | + if config_content.include?("RemoteForward 9999 localhost:8888") |
| 76 | + ohai "SSH RemoteForward already configured in #{ssh_config_path}" |
| 77 | + return true |
| 78 | + end |
| 79 | + end |
| 80 | + |
| 81 | + # Create .ssh directory if it doesn't exist |
| 82 | + unless Dir.exist?(ssh_dir) |
| 83 | + begin |
| 84 | + mkdir_p ssh_dir |
| 85 | + # Only set permissions on newly created directory |
| 86 | + chmod 0700, ssh_dir |
| 87 | + ohai "Created SSH directory at #{ssh_dir}" |
| 88 | + rescue => e |
| 89 | + opoo "Could not create or set permissions on #{ssh_dir}: #{e.message}" |
| 90 | + opoo "You may need to manually configure SSH forwarding." |
| 91 | + success = false |
| 92 | + end |
| 93 | + end |
| 94 | + |
| 95 | + # Skip further steps if we couldn't set up the directory |
| 96 | + return false unless Dir.exist?(ssh_dir) |
| 97 | + |
| 98 | + # Create config file if it doesn't exist |
| 99 | + unless File.exist?(ssh_config_path) |
| 100 | + begin |
| 101 | + touch ssh_config_path |
| 102 | + chmod 0600, ssh_config_path |
| 103 | + ohai "Created SSH config at #{ssh_config_path}" |
| 104 | + rescue => e |
| 105 | + opoo "Could not create or set permissions on #{ssh_config_path}: #{e.message}" |
| 106 | + opoo "You may need to manually configure SSH forwarding." |
| 107 | + success = false |
| 108 | + end |
| 109 | + end |
| 110 | + |
| 111 | + # Skip if we can't read/write the config file |
| 112 | + return false unless File.readable?(ssh_config_path) |
| 113 | + return false unless File.writable?(ssh_config_path) |
| 114 | + |
| 115 | + # Read current config content |
| 116 | + config_content = "" |
| 117 | + begin |
| 118 | + config_content = File.read(ssh_config_path) |
| 119 | + rescue => e |
| 120 | + opoo "Could not read SSH config: #{e.message}" |
| 121 | + return false |
| 122 | + end |
| 123 | + |
| 124 | + # Check if RemoteForward entry already exists |
| 125 | + if config_content.include?("RemoteForward 9999 localhost:8888") |
| 126 | + ohai "SSH RemoteForward already configured in #{ssh_config_path}" |
| 127 | + return true |
| 128 | + else |
| 129 | + # Back up existing config first |
| 130 | + backup_path = "#{ssh_config_path}.backup-#{Time.now.strftime("%Y%m%d%H%M%S")}" |
| 131 | + begin |
| 132 | + cp ssh_config_path, backup_path |
| 133 | + ohai "Backed up existing SSH config to #{backup_path}" |
| 134 | + rescue => e |
| 135 | + opoo "Could not back up SSH config: #{e.message}. Will continue without backup." |
| 136 | + end |
| 137 | + # Append our configuration |
| 138 | + forward_config = %Q{ |
| 139 | +# WarpClip SSH Configuration |
| 140 | +# Added by Homebrew (#{name}) on #{Time.now.strftime("%Y-%m-%d %H:%M:%S")} |
| 141 | +Host * |
| 142 | + RemoteForward 9999 localhost:8888 |
| 143 | + }.strip |
| 144 | + modified = false |
| 145 | + begin |
| 146 | + File.open(ssh_config_path, "a") do |file| |
| 147 | + file.puts("\n#{forward_config}\n") |
| 148 | + end |
| 149 | + modified = true |
| 150 | + ohai "Added RemoteForward configuration to SSH config" |
| 151 | + rescue => e |
| 152 | + opoo "Could not modify SSH config: #{e.message}" |
| 153 | + opoo "You may need to add the RemoteForward configuration manually:" |
| 154 | + puts " #{forward_config}" |
| 155 | + success = false |
| 156 | + end |
| 157 | + |
| 158 | + # Verify the configuration was actually added |
| 159 | + if modified |
| 160 | + begin |
| 161 | + new_content = File.read(ssh_config_path) |
| 162 | + if new_content.include?("RemoteForward 9999 localhost:8888") |
| 163 | + ohai "Verified SSH RemoteForward configuration was added successfully" |
| 164 | + else |
| 165 | + opoo "Failed to verify SSH config was updated. You may need to add it manually:" |
| 166 | + puts " #{forward_config}" |
| 167 | + success = false |
| 168 | + end |
| 169 | + rescue => e |
| 170 | + opoo "Could not verify SSH config: #{e.message}" |
| 171 | + success = false |
| 172 | + end |
| 173 | + end |
| 174 | + end |
| 175 | + |
| 176 | + if success |
| 177 | + ohai "SSH configuration completed successfully" |
| 178 | + else |
| 179 | + opoo "SSH configuration may not be complete. Check the messages above." |
| 180 | + opoo "WarpClip will still work if you manually configure SSH forwarding with:" |
| 181 | + puts " RemoteForward 9999 localhost:8888" |
| 182 | + end |
| 183 | + # Return true even with warnings - this will allow post-install to continue |
| 184 | + true |
| 185 | + end |
| 186 | + |
| 187 | + # Define the service plist |
| 188 | + service do |
| 189 | + # Run the warpclipd daemon (with built-in localhost-only binding) |
| 190 | + run [opt_bin/"warpclipd"] |
| 191 | + keep_alive true |
| 192 | + |
| 193 | + # Proper logging setup |
| 194 | + log_path "#{Dir.home}/.warpclip.out.log" |
| 195 | + error_log_path "#{Dir.home}/.warpclip.error.log" |
| 196 | + working_dir Dir.home |
| 197 | + |
| 198 | + # Include necessary environment variables |
| 199 | + environment_variables PATH: "#{HOMEBREW_PREFIX}/bin:/usr/bin:/bin:/usr/sbin:/sbin" |
| 200 | + |
| 201 | + # Restart if the process exits for any reason (with delay to prevent rapid restarts) |
| 202 | + restart_delay 5 |
| 203 | + end |
| 204 | + |
| 205 | + def caveats |
| 206 | + <<~EOS |
| 207 | + WarpClip v2.1.3 has been installed. To start the clipboard service: |
| 208 | +
|
| 209 | + brew services start warpclip |
| 210 | +
|
| 211 | + IMPORTANT: WarpClip consists of two components: |
| 212 | + 1. LOCAL COMPONENT (warpclipd): |
| 213 | + • Runs on your Mac and listens for clipboard data |
| 214 | + • Started automatically by Homebrew Services |
| 215 | +
|
| 216 | + 2. REMOTE COMPONENT (warpclip): |
| 217 | + • Needs to be installed on remote servers you connect to |
| 218 | + • Sends data back to your Mac through SSH tunnel |
| 219 | +
|
| 220 | + To use WarpClip on a remote server: |
| 221 | + 1. Install the client script on your remote server: |
| 222 | + #{opt_bin}/warpclip install-remote user@remote-server |
| 223 | +
|
| 224 | + 2. Connect to your remote server with SSH forwarding: |
| 225 | + ssh user@remote-server |
| 226 | + (This works automatically if you use the default SSH config) |
| 227 | +
|
| 228 | + 3. On the remote server, pipe content to warpclip: |
| 229 | + cat remote-file.txt | warpclip |
| 230 | +
|
| 231 | + The content will be copied to your local Mac clipboard! |
| 232 | + Available commands: |
| 233 | +
|
| 234 | + • Copy data to clipboard (on remote server): |
| 235 | + cat file.txt | warpclip |
| 236 | +
|
| 237 | + • Install on a remote server (from local machine): |
| 238 | + warpclip install-remote user@remote-server |
| 239 | +
|
| 240 | + • Show help and usage information: |
| 241 | + warpclip help |
| 242 | +
|
| 243 | + Status and troubleshooting: |
| 244 | + • Check service status: |
| 245 | + brew services info warpclip |
| 246 | + #{opt_bin}/warpclipd status |
| 247 | +
|
| 248 | + • View logs: |
| 249 | + cat ~/.warpclip.log |
| 250 | + cat ~/.warpclip.debug.log |
| 251 | + • Restart service: |
| 252 | + brew services restart warpclip |
| 253 | + EOS |
| 254 | + end |
| 255 | + |
| 256 | + test do |
| 257 | + assert_path_exists "#{opt_bin}/warpclipd" |
| 258 | + assert_path_exists "#{opt_bin}/warpclip" |
| 259 | + |
| 260 | + # Basic syntax check for warpclip |
| 261 | + system opt_bin/"warpclip", "--version" |
| 262 | + |
| 263 | + # Basic syntax check for warpclipd |
| 264 | + begin |
| 265 | + system opt_bin/"warpclipd", "status" |
| 266 | + rescue |
| 267 | + nil |
| 268 | + end |
| 269 | + # Check if the scripts have expected content |
| 270 | + assert_match "WarpClip v#{version}", shell_output("#{opt_bin}/warpclip --version") |
| 271 | + assert_match "warpclipd - WarpClip clipboard daemon", shell_output("head -n 10 #{opt_bin}/warpclipd") |
| 272 | + end |
| 273 | +end |
0 commit comments