The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.

NAME

instopt - Download and install software

VERSION

This document describes version 0.012 of instopt (from Perl distribution App-instopt), released on 2019-10-09.

SYNOPSIS

In ~/.config/instopt.conf:

 # if not the default ~/software
 download_dir = /home/ujang/software

 # if not the default /opt
 install_dir = !path ~/opt

 # if not the default /usr/local/bin
 program_dir = !path ~/bin

Then:

 # List all installed software in /opt
 % instopt list-installed
 % instopt list-installed -l

 # List installed versions of a software in /opt
 % instopt list-installed-versions firefox

 # Compare installed versions vs downloaded vs latest, for all installed software
 % instopt compare-versions

 # Download a software (e.g. firefox), will be put in $ARCHIVE/f/firefox/<VERSION>/<ARCH>/
 % instopt download firefox

 # Download all known software
 % instopt download-all

 # List all downloaded software
 % instopt list-downloaded
 % instopt list-downloaded -l

 # List downloaded versions of a software
 % instopt list-downloaded-versions firefox
 % instopt list-downloaded-versions -l firefox

 # Update (download + install) a software in /opt
 % instopt update firefox

 # Update all software in /opt
 % instopt update-all

 # Cleanup installed dir (remove inactive versions)
 % instopt cleanup-install-dir

 # Cleanup download dir (remove older versions)
 % instopt cleanup-download-dir


 # Update program to the latest from CPAN
 % instopt --self-upgrade ; # or -U

DESCRIPTION

STATUS: Early, experimental release. Many things can change without notice.

instopt is an opinionated tool to automate downloading and installing software binaries (by default to /opt, hence the name: "install to /opt"). To describe how it works, I'll describe how I install my software to /opt.

Normally, I depend on the package manager of my OS (Linux distribution) to install software. But some software need to be updated more often. Let's take as example firefox, where the OS version is usually too old for my taste. I'll usually do this:

  1. Go to the Mozilla download page and download the latest firefox binary, let's say firefox-99.1.2.tar.bz2.

  2. Save this file to ~/software/f/firefox/99.1.2/linux-x86_64/, so I can share this with my other laptops and PC, to avoid redownloading the same stuff.

  3. To install, I do the rest of the steps as root. I extract the tarball to /opt/firefox-99.1.2/.

  4. I create (or update) symlink /opt/firefox to point to /opt/firefox-99.1.2.

  5. I create (or update) symlink /usr/local/bin/firefox to /opt/firefox/firefox.

When a new version of Firefox comes out, I do the following:

  1. Go to the Mozilla website. Download the latest Firefox tarball, e.g. firefox-99.1.3.tar.bz2.

  2. Save it to ~/software/f/firefox/99.1.3/linux-x86_64/.

  3. Extract the tarball to /opt/firefox-99.1.3.

  4. Update the symlink /opt/firefox to point to /opt/firefox-99.1.3.

  5. Optionally delete /opt/firefox-99.1.2.

instopt is the tool I wrote to automate the above tasks. Now I only need to do:

 # instopt update firefox

This will download the latest firefox, save the tarball to the appropriate location, extract it to /opt, and create/update the symlinks.

You can customize the install directory (/opt) and the download directory (~/software).

To start using instopt, first install it from CPAN. Also install the catalog module for the software that you want/need, e.g. for firefox Software::Catalog::SW::firefox. This module tells instopt how to find out the latest version, where the download URL is, and so on.

You might also want to create a configuration file ~/.config/instopt.conf containing:

 # if not the default ~/software
 download_dir = /mnt/shared/software

 # if not the default /opt
 install_dir = /usr/local/opt

After that, install away.

SUBCOMMANDS

cleanup-download-dir

Remove older versions of downloaded software.

cleanup-install-dir

Remove inactive versions of installed software.

compare-versions

Compare installed vs downloaded vs latest versions of installed software.

download

Download latest version of one or more software.

download-all

Download latest version of all known software.

list-downloaded

List all downloaded software.

list-downloaded-versions

List all downloaded versions of a software.

list-installed

List all installed software.

list-installed-versions

List all installed versions of a software.

update

Update a software to the latest version.

update-all

Update all installed software.

OPTIONS

