Design¶
The pieces¶
https://in-1.cc/ serves a small shell script (view source on this
very site: in-1.cc/rc).
It is a polyglot that works when sourced by bash, zsh or fish, and it
does only three things:
- Clone the in-1 repo to
$TMPDIR/in-1/bootstrap(default/tmp/in-1/bootstrap), at the version the script was published with (so the served endpoint and the code always agree). Do not inherit the installed shell function's state root. - Run
bin/in-1 --env <your-shell> <tools...>from that clone. - Evaluate its output in your current shell.
bin/in-1 is a plain strict-mode bash program; all the real logic
lives there, versioned, testable and shellcheckable.
How installs work¶
in-1 stands on makes, a GNU make
library where every tool has a <tool>.mk file that knows how to
download and locally install that tool (and its host language) on
Linux or macOS. in-1 keeps its own clone of makes at
$IN1_ROOT/makes.
For each requested tool, bin/in-1 resolves the version, then writes a Makefile like:
MAKES-LOCAL-DIR := $PREFIX/share/rust/1.98.0
include $IN1_ROOT/makes/init.mk
include $IN1_ROOT/makes/rust.mk
include $IN1_ROOT/makes/shell.mk
so every (tool, version) installs into its own tree and versions
never collide. It runs make shell CMD=: to install (progress on
stderr), then make -s shell CMD='exec env -0' to capture the
environment make set up for that tool.
Wrappers¶
The captured environment is diffed against in-1's own, isolating the
PATH dirs and variables (like CARGO_HOME) the tool needs. in-1
then writes a wrapper into <prefix>/bin for every command the tool
provides:
#!/usr/bin/env bash
# in-1 wrapper
export CARGO_HOME=$PREFIX/share/rust/1.98.0/cargo
export RUSTUP_HOME=$PREFIX/share/rust/1.98.0/rustup
export PATH=$PREFIX/share/rust/1.98.0/cargo/bin:$PATH
exec $PREFIX/share/rust/1.98.0/cargo/bin/rustc "$@"
The wrapper prepends to the live $PATH (never a frozen snapshot),
so it works from any future shell. The tool's primary command also
gets a <cmd>-<version> wrapper, so pinned versions stay reachable.
<prefix>/bin is the single directory in-1 puts on your PATH, so
which <cmd> is always <prefix>/bin/<cmd> and none of the tool's
own environment leaks into your interactive shell.
Prefix selection¶
All modes share the same install-and-wrap machinery:
- Normally the prefix follows the installed in-1's public bin directory.
Without an installed in-1, it defaults to
${TMPDIR:-/tmp}/in-1. --localselects a persistent prefix, falling back to~/.local.PREFIX=DIRoverrides normal and local defaults.--tempforces the temporary prefix, ignoring inheritedPREFIXand rejecting an explicit prefix argument or--local.
Sourced calls activate PREFIX/bin, man pages and completions in the caller.
The installed in-1's internal clone bin directory never replaces its wrapper
on the caller's PATH.
in-1 never overwrites a file in <prefix>/bin it did not create.
State and installations¶
State defaults to PREFIX/share/in-1/local, independently of installed versions:
PREFIX/bin/ public wrappers
PREFIX/share/<tool>/<version>/ installed tools
IN1_ROOT/makes/ the Makes clone
IN1_ROOT/log/ logs and generated Makefiles
IN1_ROOT/cache/ downloads (IN1_CACHE)
Re-running reuses all of it, so only the first request for a tool and
version is slow. Set IN1_CACHE somewhere persistent to keep
downloads across reboots.
in-1 --reset removes managed tool versions and wrappers, except in-1 itself,
and clears Makes, logs and downloads.
Unrelated files, old nested installations, and external caches are preserved.
Before an install, in-1 fetches both clones, reports if its own clone
is behind its origin, and automatically updates makes when needed.
The one-liner pins a fresh clone to its published version but leaves a
clone that is already on a branch where it is, so after --update you
stay on the latest.
Metadata¶
A tool's primary command, a human "also:" note, and command aliases
(so in-1 cargo installs rust) live in share/tools.mk, a file of
flat make variables in-1 reads directly.
Some tools also need shell-side setup (an alias, a completion hook)
that the wrappers cannot provide. For those, an optional
share/<tool>.{sh,bash,zsh,fish} file is sourced in your shell after
a session install. in-1 itself is the biggest user: it is an
ordinary makes tool (in-1.mk clones the repo), and its extra sources
the .rc of the copy just installed, which is where the in-1 shell
function lives. .rc keeps an IN1_ROOT that is already set, so the
installed copy shares the selected state directory.
A few tools want more in their wrappers than makes provides.
An optional share/<tool>.mk is included in the generated makefile,
so whatever it exports is captured into the wrappers (clojure keeps
~/.clojure and ~/.m2 inside its install this way).
An optional share/<tool>.wrap is a bash snippet copied into the
primary command's wrappers before the exec (jolt and phel start
their REPL under rlwrap when it is available).