Search code examples
rubymacoshomebrewhomebrew-cask

Homebrew formula - renaming files on install


i have the following homebrew formulaL

class Software < Formula
    desc "Software"
    homepage "https://blabla"
    version "1.6.0"
  
    if OS.mac? && Hardware::CPU.intel?
      url "https://blabla/releases/download/v1.6.0/software-darwin-10.12-amd64"
      sha256 "ce02a97fb95aca9bba44413d4158f5f2c182f5eb2823bedf1400f556bb9b"
    end
  
    if OS.mac? && Hardware::CPU.arm?
      url "https://blabla/releases/download/v1.6.0/software-darwin-10.12-arm64"
      sha256 "1c69849ba82c10d15706d110ae63bd97c387da2a8cf925653e1bb5c6fc"
    end
  
    if OS.linux? && Hardware::CPU.intel?
      url "https://blabla/releases/download/v1.6.0/software-linux-amd64"
      sha256 "9b7245823a60c85e027929b776753848d4fbdaaa333a49ae171684893"
    end
  
    def install
      bin.install "software*" => "software"
    end
  
    test do
      system "#{bin}/software --version"
    end
  end

The problematic part is:

    def install
      bin.install "software*" => "software"
    end

The files that get downloaded depends on which OS a user is on before installation. I want to automatically find the downloaded file (whatever the name is), hence why I am trying to use a regex as bin.install "software"* with a star to find the downloaded file and install it as software

however, I get an error stating software* cannot be found

please how would I rectify this issue?


Solution

  • Some Suggestions (But See Caveats Below)

    Per the Homebrew bin.install documentation, the purpose of bin.install is to rename a file within the formula's location within the Cellar, and the key doesn't seem to accept either a glob or a regex. However, since you have the full power of Ruby available to you in addition to the Homebrew formula DSL, you might consider doing something like the following:

    def install
      binfile_with_extension =
        File.basename(Dir.glob "#{prefix}/bin/software*")
      bin.install binfile_with_extension => "software"
    end
    

    This of course assumes there's only one software-* executable. If there's more than one, then you may need to do something to return value of the glob (which should be an Array) to select the correct one for your architecture.

    Alternatively, rather than renaming the file itself, you may simply want to symlink it so that you aren't changing something the application might expect. The documentation says that you have full access to both FileUtils and the DSL's bin.install_symlink method, so you might consider using some combination of those instead. For example, to create a hardlink in the cellar for your architecture-named file, then symlink it into the correct bin directory using relative symlinks, the following should work:

    def install
      file = Dir.glob("#{prefix}/bin/software*").first
      FileUtils.ln file, "#{prefix}/bin/software"
      bin.install_symlink bin/"software"
    end
    

    There may be better Homebrew-native options for renaming symlinks differently from the file they link to, but I was unable to find one. That doesn't mean one doesn't exist, though.

    Additionally, whether or not hardlinking or symlinking is necessary in the first place depends on the application. Some applications care about the name they are invoked by (think busybox as an example) while others don't. YMMV.

    Caveats

    I'm not currently a Homebrew developer, so there may be other or better ways to do this. Nevertheless, a combination of Ruby globs and the Hombrew DSL features should get you where you want to go.

    Please do note that I haven't tested this myself, so the suggestions above may or may not work without tweaking. I offer it simply as a place to start since I don't think bin.install is intended to do what you want by itself.