* marks required options.

Common options

--config-path=s, -c

Set path to configuration file.

--config-profile=s, -P

Set configuration profile to use.

--debug

Shortcut for --log-level=debug.

--download-dir=s
--format=s

Choose output format, e.g. json, text.

Default value:

 undef
--help, -h, -?

Display help message and exit.

--install-dir=s
--json

Set output format to json.

--log-level=s

Set log level.

--naked-res

When outputing as JSON, strip result envelope.

Default value:

 0

By default, when outputing as JSON, the full enveloped result is returned, e.g.:

    [200,"OK",[1,2,3],{"func.extra"=>4}]

The reason is so you can get the status (1st element), status message (2nd element) as well as result metadata/extra result (4th element) instead of just the result (3rd element). However, sometimes you want just the result, e.g. when you want to pipe the result for more post-processing. In this case you can use `--naked-res` so you just get:

    [1,2,3]
--no-config, -C

Do not use any configuration file.

--no-env

Do not read environment for default options.

--program-dir=s
--quiet

Shortcut for --log-level=error.

--self-upgrade, -U

Update program to latest version from CPAN.

--subcommands

List available subcommands.

--trace

Shortcut for --log-level=trace.

--verbose

Shortcut for --log-level=info.

--version, -v

Display program's version and exit.

Options for subcommand download

--arch=s
--software-or-pattern=s@*

Can be specified multiple times.

--softwares-or-patterns-json=s

See --software-or-pattern.

Options for subcommand download-all

--arch=s

Options for subcommand list-downloaded

--detail, -l

Options for subcommand list-downloaded-versions

--arch=s
--software=s*

Options for subcommand list-installed

--detail, -l

Options for subcommand list-installed-versions

--software=s*

Options for subcommand update

--no-download

Do not download latest version from URL, just find from download dir.

Do not use symlink to create latest version directory, but hard-copy instead.

The default is to use symlink. This will create a symlink to the latest version directory, e.g.:

    firefox -> firefox-69.0.2

Then the program will be symlinked from this directory, e.g.:

    /usr/local/bin/firefox -> /opt/firefox/firefox

Another alternative (when this option is set to false) is to use hardlink. A directory (`firefox`) will be copied from the latest version directory (e.g. `firefox-69.0.2`). Then a file (`firefox/instopt.version`) will be written to contain the version number (`69.0.2`). Then, as usual, the program will be symlinked from this directory, e.g.:

    /usr/local/bin/firefox -> /opt/firefox/firefox

Currently hardlinking is performed using the `cp` command (with the option `-la`), so you need to have this on your system (normally present on all Unix systems).

--software-or-pattern=s@*

Can be specified multiple times.

--softwares-or-patterns-json=s

See --software-or-pattern.

-D

Shortcut for --no-download.

See --no-download.

Options for subcommand update-all

--no-download

Do not download latest version from URL, just find from download dir.

--no-make-latest-dir-as-symlink

Do not use symlink to create latest version directory, but hard-copy instead.

The default is to use symlink. This will create a symlink to the latest version directory, e.g.:

    firefox -> firefox-69.0.2

Then the program will be symlinked from this directory, e.g.:

    /usr/local/bin/firefox -> /opt/firefox/firefox

Another alternative (when this option is set to false) is to use hardlink. A directory (`firefox`) will be copied from the latest version directory (e.g. `firefox-69.0.2`). Then a file (`firefox/instopt.version`) will be written to contain the version number (`69.0.2`). Then, as usual, the program will be symlinked from this directory, e.g.:

    /usr/local/bin/firefox -> /opt/firefox/firefox

Currently hardlinking is performed using the `cp` command (with the option `-la`), so you need to have this on your system (normally present on all Unix systems).

-D

Shortcut for --no-download.

See --no-download.

COMPLETION

This script has shell tab completion capability with support for several shells.

bash

To activate bash completion for this script, put:

 complete -C instopt instopt

in your bash startup (e.g. ~/.bashrc). Your next shell session will then recognize tab completion for the command. Or, you can also directly execute the line above in your shell to activate immediately.

It is recommended, however, that you install modules using cpanm-shcompgen which can activate shell completion for scripts immediately.

tcsh

