imagineerThat
imagineerThat

Reputation: 5553

MacPorts and HomeBrew: Can I install multiple packages from a file or list?

Surprised I couldn't find much information about this. I'm trying to create a list/file of all the ports and recipes I have installed and repopulate them on another Macbook. Is this possible without too much fuss?

ie. python pip has a feature where you can install from a requirements file that lists all the packages and their versions you want. pip install -r requirementsfile.

Upvotes: 1

Views: 1746

Answers (3)

0 _
0 _

Reputation: 11464

The port program of MacPorts can read files of MacPorts commands, for example:

> cat cmdfile.txt
install git
install vim

> sudo port -F cmdfile.txt
--->  Computing dependencies for git
...
--->  Computing dependencies for vim
...
...

The option -F passes a "command file":

> port -h
Usage: port
        [-bcdfknNopqRstuvy] [-D portdir|portname] [-F cmdfile] action [actionflags]
        [[portname|pseudo-portname|port-url] [@version] [+-variant]... [option=value]...]...

"port help" or "man 1 port" for more information.

Running portf

It turns out that MacPorts also installs portf, which is a symbolic link to port:

> ls -l /opt/local/bin/portf
lr-xr-xr-x  1 root  admin  4 Jun 29 13:25 /opt/local/bin/portf -> port

and is equivalent to running port -F:

> sudo portf cmdfile.txt
--->  Computing dependencies for git
...
--->  Computing dependencies for vim
...

Specifying multiple package names per install command

Note that port install accepts multiple package names. Specifying multiple package names results in faster execution, because scanning of binaries for linking errors occurs upon completion of each install command (and consumes a nonnegligible amount of time). For example:

> cat cmdfile.txt
install git vim

> sudo port -F cmdfile.txt
--->  Computing dependencies for git
...
--->  Computing dependencies for vim
...
--->  Scanning binaries for linking errors
...

Installing packages listed in a requirements file

A quick way to run port install for a list of packages from a file is:

> cat macports_packages.txt
git
vim

> python -c '\
> with open("macports_packages.txt", "rt") as f:
>     text = f.read()
> print("install " + text.replace("\n", " "))' | sudo port
MacPorts 2.7.1
Entering shell mode... ("help" for help, "quit" to quit)
--->  Computing dependencies for git
...
--->  Computing dependencies for vim
...
--->  Scanning binaries for linking errors
...

Details from MacPorts source code

Changelog

Quoting from the MacPorts changelog:

https://github.com/macports/macports-base/blob/9896034b1cf452ee905d61e9fcdee739d4112926/ChangeLog#L2487

Release 1.3 (27-Jul-2006):

https://github.com/macports/macports-base/blob/9896034b1cf452ee905d61e9fcdee739d4112926/ChangeLog#L2584-L2586

  • Add new option -F which specifies a command file to be read and processed. Multiple such options may be given to provide multiple command files. If filename is "-", then stdin is read.

https://github.com/macports/macports-base/blob/9896034b1cf452ee905d61e9fcdee739d4112926/ChangeLog#L2591-L2594

  • If port is invoked as portf, an -F is assumed as an implicit first argument (so the real first argument is taken as a command file to be processed). This should allow the use of a shebang line such as: !/usr/bin/env portf

Code

The most relevant Tcl code is:

https://github.com/macports/macports-base/blob/9896034b1cf452ee905d61e9fcdee739d4112926/src/port/port.tcl#L4628-L4633

                    F {
                        # Name a command file to process
                        advance
                        if {[moreargs]} {
                            lappend ui_options(ports_commandfiles) [lookahead]
                        }

https://github.com/macports/macports-base/blob/9896034b1cf452ee905d61e9fcdee739d4112926/src/port/port.tcl#L5724-L5730

# If we've been invoked as portf, then the first argument is assumed
# to be the name of a command file (i.e., there is an implicit -F
# before any arguments).
if {[moreargs] && $cmdname eq "portf"} {
    lappend ui_options(ports_commandfiles) [lookahead]
    advance
}

https://github.com/macports/macports-base/blob/9896034b1cf452ee905d61e9fcdee739d4112926/src/port/port.tcl#L5835

        set exit_status [process_command_files $ui_options(ports_commandfiles)]

https://github.com/macports/macports-base/blob/9896034b1cf452ee905d61e9fcdee739d4112926/src/port/port.tcl#L4967-L4994

proc process_command_files { filelist } {
    set exit_status 0

    # For each file in the command list, process commands
    # in the file
    foreach file $filelist {
        if {$file eq "-"} {
            set in stdin
        } else {
            if {[catch {set in [open $file]} result]} {
                fatal "Failed to open command file; $result"
            }
        }

        set exit_status [process_command_file $in]

        if {$in ne "stdin"} {
            close $in
        }

        # Exit on first failure unless -p was given
        if {$exit_status != 0 && ![macports::ui_isset ports_processall]} {
            return $exit_status
        }
    }

    return $exit_status
}

Searching

This information in the repository macports-base was located using ag, as follows:

git clone [email protected]:macports/macports-base.git
cd macports-base
ag -u 'command file'

Upvotes: 5

neverpanic
neverpanic

Reputation: 2998

For MacPorts, you can grab a list of ports you manually installed using port installed requested. One way to get those installed again is writing a loop in bash; this might get tricky with variants, though.

Take a look at https://trac.macports.org/wiki/Migration which has basically the same requirements even though moving across boxes isn't covered (you can probably figure out where to switch the boxes). If you want to avoid the manual work, there's a script at the bottom.

Upvotes: 3

mipadi
mipadi

Reputation: 410542

You can use a brewfile with Homebrew.

Upvotes: 1

Related Questions