Installer

This is a package for installing software on linux.

Ideally, all installation in a "normal" linux distribution should be handled by a package manager, and this simple package is in no way meant to replace this functionality. There are however many cases in which one must install either a highly customized configuration, "bleeding edge" software, or software which is not easily available.

This package was originally created to manage my dotfiles and this is the best (and presumably, by far the most common) use case for this package.

Installation (of Installer.jl itself)

In some contexts simply cloning the package git clone https://gitlab.com/ExpandingMan/Installer.jl may be best.

You can also clone the package with the package manager

Pkg.dev("https://gitlab.com/ExpandingMan/Installer.jl")

Currently the package is not registered and there are no tags.

Note

For the time being, Installer.jl quite deliberately has no dependencies outside of the Julia stdlib. This is to ensure that latency due to compilation is minimized when running it. As solutions for reducing Julia's startup latency improve, I may at some point consider adding useful dependencies.

Usage

Setting Up Directories

Installer.jl expects the locations of a home directory and a directory from which to install configuration files. The following environment variables are relevant:

  • INSTALLER_DOTFILES_DIR: this is a directory that should mirror the structure of your home directory. Configs in this directory (usually dotfiles, but they can be anything) by default get installed to the same relative path in $HOME.
  • INSTALLER_PROGRAMS_DIR: a directory containing Julia source files which provide program install configurations (see below).

If this package is run interactively, i.e. in the Julia REPL, it will prompt the user with various requests to make installation safer and easier.

Getting Started

When used interactively, when the runtime of the package module starts, it will print a helpful message showing available functions.

During interactive use, run

install()

to bring up a selectable list of installable programs. This list will be obtained from the configurations you gave it either with INSTALLER_PROGRAMS_DIR or with addprograms(dir).

This package is also intended to be useful for non-interactive scripts. If the Julia REPL is not running, instead of prompting the user, reasonable defaults will be used. Such usage is not as safe: for example, with the REPL the installer will prompt you before overwriting anything, but if you use it in a script it will overwrite without asking.

The Program Interface

Installation is defined via the Program struct. This is a simple data sctructure providing users the ability to easily specify common installation tasks.

A list of exmaples of configuration definitions can be found here.

An example of an installation config is as follows:

const alacritty = Program(:alacritty,
                          configs=[".config/alacritty/alacritty.yml"],
                          packages=["alacritty"]
                         )

The first argument is the name used to identify the program config. Additionally, Program accepts keyword arguments which are useful for describing common installation tasks. In this example, Insatller.jl will copy the alacritty configuration YAML from $INSTALLER_DOTFILES_DIR/.config/alacritty/alacritty.yml to $HOME/.config/alacritty/alacritty.yml (prompting the user and offering the chance to edit a diff before overwriting, if in interactive mode) and it will attempt to install the package manager package alacritty (this will be skipped if not sudo, since package managers require sudo to run).

Available keyword arguments are:

  • configs (Vector{String}): Config files to be copied from $INSTALLER_DOTFILES_DIR to the same relative location in $HOME. When used in interactive mode, you will be prompted whether you'd like to overwrite or edit the diff.
  • downloads (Vector{Download}): Specifies downloads from URL's to their target, and whether the target should be made executable.
  • repos (Vector{GitRepo}): A list of git repos to clone and update.
  • commands (Vector{Cmd}): Specifies shell commands to be executed.
  • packages (Vector{String}): Specifies package manager packages to be installed (will require sudo).
  • aux (Dict{Symbol,Any}): A dict storing any other data that might be needed.

Adding Programs

Program configs should be provided in Julia source files. The files provided will be evaluated directly into the Installer.Programs module. It is recommended that these be defined as a const with the same name as the first argument of Program. These can be defined in as many separate files as the user would like.

To add all Julia source code files in a directory to Installer.Programs set the value of the environment variable INSTALLER_PROGRAMS_DIR to the chosen directory or call addprograms(dir).

Custom Installation Steps

Sometimes installation steps are required which are hard to describe in simple lists. For these cases, the aux function can be defined to run arbitrary blocks of code. This function is run on the sole argument p::Program{name} where name is a Symbol which designates the program. See, for example, the following aux method

function aux(p::Program{:neovim})
    # get AppImage unless FUSE is unavailable
    if I.hasfuse()
        download(Download("https://github.com/neovim/neovim/releases/download/nightly/nvim.appimage",
                          "sbin/nvim", true))
    else
        I.pminstall("neovim")  # installation via package manager
    end

    I.installconfig(".config/nvim/init.vim")

    # we run this here to make sure that `which nvim` is evaluated *last*
    nvim = String(readchomp(`which nvim`))
    I.runcommand(Cmd([nvim, "-c", "PlugInstall", "-c", "UpdateRemotePlugins", "-c", "qa", "--headless"]))
end

As the function is evaluated in the Programs submodule, functions from Installer must be qualified with either Installer or the alias I, as seen above.

It is recommended that functions from Installer be used when defining aux methods, as these provide helpful utility features such as prompts when used interactively, however, of course you can put anything in aux you want. Additionally, you can put anything in the program soruce files you want that does not conflict with existing functionality.

The Download Struct

Download is a struct provided to let users easily specify where something should be downloaded from and where it should be downloaded to, as well as whether the donwloaded files should be made execeutable. For example

Download("https://github.com/neovim/neovim/releases/download/nightly/nvim.appimage",
         "sbin/nvim", true)

can be used to download the binaries from the URL provided to the file $HOME/sbin/nvim, after which it will be made executable.