To activate tcsh completion for this script, put:

 complete instopt 'p/*/`instopt`/'

in your tcsh startup (e.g. ~/.tcshrc). Your next shell session will then recognize tab completion for the command. Or, you can also directly execute the line above in your shell to activate immediately.

It is also recommended to install shcompgen (see above).

other shells

For fish and zsh, install shcompgen as described above.

CONFIGURATION FILE

This script can read configuration files. Configuration files are in the format of IOD, which is basically INI with some extra features.

By default, these names are searched for configuration filenames (can be changed using --config-path): ~/.config/instopt.conf, ~/instopt.conf, or /etc/instopt.conf.

All found files will be read and merged.

To disable searching for configuration files, pass --no-config.

To put configuration for a certain subcommand only, use a section name like [subcommand=NAME] or [SOMESECTION subcommand=NAME].

You can put multiple profiles in a single file by using section names like [profile=SOMENAME] or [SOMESECTION profile=SOMENAME] or [subcommand=SUBCOMMAND_NAME profile=SOMENAME] or [SOMESECTION subcommand=SUBCOMMAND_NAME profile=SOMENAME]. Those sections will only be read if you specify the matching --config-profile SOMENAME.

You can also put configuration for multiple programs inside a single file, and use filter program=NAME in section names, e.g. [program=NAME ...] or [SOMESECTION program=NAME]. The section will then only be used when the reading program matches.

Finally, you can filter a section by environment variable using the filter env=CONDITION in section names. For example if you only want a section to be read if a certain environment variable is true: [env=SOMEVAR ...] or [SOMESECTION env=SOMEVAR ...]. If you only want a section to be read when the value of an environment variable has value equals something: [env=HOSTNAME=blink ...] or [SOMESECTION env=HOSTNAME=blink ...]. If you only want a section to be read when the value of an environment variable does not equal something: [env=HOSTNAME!=blink ...] or [SOMESECTION env=HOSTNAME!=blink ...]. If you only want a section to be read when an environment variable contains something: [env=HOSTNAME*=server ...] or [SOMESECTION env=HOSTNAME*=server ...]. Note that currently due to simplistic parsing, there must not be any whitespace in the value being compared because it marks the beginning of a new section filter or section name.

List of available configuration parameters:

Common for all subcommands

 download_dir (see --download-dir)
 format (see --format)
 install_dir (see --install-dir)
 log_level (see --log-level)
 naked_res (see --naked-res)
 program_dir (see --program-dir)

Configuration for subcommand cleanup-download-dir

Configuration for subcommand cleanup-install-dir

Configuration for subcommand compare-versions

Configuration for subcommand download

 arch (see --arch)
 softwares_or_patterns (see --software-or-pattern)

Configuration for subcommand download-all

 arch (see --arch)

Configuration for subcommand list-downloaded

 detail (see --detail)

Configuration for subcommand list-downloaded-versions

 arch (see --arch)
 software (see --software)

Configuration for subcommand list-installed

 detail (see --detail)

Configuration for subcommand list-installed-versions

 software (see --software)

Configuration for subcommand update

 download (see --no-download)
 make_latest_dir_as_symlink (see --no-make-latest-dir-as-symlink)
 softwares_or_patterns (see --software-or-pattern)

Configuration for subcommand update-all

 download (see --no-download)
 make_latest_dir_as_symlink (see --no-make-latest-dir-as-symlink)

ENVIRONMENT

INSTOPT_OPT => str

Specify additional command-line options.

FILES

~/.config/instopt.conf

~/instopt.conf

/etc/instopt.conf

HOMEPAGE

Please visit the project's homepage at https://metacpan.org/release/App-instopt.

SOURCE

Source repository is at https://github.com/perlancar/perl-App-instopt.

BUGS

Please report any bugs or feature requests on the bugtracker website https://rt.cpan.org/Public/Dist/Display.html?Name=App-instopt

When submitting a bug or request, please include a test-file or a patch to an existing test-file that illustrates the bug or desired feature.

SEE ALSO

swcat from App::swcat

AUTHOR

perlancar <perlancar@cpan.org>

COPYRIGHT AND LICENSE

This software is copyright (c) 2019, 2018 by perlancar@cpan.org.

This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.