mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 00:00:16 +02:00
install.sh: install --clone <git-url> [--dir] [--ref]
Clones your own config repository (git@host:owner/repo, https://..., github:owner/repo) into ~/nix-config or --dir and installs it like --flake <dir>. An existing clone of the same repository (any URL form) is reused and, after asking, pulled with --ff-only; another repository, a non-clone or a different branch is refused. A failed clone hints at SSH URLs and gh auth login. Uses SteamOS' git, else Nix's. Checked against local bare repositories through a logging git.
This commit is contained in:
1 parent
6b12d5329f
commit
da01b7e5ac
4 files changed
+186
-8
No files matched your search
@@ -91,6 +91,17 @@ with "Restart once": reboot once. Re-running it just switches
|
||||
again (`--yes` answers every question). Afterwards edit
|
||||
`~/nix-config/home.nix` and switch (see [Usage](#usage)).
|
||||
|
||||
Your own config in a git repository: `--clone <git-url>` clones it into
|
||||
`~/nix-config` (`--dir <path>`, branch `--ref <branch>`) and installs it like
|
||||
`--flake <dir>`; an existing clone of the same repository is reused (after
|
||||
asking, `git pull --ff-only`). URLs: `git@github.com:owner/repo`,
|
||||
`https://...` or `github:owner/repo`; a private repository needs an SSH URL
|
||||
with your key or HTTPS credentials (e.g. `gh auth login`).
|
||||
|
||||
```sh
|
||||
curl -fsSL https://steam-frame-nix.lhns.de | bash -s -- install --clone git@github.com:owner/my-config
|
||||
```
|
||||
|
||||
```sh
|
||||
curl -fsSL https://steam-frame-nix.lhns.de | bash -s -- status # Nix, generation, services
|
||||
curl -fsSL https://steam-frame-nix.lhns.de | bash -s -- uninstall # --keep-nix keeps Nix
|
||||
@@ -440,8 +451,10 @@ versions left: [docs/cleanup.md](docs/cleanup.md).
|
||||
if Nix was already there without flakes;
|
||||
- `~/nix-config` (your configuration, a git repository, from the template
|
||||
with your user name filled into `flake.nix`) and the link
|
||||
`~/.config/home-manager` to it, unless that exists or `--flake` is given;
|
||||
uninstall removes the link, never the configuration;
|
||||
`~/.config/home-manager` to it, unless that exists or `--flake` is given
|
||||
(with `--flake <dir>` or `--clone`, the link to that directory unless it
|
||||
exists); uninstall removes the link, never the configuration (a clone
|
||||
included);
|
||||
- dotfiles in Home Manager's way, renamed to `*.hm-backup-<time>` (kept);
|
||||
- `~/.local/state/home-manager`, `~/.local/state/nix` (profiles,
|
||||
generations), `~/.nix-profile`, `~/.nix-defexpr`, `~/.nix-channels`,
|
||||
|
||||
+2
-1
@@ -48,7 +48,8 @@ modules/
|
||||
session.nix switch: outer bus/runtime dir, user services on switch
|
||||
cleanup.nix switch: `cleanup --orphans`; steam-frame-nix-cleanup on PATH
|
||||
cleanup/package.nix build: install.sh as a command (cleanup, steamvr-debugger-arm, restart-check)
|
||||
cleanup/check.nix test: install.sh cleanup and restart-check on fake home/runtime dirs
|
||||
cleanup/check.nix test: install.sh cleanup and restart-check on fake home/runtime dirs,
|
||||
install --clone against local bare repos
|
||||
portal.nix Steam session portal config (session.portalFix)
|
||||
portal/check.nix test: KDE FileChooser on by default, absent when disabled
|
||||
applications-menu.nix applications.menu link for KDE apps (session.applicationsMenu)
|
||||
|
||||
+83
-4
@@ -48,10 +48,17 @@ Nix + Home Manager for SteamOS (Steam Frame, Steam Deck).
|
||||
Usage: install.sh <command> [options]
|
||||
|
||||
Commands:
|
||||
install [--flake <dir-or-flakeref>] [--yes]
|
||||
install [--flake <dir-or-flakeref> | --clone <git-url> [--dir <path>]
|
||||
[--ref <branch>]] [--yes]
|
||||
Install Nix (NixOS nix-installer, steam-deck planner, flakes enabled) if
|
||||
it is missing, then activate a Home Manager configuration:
|
||||
--flake given that flake (a directory or a flake reference)
|
||||
--clone given your config's git repository (git@host:owner/repo,
|
||||
https://..., github:owner/repo), cloned into
|
||||
--dir (default ~/nix-config) on branch --ref,
|
||||
then used like --flake <dir>; an existing clone
|
||||
of the same repository is reused (and pulled
|
||||
with --ff-only after asking)
|
||||
otherwise ~/.config/home-manager
|
||||
neither exists a new config in ~/nix-config from the
|
||||
steam-frame-nix template, linked to
|
||||
@@ -62,7 +69,8 @@ Commands:
|
||||
uninstall [--yes] [--keep-nix]
|
||||
Stop Home Manager's user services, run 'cleanup --all', uninstall Home
|
||||
Manager, uninstall Nix (unless --keep-nix) and remove per-user Nix
|
||||
leftovers. Your configuration directory is never deleted.
|
||||
leftovers. Your configuration directory (also a --clone) is never
|
||||
deleted.
|
||||
|
||||
cleanup [--dry-run] [--quiet] (--all | --orphans [--keep <artifact>]...)
|
||||
Remove what steam-frame-nix (any version) wrote outside the Nix store,
|
||||
@@ -309,16 +317,82 @@ create_config() {
|
||||
info "linked $HM_CONFIG_LINK -> $dir"
|
||||
}
|
||||
|
||||
# git, or Nix's when SteamOS has none (only after ensure_nix).
|
||||
git_any() {
|
||||
if command -v git >/dev/null 2>&1; then git "$@"
|
||||
else nix run nixpkgs#git -- "$@"; fi
|
||||
}
|
||||
|
||||
# git URL for --clone: github:owner/repo -> https://github.com/owner/repo.git
|
||||
clone_url() {
|
||||
case $1 in
|
||||
github:*)
|
||||
[[ ${1#github:} =~ ^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$ ]] \
|
||||
|| die "--clone: expected github:owner/repo, got '$1' (use --ref for a branch)"
|
||||
printf 'https://github.com/%s.git\n' "${1#github:}" ;;
|
||||
*) printf '%s\n' "$1" ;;
|
||||
esac
|
||||
}
|
||||
|
||||
# host/path of a git URL, to compare SSH and HTTPS forms of one repository.
|
||||
repo_id() {
|
||||
local u=$1
|
||||
case $u in
|
||||
*://*) u=${u#*://}; u=${u#*@} ;;
|
||||
*@*:*) u=${u#*@}; u=${u/://} ;;
|
||||
esac
|
||||
u=${u%/}; u=${u%.git}
|
||||
printf '%s\n' "${u,,}"
|
||||
}
|
||||
|
||||
# Clone the config (--clone), or reuse an existing clone of the same repository.
|
||||
clone_config() { # url dir ref
|
||||
local url dir=$2 ref=$3 origin branch
|
||||
url="$(clone_url "$1")"
|
||||
if [[ -e $dir ]] && [[ -n $(ls -A "$dir" 2>/dev/null) ]]; then
|
||||
[[ $(git_any -C "$dir" rev-parse --show-toplevel 2>/dev/null) -ef $dir ]] \
|
||||
&& origin="$(git_any -C "$dir" config --get remote.origin.url)" \
|
||||
|| die "$dir exists and is not a git clone; move it away or pass --dir <path>"
|
||||
[[ $(repo_id "$origin") == "$(repo_id "$url")" ]] \
|
||||
|| die "$dir is a clone of $origin, not $url; move it away or pass --dir <path>"
|
||||
branch="$(git_any -C "$dir" symbolic-ref --short -q HEAD || true)"
|
||||
[[ -z $ref || $branch == "$ref" ]] \
|
||||
|| die "$dir is on ${branch:-a detached HEAD}, not $ref; check out $ref there first"
|
||||
step "Using the existing clone in $dir"
|
||||
if confirm "Update it with 'git pull --ff-only'?"; then
|
||||
git_any -C "$dir" pull --ff-only \
|
||||
|| warn "git pull failed; using $dir as it is"
|
||||
fi
|
||||
return 0
|
||||
fi
|
||||
step "Cloning $url into $dir"
|
||||
mkdir -p "${dir%/*}"
|
||||
git_any clone ${ref:+--branch "$ref"} -- "$url" "$dir" || die "git clone failed. \
|
||||
For a private repository use an SSH URL (git@github.com:owner/repo) with a key \
|
||||
your account knows, or HTTPS credentials (e.g. 'gh auth login')."
|
||||
}
|
||||
|
||||
cmd_install() {
|
||||
local flake='' ref dir=''
|
||||
local flake='' ref dir='' clone='' clone_dir='' clone_ref=''
|
||||
while (( $# )); do
|
||||
case $1 in
|
||||
--flake) [[ $# -ge 2 ]] || die "--flake needs an argument"; flake=$2; shift 2 ;;
|
||||
--clone) [[ $# -ge 2 ]] || die "--clone needs an argument"; clone=$2; shift 2 ;;
|
||||
--dir) [[ $# -ge 2 ]] || die "--dir needs an argument"; clone_dir=$2; shift 2 ;;
|
||||
--ref) [[ $# -ge 2 ]] || die "--ref needs an argument"; clone_ref=$2; shift 2 ;;
|
||||
-y|--yes) ASSUME_YES=1; shift ;;
|
||||
-h|--help) usage; exit 0 ;;
|
||||
*) die "install: unknown option '$1' (see --help)" ;;
|
||||
esac
|
||||
done
|
||||
if [[ -n $clone ]]; then
|
||||
[[ -z $flake ]] || die "install: --clone and --flake exclude each other"
|
||||
clone_url "$clone" >/dev/null
|
||||
clone_dir=${clone_dir:-$DEFAULT_CONFIG_DIR}
|
||||
[[ $clone_dir == /* ]] || clone_dir=$PWD/$clone_dir
|
||||
elif [[ -n $clone_dir || -n $clone_ref ]]; then
|
||||
die "install: --dir and --ref need --clone"
|
||||
fi
|
||||
|
||||
need_not_root
|
||||
check_os
|
||||
@@ -326,6 +400,11 @@ cmd_install() {
|
||||
|
||||
ensure_nix
|
||||
|
||||
if [[ -n $clone ]]; then
|
||||
clone_config "$clone" "$clone_dir" "$clone_ref"
|
||||
flake=$clone_dir
|
||||
fi
|
||||
|
||||
step "Finding the Home Manager configuration"
|
||||
if [[ -n $flake ]]; then
|
||||
if [[ -d ${flake%%#*} ]]; then
|
||||
@@ -1182,7 +1261,7 @@ cmd_uninstall() {
|
||||
cat <<EOF
|
||||
|
||||
Intentionally left in place:
|
||||
- your configuration (e.g. $DEFAULT_CONFIG_DIR)
|
||||
- your configuration (e.g. $DEFAULT_CONFIG_DIR, also when cloned)
|
||||
- files Home Manager renamed to *.hm-backup-<time>
|
||||
- app data, e.g. ~/.local/share/docker, Firefox profiles, and Flatpak apps
|
||||
Log out or reboot so running sessions drop the removed tweaks.
|
||||
|
||||
@@ -3,11 +3,13 @@
|
||||
# aren't ours (left alone), --dry-run changes nothing, a second run changes
|
||||
# nothing, SteamVR running defers the debugger key to a runtime drop-in.
|
||||
# Also `install.sh restart-check` (what waits for a session/SteamVR restart).
|
||||
# Also `install.sh install --clone` (argument parsing and the clone step),
|
||||
# against local bare repositories through a logging git, without network.
|
||||
{ pkgs }:
|
||||
let
|
||||
cleanup = pkgs.callPackage ./package.nix { };
|
||||
in
|
||||
pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq ]; } ''
|
||||
pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq pkgs.git ]; } ''
|
||||
set -euo pipefail
|
||||
fail() { echo "FAIL: $*" >&2; exit 1; }
|
||||
export HOME XDG_RUNTIME_DIR STEAM_FRAME_NIX_RUNTIME_DIR STEAM_FRAME_NIX_SYSTEMCTL
|
||||
@@ -300,5 +302,88 @@ pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq ]; } ''
|
||||
rm -r $U/gamescope-session.service.d $U/steamvr.service.d; : > $root/proc/net/tcp
|
||||
res=$(rc); [ -z "$res" ] || fail "restart-check without the drop-ins: $res"
|
||||
echo "F ok"
|
||||
|
||||
# --- G: install --clone ---
|
||||
INSTALL=${../../install.sh}
|
||||
export GIT_AUTHOR_NAME=t GIT_AUTHOR_EMAIL=t@t GIT_COMMITTER_NAME=t GIT_COMMITTER_EMAIL=t@t
|
||||
fresh g
|
||||
R=$root/remotes; mkdir -p $R
|
||||
for repo in config other; do
|
||||
git init -q -b main $R/src-$repo
|
||||
echo "{ outputs = _: { }; }" > $R/src-$repo/flake.nix
|
||||
git -C $R/src-$repo add -A; git -C $R/src-$repo commit -qm init
|
||||
git -C $R/src-$repo branch dev
|
||||
git clone -q --bare $R/src-$repo $R/$repo.git
|
||||
done
|
||||
# The URL forms reach the bare repositories; a git that logs its arguments.
|
||||
export GIT_CONFIG_GLOBAL=$root/gitconfig GITLOG=$root/gitlog
|
||||
git config --global url."file://$R/config.git".insteadOf https://github.com/owner/config.git
|
||||
git config --global --add url."file://$R/config.git".insteadOf git@github.com:owner/config
|
||||
git config --global url."file://$R/other.git".insteadOf https://example.org/other.git
|
||||
mkdir -p $root/bin
|
||||
printf '#!%s\necho "$*" >> "$GITLOG"\nexec %s "$@"\n' ${pkgs.bash}/bin/bash ${pkgs.git}/bin/git > $root/bin/git
|
||||
chmod +x $root/bin/git
|
||||
PATH=$root/bin:$PATH
|
||||
# sourced: run one function with fresh state
|
||||
sfn() { (. $INSTALL; "$@"); }
|
||||
# install with Nix, curl and home-manager stubbed
|
||||
inst() {
|
||||
: > $GITLOG
|
||||
(. $INSTALL; ASSUME_YES=1; ensure_nix() { :; }; curl() { :; }; hm() { echo "hm $*"; }; cmd_install "$@")
|
||||
}
|
||||
|
||||
# parsing
|
||||
res=$(bash $INSTALL install --clone github:owner/config --flake /x 2>&1) && fail "--clone --flake accepted"
|
||||
has "$res" "--clone and --flake exclude each other"
|
||||
res=$(bash $INSTALL install --dir /x 2>&1) && fail "--dir without --clone accepted"
|
||||
has "$res" "--dir and --ref need --clone"
|
||||
res=$(bash $INSTALL install --clone github:owner/config/dev 2>&1) && fail "github:o/r/x accepted"
|
||||
has "$res" "expected github:owner/repo"
|
||||
res=$(bash $INSTALL install --clone 2>&1) && fail "--clone without URL accepted"
|
||||
[ "$(sfn clone_url github:owner/config)" = https://github.com/owner/config.git ] || fail clone_url
|
||||
[ "$(sfn clone_url git@github.com:owner/config)" = git@github.com:owner/config ] || fail clone_url-ssh
|
||||
[ "$(sfn repo_id git@GitHub.com:owner/config.git)" = "$(sfn repo_id https://github.com/owner/config/)" ] || fail repo_id
|
||||
[ "$(sfn repo_id ssh://git@github.com/owner/config)" = github.com/owner/config ] || fail repo_id-ssh
|
||||
|
||||
# each URL form: the git command, the flake dir, the link
|
||||
for url in github:owner/config https://github.com/owner/config.git git@github.com:owner/config; do
|
||||
rm -rf $HOME/nix-config $HOME/.config/home-manager
|
||||
res=$(inst --clone $url)
|
||||
want=$(sfn clone_url $url)
|
||||
grep -qxF -- "clone -- $want $HOME/nix-config" $GITLOG || fail "$url: git: $(cat $GITLOG)"
|
||||
has "$res" "hm switch --flake $HOME/nix-config -b"
|
||||
[ "$(readlink $HOME/.config/home-manager)" = $HOME/nix-config ] || fail "$url: link"
|
||||
[ "$(git -C $HOME/nix-config branch --show-current)" = main ] || fail "$url: branch"
|
||||
done
|
||||
|
||||
# reuse: same repository in another URL form, pulled (--yes)
|
||||
res=$(inst --clone https://github.com/owner/config.git)
|
||||
has "$res" "Using the existing clone in $HOME/nix-config"
|
||||
grep -qxF -- "-C $HOME/nix-config pull --ff-only" $GITLOG || fail "no pull: $(cat $GITLOG)"
|
||||
! grep -q "^clone" $GITLOG || fail "cloned again"
|
||||
has "$res" "hm switch --flake $HOME/nix-config -b"
|
||||
|
||||
# --dir (relative) and --ref; the existing link stays
|
||||
res=$(cd $HOME && inst --clone github:owner/config --dir cfg --ref dev)
|
||||
grep -qxF -- "clone --branch dev -- https://github.com/owner/config.git $HOME/cfg" $GITLOG || fail "ref: $(cat $GITLOG)"
|
||||
[ "$(git -C $HOME/cfg branch --show-current)" = dev ] || fail "ref branch"
|
||||
has "$res" "hm switch --flake $HOME/cfg -b"
|
||||
[ "$(readlink $HOME/.config/home-manager)" = $HOME/nix-config ] || fail "link replaced"
|
||||
res=$(inst --clone github:owner/config --dir $HOME/cfg --ref main 2>&1) && fail "other branch reused"
|
||||
has "$res" "is on dev, not main"
|
||||
|
||||
# refused: another repository, not a clone, a subdirectory of a clone
|
||||
res=$(inst --clone https://example.org/other.git 2>&1) && fail "other repo reused"
|
||||
has "$res" "is a clone of git@github.com:owner/config, not https://example.org/other.git"
|
||||
mkdir $HOME/plain; echo x > $HOME/plain/x
|
||||
res=$(inst --clone github:owner/config --dir $HOME/plain 2>&1) && fail "plain dir used"
|
||||
has "$res" "is not a git clone"
|
||||
mkdir $HOME/cfg/sub; echo x > $HOME/cfg/sub/x
|
||||
res=$(inst --clone github:owner/config --dir $HOME/cfg/sub 2>&1) && fail "subdir used"
|
||||
has "$res" "is not a git clone"
|
||||
# a failed clone: the hint
|
||||
res=$(inst --clone https://example.org/missing.git --dir $HOME/m 2>&1) && fail "missing repo"
|
||||
has "$res" "gh auth login"
|
||||
echo "G ok"
|
||||
touch $out
|
||||
''
|
||||
Reference in new issue
Block a user