mirror of
https://github.com/lhns/steam-frame-nix.git
synced 2026-10-06 04:00:12 +02:00
install --clone: clone with the template's credential helpers
The template now enables git (SteamOS's own, package = null; Home Manager writes its config) with the GitHub CLI's credential helper for github.com and `store` (~/.git-credentials) for other hosts. Without a Home Manager configuration, `install --clone` first creates and activates the template in the target directory, then clones next to it with git's helpers and GIT_TERMINAL_PROMPT=0 (never a password prompt). If that fails with a terminal, it offers `gh auth login` and retries once; otherwise the template stays active and the message says how to continue. After the clone the template is removed, the clone takes its place and Home Manager switches to it. Only a missing (or empty) target or the untouched template is cloned into: create_config marks its configuration with the hash of its files in .git/steam-frame-nix-template. Anything else there is used as it is, so a rerun continues where a run stopped (after a failed switch it just switches); Nix and the template switch (helpers present) are skipped when already done. The origin comparison and the pull are gone.
This commit is contained in:
1 parent
269321ea92
commit
6f163141f5
3 files changed
+307
-85
No files matched your search
+133
-48
@@ -7,7 +7,7 @@
|
||||
# curl -fsSL https://steam-frame-nix.lhns.de | bash -s -- cleanup --all
|
||||
#
|
||||
# Run `install.sh --help` for details. Works from a file or piped into bash
|
||||
# (prompts read from /dev/tty).
|
||||
# (prompts read from /dev/tty; tests: STEAM_FRAME_NIX_TTY).
|
||||
set -euo pipefail
|
||||
|
||||
TEMPLATE="${STEAM_FRAME_NIX_TEMPLATE:-github:lhns/steam-frame-nix}"
|
||||
@@ -28,11 +28,13 @@ USER_NAME="$(id -un)"
|
||||
USER_ID="$(id -u)"
|
||||
OUTER_RUNTIME_DIR="${STEAM_FRAME_NIX_RUNTIME_DIR:-/run/user/$USER_ID}"
|
||||
SFN_PROC="${STEAM_FRAME_NIX_PROC:-/proc}" # tests: a fake /proc
|
||||
SFN_TTY="${STEAM_FRAME_NIX_TTY:-/dev/tty}"
|
||||
# Runtime drop-in for the uninstall (tests: another directory).
|
||||
NIX_MOUNT_DROPIN="${STEAM_FRAME_NIX_SYSTEM_RUNTIME:-/run/systemd/system}/nix.mount.d/50-steam-frame-nix-lazy-unmount.conf"
|
||||
|
||||
ASSUME_YES=0
|
||||
RO_RELOCK=0
|
||||
CLONE_TMP=''
|
||||
|
||||
# --- output -----------------------------------------------------------------
|
||||
|
||||
@@ -59,9 +61,14 @@ Commands:
|
||||
--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)
|
||||
then used like --flake <dir>. Without a Home
|
||||
Manager configuration it activates the template
|
||||
first, so git clones with its credential helpers
|
||||
(gh, ~/.git-credentials); if that fails it offers
|
||||
'gh auth login'. Only a missing directory or the
|
||||
unchanged template is replaced by the clone;
|
||||
anything else there is used as it is (a rerun
|
||||
after a failed switch just switches)
|
||||
otherwise ~/.config/home-manager
|
||||
neither exists a new config in ~/nix-config from the
|
||||
steam-frame-nix template, linked to
|
||||
@@ -119,15 +126,15 @@ EOF
|
||||
|
||||
# --- helpers ----------------------------------------------------------------
|
||||
|
||||
have_tty() { { : </dev/tty; } 2>/dev/null; }
|
||||
have_tty() { { : <"$SFN_TTY"; } 2>/dev/null; }
|
||||
|
||||
confirm() {
|
||||
confirm() { # question [default answer: n|y]
|
||||
(( ASSUME_YES )) && return 0
|
||||
have_tty || die "no terminal to ask \"$1\"; re-run with --yes"
|
||||
local reply=''
|
||||
printf '%s [y/N] ' "$1" >/dev/tty
|
||||
read -r reply </dev/tty || true
|
||||
[[ $reply == [yY]* ]]
|
||||
local reply='' def=${2:-n}
|
||||
printf '%s [%s] ' "$1" "$([[ $def == y ]] && echo Y/n || echo y/N)" >"$SFN_TTY"
|
||||
read -r reply <"$SFN_TTY" || true
|
||||
[[ ${reply:-$def} == [yY]* ]]
|
||||
}
|
||||
|
||||
need_not_root() {
|
||||
@@ -166,7 +173,11 @@ ro_relock() {
|
||||
sudo steamos-readonly enable || warn "could not re-enable it; run: sudo steamos-readonly enable"
|
||||
}
|
||||
|
||||
trap ro_relock EXIT
|
||||
on_exit() {
|
||||
[[ -z $CLONE_TMP ]] || rm -rf -- "$CLONE_TMP" # an unfinished --clone
|
||||
ro_relock
|
||||
}
|
||||
trap on_exit EXIT
|
||||
trap 'exit 130' INT TERM
|
||||
|
||||
# Make nix available in this shell, with flakes enabled for our own calls.
|
||||
@@ -282,7 +293,7 @@ ensure_nix() {
|
||||
step "Checking Nix"
|
||||
load_nix
|
||||
if nix_works; then
|
||||
info "$(nix --version)"
|
||||
info "$(nix --version): installed already"
|
||||
else
|
||||
if [[ -e $NIX_RECEIPT ]]; then
|
||||
warn "Nix is installed ($NIX_RECEIPT) but not working"
|
||||
@@ -315,7 +326,27 @@ set_let() { # file name value
|
||||
sed -i "s|^\( *$name = \)\"[^\"]*\";|\1\"$value\";|" "$file"
|
||||
}
|
||||
|
||||
create_config() {
|
||||
# Marker of a configuration create_config made: the hash of its files, in
|
||||
# .git (never a file of the configuration). `install --clone` replaces
|
||||
# such a configuration while it is unchanged (template_untouched).
|
||||
TEMPLATE_MARK=steam-frame-nix-template
|
||||
|
||||
# Hash of a configuration's files (without .git).
|
||||
config_hash() {
|
||||
(cd "$1" && find . -path ./.git -prune -o ! -type d -print0 | LC_ALL=C sort -z \
|
||||
| xargs -0 -r sha256sum | sha256sum) | cut -d' ' -f1
|
||||
}
|
||||
|
||||
# Whether <dir> is the template as create_config made it: the marker
|
||||
# matches its files, at most one commit.
|
||||
template_untouched() { # dir
|
||||
local m=$1/.git/$TEMPLATE_MARK n
|
||||
[[ -f $m ]] || return 1
|
||||
n="$(git -C "$1" rev-list --count HEAD 2>/dev/null || echo 0)"
|
||||
[[ $(<"$m") == "$(config_hash "$1")" ]] && (( n <= 1 ))
|
||||
}
|
||||
|
||||
create_config() { # dir [question]
|
||||
local dir=$1 system
|
||||
if [[ -e $dir ]] && [[ -n $(ls -A "$dir" 2>/dev/null) ]]; then
|
||||
if [[ -e $dir/flake.nix ]]; then
|
||||
@@ -326,7 +357,7 @@ create_config() {
|
||||
[[ $USER_NAME =~ ^[a-z_][a-z0-9_-]*$ ]] || die "unsupported user name '$USER_NAME' for the template"
|
||||
[[ $HOME =~ ^/[A-Za-z0-9._/-]+$ ]] || die "unsupported home directory '$HOME' for the template"
|
||||
|
||||
confirm "No Home Manager configuration found. Create one in $dir from the steam-frame-nix template?" \
|
||||
confirm "${2:-No Home Manager configuration found. Create one in $dir from the steam-frame-nix template?}" \
|
||||
|| die "aborted; pass --flake <your config> to use an existing one"
|
||||
|
||||
step "Creating a Home Manager configuration in $dir"
|
||||
@@ -344,6 +375,7 @@ create_config() {
|
||||
git -C "$dir" add -A
|
||||
nix flake lock "$dir"
|
||||
git -C "$dir" add flake.lock
|
||||
config_hash "$dir" >"$dir/.git/$TEMPLATE_MARK"
|
||||
else
|
||||
warn "git not found; $dir is used as a plain directory"
|
||||
nix flake lock "$dir"
|
||||
@@ -371,42 +403,99 @@ clone_url() {
|
||||
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,,}"
|
||||
# git with its credential helpers but without asking for a password.
|
||||
git_noprompt() {
|
||||
local -x GIT_TERMINAL_PROMPT=0
|
||||
git_any "$@"
|
||||
}
|
||||
|
||||
# Clone the config (--clone), or reuse an existing clone of the same repository.
|
||||
# Whether git has a credential helper (the template's: gh, store).
|
||||
git_has_helpers() {
|
||||
git_any config --global --get-regexp '^credential\..*helper$' 2>/dev/null \
|
||||
| awk 'NF > 1 { f = 1 } END { exit !f }'
|
||||
}
|
||||
|
||||
# `gh auth login` with gh from the Home Manager profile (the template's),
|
||||
# for an HTTPS URL on github.com and only with a terminal.
|
||||
gh_login() { # url
|
||||
local gh=$HM_PROFILE/home-path/bin/gh
|
||||
[[ $1 == https://github.com/* ]] && have_tty || return 1
|
||||
[[ -x $gh ]] || gh="$(command -v gh)" || return 1
|
||||
confirm "Log in to GitHub now with 'gh auth login'?" y || return 1
|
||||
"$gh" auth login --hostname github.com --git-protocol https <"$SFN_TTY"
|
||||
}
|
||||
|
||||
# --clone: <dir> missing (or empty) or the untouched template gets the clone
|
||||
# of <url>; anything else in <dir> is used as it is (also the clone of an
|
||||
# earlier run whose switch failed). Each step checks whether an earlier run
|
||||
# did it already:
|
||||
# - without a Home Manager configuration (or with the template in <dir>
|
||||
# linked), the template is created in <dir> and activated, so git has
|
||||
# the credential helpers (skipped if they are there);
|
||||
# - <url> is cloned next to <dir> (on failure the template stays active
|
||||
# in <dir>); the template is removed and the clone takes its place.
|
||||
clone_config() { # url dir ref
|
||||
local url dir=$2 ref=$3 origin branch
|
||||
local url dir=$2 ref=$3 tmpl=0 parent link=''
|
||||
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
|
||||
if ! template_untouched "$dir"; then
|
||||
step "$dir already exists and isn't the untouched template: using it as it is (not cloning)"
|
||||
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')."
|
||||
tmpl=1
|
||||
fi
|
||||
|
||||
# The template, for git's credential helpers.
|
||||
if [[ -L $HM_CONFIG_LINK || -e $HM_CONFIG_LINK ]]; then
|
||||
link="$(readlink -f "$HM_CONFIG_LINK" || true)"
|
||||
fi
|
||||
if (( ! tmpl )) && [[ -z $link ]]; then
|
||||
create_config "$dir" "No Home Manager configuration found. First activate the steam-frame-nix template from $dir (git's credential helpers, e.g. 'gh auth login'), then replace it with the clone of $url?"
|
||||
tmpl=1
|
||||
hm_activate "$dir#$USER_NAME" || die "the switch to the template failed (see above); run install --clone again to continue"
|
||||
elif (( tmpl )) && [[ -z $link || $link -ef $dir ]]; then
|
||||
if [[ -z $link ]]; then
|
||||
mkdir -p "${HM_CONFIG_LINK%/*}"
|
||||
ln -s "$dir" "$HM_CONFIG_LINK"
|
||||
info "linked $HM_CONFIG_LINK -> $dir"
|
||||
fi
|
||||
if [[ -n $link ]] && hm_installed && git_has_helpers; then
|
||||
step "The template in $dir is active with git's credential helpers (skipped)"
|
||||
else
|
||||
hm_activate "$dir#$USER_NAME" || die "the switch to the template failed (see above); run install --clone again to continue"
|
||||
fi
|
||||
fi
|
||||
|
||||
parent="$(mkdir -p "${dir%/*}" && cd "${dir%/*}" && pwd)"
|
||||
CLONE_TMP="$(mktemp -d "$parent/.${dir##*/}.clone.XXXXXX")"
|
||||
chmod "$(umask -S)" "$CLONE_TMP"
|
||||
step "Cloning $url"
|
||||
if ! git_noprompt clone ${ref:+--branch "$ref"} -- "$url" "$CLONE_TMP" \
|
||||
&& ! { gh_login "$url" && git_noprompt clone ${ref:+--branch "$ref"} -- "$url" "$CLONE_TMP"; }; then
|
||||
(( tmpl )) && warn "the steam-frame-nix template stays active in $dir; install --clone replaces it while it is unchanged"
|
||||
die "git clone failed. For a private repository log in to GitHub with \
|
||||
'gh auth login' or use an SSH URL (git@github.com:owner/repo) with a key \
|
||||
your account knows, then run install --clone again: it continues where it stopped."
|
||||
fi
|
||||
if (( tmpl )); then
|
||||
template_untouched "$dir" || die "$dir was changed while cloning; the clone is not used"
|
||||
rm -rf -- "$dir"
|
||||
info "removed the template in $dir (only needed for the clone)"
|
||||
elif [[ -d $dir ]]; then
|
||||
rmdir -- "$dir" # empty
|
||||
fi
|
||||
mv -T -- "$CLONE_TMP" "$dir"
|
||||
CLONE_TMP=''
|
||||
info "cloned into $dir"
|
||||
}
|
||||
|
||||
# home-manager switch; files in its way are renamed to *.hm-backup-<time>
|
||||
# (unique per run: Home Manager aborts if a backup from an earlier run exists).
|
||||
hm_activate() { # flake ref
|
||||
local backup
|
||||
backup="hm-backup-$(date +%Y%m%d-%H%M%S)"
|
||||
step "Activating Home Manager (conflicting files are renamed to *.$backup)"
|
||||
hm switch --flake "$1" -b "$backup"
|
||||
}
|
||||
|
||||
cmd_install() {
|
||||
@@ -475,11 +564,7 @@ cmd_install() {
|
||||
[[ -z $untracked ]] || warn "untracked files are invisible to the flake (git add them): $(echo "$untracked" | tr '\n' ' ')"
|
||||
fi
|
||||
|
||||
# Unique per run: Home Manager aborts if a backup from an earlier run exists.
|
||||
local backup
|
||||
backup="hm-backup-$(date +%Y%m%d-%H%M%S)"
|
||||
step "Activating Home Manager (conflicting files are renamed to *.$backup)"
|
||||
hm switch --flake "$ref" -b "$backup"
|
||||
hm_activate "$ref" || die "home-manager switch failed (see above)${clone:+; fix $dir and run install --clone again: it continues with this switch}"
|
||||
|
||||
# Settings read only at a process start (the activation warned already).
|
||||
local pending=()
|
||||
|
||||
+163
-37
@@ -3,8 +3,9 @@
|
||||
# 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.
|
||||
# Also `install.sh install` (the template) and `install --clone` (parsing,
|
||||
# the template's credential helper, clone, reruns), against local bare
|
||||
# repositories through a logging git and a fake nix, without network.
|
||||
# Also `install.sh uninstall` removing Nix while programs from the Nix store
|
||||
# run (a fake /proc, a logging nix-installer).
|
||||
{ pkgs }:
|
||||
@@ -305,34 +306,98 @@ pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq pkgs.git
|
||||
res=$(rc); [ -z "$res" ] || fail "restart-check without the drop-ins: $res"
|
||||
echo "F ok"
|
||||
|
||||
# --- G: install --clone ---
|
||||
# --- G: install from the template, install --clone ---
|
||||
INSTALL=${../../install.sh}
|
||||
GIT=${pkgs.git}/bin/git # not G: install.sh has G (a colour)
|
||||
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
|
||||
for repo in config other private; do
|
||||
git init -q -b main $R/src-$repo
|
||||
echo "{ outputs = _: { }; }" > $R/src-$repo/flake.nix
|
||||
# a configuration that keeps git's credential helper
|
||||
[ $repo = other ] || echo '{ programs.git.settings.credential.helper = "store"; }' > $R/src-$repo/home.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
|
||||
# The URL forms reach the bare repositories.
|
||||
export GIT_CONFIG_GLOBAL=$root/gitconfig LOG=$root/log GH_LOGIN=$root/gh-login GIT
|
||||
export STEAM_FRAME_NIX_TTY=$root/no-tty # none; a file for "a terminal"
|
||||
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
|
||||
git config --global url."file://$R/private.git".insteadOf https://github.com/owner/private.git
|
||||
: > $root/tty
|
||||
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
|
||||
# git that logs its arguments; clone never prompts, and https://github.com
|
||||
# needs a credential helper (private.git also a gh login)
|
||||
cat > $root/bin/git <<'SH'
|
||||
#!/bin/sh
|
||||
if [ "$1" = clone ]; then
|
||||
echo "$* (prompt=$GIT_TERMINAL_PROMPT)" >> "$LOG"
|
||||
url=; prev=; for a; do [ "$prev" = -- ] && url=$a; prev=$a; done
|
||||
[ "$GIT_TERMINAL_PROMPT" = 0 ] || { echo "fatal: would ask for a password" >&2; exit 128; }
|
||||
case $url in https://github.com/*)
|
||||
"$GIT" config --global credential.helper >/dev/null \
|
||||
|| { echo "fatal: could not read Username: terminal prompts disabled" >&2; exit 128; } ;;
|
||||
esac
|
||||
case $url in *private.git) [ -e "$GH_LOGIN" ] || { echo "fatal: Authentication failed" >&2; exit 128; } ;; esac
|
||||
else
|
||||
echo "$*" >> "$LOG"
|
||||
fi
|
||||
exec "$GIT" "$@"
|
||||
SH
|
||||
# nix: works; the template from this repository
|
||||
cat > $root/bin/nix <<'SH'
|
||||
#!/bin/sh
|
||||
case "$1 $2" in
|
||||
"--version "*) echo "nix (Nix) 2.0" ;;
|
||||
"store info") ;;
|
||||
"config show") echo "flakes nix-command" ;;
|
||||
"flake init") cp -r --no-preserve=mode "$TEMPLATE_SRC"/. . ;;
|
||||
"flake lock") echo '{}' > "$3/flake.lock" ;;
|
||||
"eval --impure") printf aarch64-linux ;;
|
||||
*) echo "nix $*: not faked" >&2; exit 1 ;;
|
||||
esac
|
||||
SH
|
||||
sed -i "1s|.*|#!${pkgs.bash}/bin/bash|" $root/bin/git $root/bin/nix
|
||||
chmod +x $root/bin/git $root/bin/nix
|
||||
export TEMPLATE_SRC=${../../template}
|
||||
PATH=$root/bin:$PATH
|
||||
# gh in the Home Manager profile: logs in
|
||||
GH=$HOME/.local/state/nix/profiles/home-manager/home-path/bin/gh
|
||||
mkdir -p ''${GH%/*}
|
||||
printf '#!%s\necho "gh $*" >> "$LOG"; : > "$GH_LOGIN"\n' ${pkgs.bash}/bin/bash > $GH
|
||||
chmod +x $GH
|
||||
# sourced: run one function with fresh state
|
||||
sfn() { (. $INSTALL; "$@"); }
|
||||
# install with Nix, curl and home-manager stubbed
|
||||
# install with curl stubbed; home-manager writes git's credential helper
|
||||
# like Home Manager would (if the configuration has it); a switch to a
|
||||
# clone fails while $root/fail-switch exists
|
||||
inst() {
|
||||
: > $GITLOG
|
||||
(. $INSTALL; ASSUME_YES=1; ensure_nix() { :; }; curl() { :; }; hm() { echo "hm $*"; }; cmd_install "$@")
|
||||
: > $LOG
|
||||
(. $INSTALL; ASSUME_YES=1; curl() { :; }; install_nix() { echo "nix install"; }
|
||||
hm() {
|
||||
echo "hm $*" | tee -a $LOG
|
||||
if grep -qs 'credential.helper = "store"' "''${3%%#*}/home.nix"; then
|
||||
$GIT config --global credential.helper store
|
||||
else
|
||||
$GIT config --global --unset-all credential.helper || true
|
||||
fi
|
||||
[[ $3 == *#* || ! -e $root/fail-switch ]]
|
||||
}
|
||||
cmd_install "$@")
|
||||
}
|
||||
nohelper() { $GIT config --global --unset-all credential.helper || true; }
|
||||
# <dir> is a clone on <branch>, without marker; no temporary clone left
|
||||
clone_ok() { # dir branch
|
||||
[ "$($GIT -C $1 branch --show-current)" = $2 ] || fail "$1: branch"
|
||||
[ -n "$($GIT -C $1 config --get remote.origin.url)" ] || fail "$1: not a clone"
|
||||
[ ! -e $1/.git/steam-frame-nix-template ] || fail "$1: template marker left"
|
||||
[ -z "$(find ''${1%/*} -maxdepth 1 -name '.*.clone.*')" ] || fail "temporary clone left"
|
||||
}
|
||||
switched_to_template() { grep -q '^hm switch --flake [^ ]*#' $LOG; }
|
||||
|
||||
# parsing
|
||||
res=$(bash $INSTALL install --clone github:owner/config --flake /x 2>&1) && fail "--clone --flake accepted"
|
||||
@@ -344,48 +409,109 @@ pkgs.runCommand "cleanup-check" { nativeBuildInputs = [ cleanup pkgs.jq pkgs.git
|
||||
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
|
||||
# a plain install: the template, its marker in .git
|
||||
res=$(inst)
|
||||
has "$res" "installed already"; hasnt "$res" "nix install"
|
||||
has "$res" "hm switch --flake $HOME/nix-config#$(id -un) -b"
|
||||
grep -q "steamFrame" $HOME/nix-config/home.nix || fail "no template"
|
||||
[ -s $HOME/nix-config/.git/steam-frame-nix-template ] || fail "no template marker"
|
||||
! $GIT -C $HOME/nix-config status --porcelain | grep -v '^A ' || fail "marker visible to git"
|
||||
# --clone replaces it (unchanged; active with the helpers: no switch to it)
|
||||
res=$(inst --clone github:owner/config)
|
||||
has "$res" "(skipped)"
|
||||
! switched_to_template || fail "template switched again: $(cat $LOG)"
|
||||
has "$res" "removed the template in $HOME/nix-config"
|
||||
clone_ok $HOME/nix-config main
|
||||
|
||||
# each URL form: template switch, clone (never prompting), the clone
|
||||
# replaces the template, switch to it
|
||||
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
|
||||
rm -rf $HOME/nix-config $HOME/.config/home-manager; nohelper
|
||||
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"
|
||||
l1=$(grep -n "^hm switch --flake $HOME/nix-config#" $LOG | cut -d: -f1)
|
||||
l2=$(grep -nF "clone -- $want $HOME/.nix-config.clone." $LOG | cut -d: -f1)
|
||||
l3=$(grep -n "^hm switch --flake $HOME/nix-config -b" $LOG | cut -d: -f1)
|
||||
[ -n "$l1" ] && [ -n "$l2" ] && [ -n "$l3" ] && [ $l1 -lt $l2 ] && [ $l2 -lt $l3 ] || fail "$url: order: $(cat $LOG)"
|
||||
grep -q "^clone .*(prompt=0)$" $LOG || fail "$url: clone may prompt"
|
||||
[ "$(readlink $HOME/.config/home-manager)" = $HOME/nix-config ] || fail "$url: link"
|
||||
[ "$(git -C $HOME/nix-config branch --show-current)" = main ] || fail "$url: branch"
|
||||
clone_ok $HOME/nix-config main
|
||||
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"
|
||||
# an existing directory that isn't the template (here a clone of another
|
||||
# repository): used as it is, no clone, no template
|
||||
res=$(inst --clone https://example.org/other.git)
|
||||
has "$res" "$HOME/nix-config already exists and isn't the untouched template: using it as it is (not cloning)"
|
||||
! grep -q "^clone" $LOG || fail "cloned over an existing directory"
|
||||
! switched_to_template || fail "template over an existing directory"
|
||||
has "$res" "hm switch --flake $HOME/nix-config -b"
|
||||
[ "$($GIT -C $HOME/nix-config config --get remote.origin.url)" = git@github.com:owner/config ] || fail "existing directory changed"
|
||||
|
||||
# --dir (relative) and --ref; the existing link stays
|
||||
# --dir (relative) and --ref; an active configuration: no template, 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"
|
||||
grep -qF "clone --branch dev -- https://github.com/owner/config.git $HOME/.cfg.clone." $LOG || fail "ref: $(cat $LOG)"
|
||||
! switched_to_template || fail "template with a configuration"
|
||||
clone_ok $HOME/cfg dev
|
||||
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"
|
||||
# not a configuration: not cloned over, kept (and no flake to switch to)
|
||||
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
|
||||
has "$res" "using it as it is (not cloning)"
|
||||
has "$res" "has no flake.nix"
|
||||
there $HOME/plain/x
|
||||
# a failed clone: the hint, nothing left
|
||||
res=$(inst --clone https://example.org/missing.git --dir $HOME/m 2>&1) && fail "missing repo"
|
||||
has "$res" "gh auth login"
|
||||
gone $HOME/m
|
||||
[ -z "$(find $HOME -maxdepth 1 -name '.m.clone.*')" ] || fail "temporary clone left"
|
||||
|
||||
# a failed clone (no login, no terminal: gh isn't offered): the template
|
||||
# stays active in ~/nix-config, with its marker
|
||||
rm -rf $HOME/nix-config $HOME/.config/home-manager; nohelper
|
||||
res=$(inst --clone https://github.com/owner/private.git 2>&1) && fail "private repo cloned"
|
||||
has "$res" "the steam-frame-nix template stays active in $HOME/nix-config"
|
||||
has "$res" "gh auth login"
|
||||
! grep -q "^gh " $LOG || fail "gh without a terminal"
|
||||
grep -q "steamFrame" $HOME/nix-config/home.nix || fail "template gone"
|
||||
[ -s $HOME/nix-config/.git/steam-frame-nix-template ] || fail "template marker gone"
|
||||
[ "$(readlink $HOME/.config/home-manager)" = $HOME/nix-config ] || fail "template link"
|
||||
[ -z "$(find $HOME -maxdepth 1 -name '.nix-config.clone.*')" ] || fail "temporary clone left"
|
||||
# the rerun (a terminal): no Nix install, no template switch; gh auth
|
||||
# login, the clone again, the switch
|
||||
res=$(STEAM_FRAME_NIX_TTY=$root/tty inst --clone https://github.com/owner/private.git)
|
||||
has "$res" "installed already"; hasnt "$res" "nix install"
|
||||
has "$res" "(skipped)"
|
||||
! switched_to_template || fail "template switched again: $(cat $LOG)"
|
||||
grep -qxF "gh auth login --hostname github.com --git-protocol https" $LOG || fail "no gh login: $(cat $LOG)"
|
||||
[ "$(grep -c '^clone ' $LOG)" = 2 ] || fail "clone not retried: $(cat $LOG)"
|
||||
has "$res" "hm switch --flake $HOME/nix-config -b"
|
||||
clone_ok $HOME/nix-config main
|
||||
|
||||
# a changed template is used as it is
|
||||
rm -rf $HOME/nix-config $HOME/.config/home-manager $GH_LOGIN; nohelper
|
||||
inst --clone https://github.com/owner/private.git >/dev/null 2>&1 && fail "private repo cloned"
|
||||
echo "# mine" >> $HOME/nix-config/home.nix
|
||||
res=$(inst --clone github:owner/config)
|
||||
has "$res" "using it as it is (not cloning)"
|
||||
! grep -q "^clone" $LOG || fail "cloned over a changed template"
|
||||
has "$res" "hm switch --flake $HOME/nix-config -b"
|
||||
grep -q "# mine" $HOME/nix-config/home.nix || fail "changed template touched"
|
||||
|
||||
# a failed switch to the clone: the clone stays, the rerun only switches
|
||||
rm -rf $HOME/nix-config $HOME/.config/home-manager; nohelper
|
||||
touch $root/fail-switch
|
||||
res=$(inst --clone github:owner/config 2>&1) && fail "failed switch passed"
|
||||
has "$res" "it continues with this switch"
|
||||
clone_ok $HOME/nix-config main
|
||||
rm $root/fail-switch
|
||||
res=$(inst --clone github:owner/config)
|
||||
has "$res" "(not cloning)"
|
||||
! grep -q "^clone" $LOG || fail "cloned again"
|
||||
! switched_to_template || fail "template switched again"
|
||||
[ "$(grep -c '^hm ' $LOG)" = 1 ] || fail "switches: $(cat $LOG)"
|
||||
echo "G ok"
|
||||
|
||||
# --- H: uninstall: Nix goes while programs from the store still run ---
|
||||
|
||||
@@ -9,6 +9,17 @@
|
||||
targets.genericLinux.enable = true; # non-NixOS integration
|
||||
programs.home-manager.enable = true; # the `home-manager` command
|
||||
|
||||
# git credentials for HTTPS (`install.sh install --clone` uses them):
|
||||
# GitHub through the GitHub CLI (log in once: gh auth login, works with
|
||||
# 2FA), other hosts from ~/.git-credentials. git itself is SteamOS's;
|
||||
# Home Manager only writes its config. Remove to manage git yourself.
|
||||
programs.git = {
|
||||
enable = true;
|
||||
package = null;
|
||||
settings.credential.helper = "store";
|
||||
};
|
||||
programs.gh.enable = true;
|
||||
|
||||
# Packages for your user, e.g.:
|
||||
# home.packages = with pkgs; [ htop ripgrep ];
|
||||
|
||||
|
||||
Reference in new issue
Block a user