mirror of
https://github.com/nix-community/home-manager
synced 2024-06-02 04:53:33 +02:00
bf3a8c6383
Before this path would point to the modules path. Using the project root instead makes it possible to set `<home-manager>` to point to a downloadable archive of Home Manager. This should make it significantly easier to install and keep Home Manager up to date. To match this change we also deprecate the Home Manager option programs.home-manager.modulesPath and instead ask users to use programs.home-manager.path
308 lines
7.9 KiB
Bash
308 lines
7.9 KiB
Bash
#!@bash@/bin/bash
|
|
|
|
# This code explicitly requires GNU Core Utilities and we therefore
|
|
# need to ensure they are prioritized over any other similarly named
|
|
# tools on the system.
|
|
PATH=@coreutils@/bin:@less@/bin${PATH:+:}$PATH
|
|
|
|
set -euo pipefail
|
|
|
|
function errorEcho() {
|
|
echo $* >&2
|
|
}
|
|
|
|
# Attempts to set the HOME_MANAGER_CONFIG global variable.
|
|
#
|
|
# If no configuration file can be found then this function will print
|
|
# an error message and exit with an error code.
|
|
function setConfigFile() {
|
|
if [[ -v HOME_MANAGER_CONFIG ]] ; then
|
|
if [[ ! -e "$HOME_MANAGER_CONFIG" ]] ; then
|
|
errorEcho "No configuration file found at $HOME_MANAGER_CONFIG"
|
|
exit 1
|
|
fi
|
|
|
|
HOME_MANAGER_CONFIG="$(realpath "$HOME_MANAGER_CONFIG")"
|
|
return
|
|
fi
|
|
|
|
local confFile
|
|
for confFile in "$HOME/.config/nixpkgs/home.nix" \
|
|
"$HOME/.nixpkgs/home.nix" ; do
|
|
if [[ -e "$confFile" ]] ; then
|
|
HOME_MANAGER_CONFIG="$confFile"
|
|
return
|
|
fi
|
|
done
|
|
|
|
errorEcho "No configuration file found." \
|
|
"Please create one at ~/.config/nixpkgs/home.nix"
|
|
exit 1
|
|
}
|
|
|
|
function setHomeManagerNixPath() {
|
|
local path
|
|
for path in "@HOME_MANAGER_PATH@" \
|
|
"$HOME/.config/nixpkgs/home-manager" \
|
|
"$HOME/.nixpkgs/home-manager" ; do
|
|
if [[ -e "$path" || "$path" =~ ^https?:// ]] ; then
|
|
export NIX_PATH="$NIX_PATH${NIX_PATH:+:}home-manager=$path"
|
|
return
|
|
fi
|
|
done
|
|
}
|
|
|
|
function doBuildAttr() {
|
|
setConfigFile
|
|
setHomeManagerNixPath
|
|
|
|
local extraArgs="$*"
|
|
|
|
for p in "${EXTRA_NIX_PATH[@]}"; do
|
|
extraArgs="$extraArgs -I $p"
|
|
done
|
|
|
|
if [[ -v VERBOSE ]]; then
|
|
extraArgs="$extraArgs --show-trace"
|
|
fi
|
|
|
|
nix-build \
|
|
"<home-manager/home-manager/home-manager.nix>" \
|
|
$extraArgs \
|
|
--argstr confPath "$HOME_MANAGER_CONFIG" \
|
|
--argstr confAttr "$HOME_MANAGER_CONFIG_ATTRIBUTE"
|
|
}
|
|
|
|
# Presents news to the user. Takes as argument the path to a "news
|
|
# info" file as generated by `buildNews`.
|
|
function presentNews() {
|
|
local infoFile="$1"
|
|
|
|
# shellcheck source=/dev/null
|
|
. "$infoFile"
|
|
|
|
if [[ $newsNumUnread -eq 0 ]]; then
|
|
return
|
|
elif [[ "$newsDisplay" == "silent" ]]; then
|
|
return
|
|
elif [[ "$newsDisplay" == "notify" ]]; then
|
|
local msg
|
|
if [[ $newsNumUnread -eq 1 ]]; then
|
|
msg="There is an unread and relevant news item.\n"
|
|
msg+="Read it by running the command '$(basename "$0") news'."
|
|
else
|
|
msg="There are $newsNumUnread unread and relevant news items.\n"
|
|
msg+="Read them by running the command '$(basename "$0") news'."
|
|
fi
|
|
|
|
# Not actually an error but here stdout is reserved for
|
|
# nix-build output.
|
|
errorEcho
|
|
errorEcho -e "$msg"
|
|
errorEcho
|
|
|
|
if [[ -v DISPLAY ]] && type -P notify-send > /dev/null; then
|
|
notify-send "Home Manager" "$msg"
|
|
fi
|
|
elif [[ "$newsDisplay" == "show" ]]; then
|
|
doShowNews --unread
|
|
else
|
|
errorEcho "Unknown 'news.display' setting '$newsDisplay'."
|
|
fi
|
|
}
|
|
|
|
function doBuild() {
|
|
local newsInfo
|
|
newsInfo=$(buildNews)
|
|
|
|
local exitCode
|
|
doBuildAttr -A activationPackage \
|
|
&& exitCode=0 || exitCode=1
|
|
|
|
presentNews "$newsInfo"
|
|
|
|
return $exitCode
|
|
}
|
|
|
|
function doSwitch() {
|
|
local newsInfo
|
|
newsInfo=$(buildNews)
|
|
|
|
local generation
|
|
local exitCode=0
|
|
local wrkdir
|
|
|
|
# Build the generation and run the activate script. Note, we
|
|
# specify an output link si that it is treated as a GC root. This
|
|
# prevents an unfortunately timed GC from removing the generation
|
|
# before activation completes.
|
|
wrkdir="$(mktemp -d)"
|
|
generation=$(doBuildAttr -o "$wrkdir/result" -A activationPackage) \
|
|
&& $generation/activate || exitCode=1
|
|
|
|
# Because the previous command never fails, the script keeps
|
|
# running and $wrkdir is always removed.
|
|
rm -r "$wrkdir"
|
|
|
|
presentNews "$newsInfo"
|
|
|
|
return $exitCode
|
|
}
|
|
|
|
function doListGens() {
|
|
pushd "/nix/var/nix/profiles/per-user/$USER" > /dev/null
|
|
ls --color=yes -gG --sort time home-manager-*-link \
|
|
| cut -d' ' -f 4-
|
|
popd > /dev/null
|
|
}
|
|
|
|
function doListPackages() {
|
|
local outPath
|
|
outPath="$(nix-env -q --out-path | grep -o '/.*home-manager-path$')"
|
|
if [[ -n "$outPath" ]] ; then
|
|
nix-store -q --references "$outPath" | sed 's/[^-]*-//'
|
|
else
|
|
errorEcho "No home-manager packages seem to be installed."
|
|
fi
|
|
}
|
|
|
|
function newsReadIdsFile() {
|
|
local dataDir="${XDG_DATA_HOME:-$HOME/.local/share}/home-manager"
|
|
local path="$dataDir/news-read-ids"
|
|
|
|
# If the path doesn't exist then we should create it, otherwise
|
|
# Nix will error out when we attempt to use builtins.readFile.
|
|
if [[ ! -f "$path" ]]; then
|
|
mkdir -p "$dataDir"
|
|
touch "$path"
|
|
fi
|
|
|
|
echo "$path"
|
|
}
|
|
|
|
# Builds news meta information to be sourced into this script.
|
|
#
|
|
# Note, we suppress build output to remove unnecessary verbosity. We
|
|
# also use "no out link" to avoid the need for a build directory
|
|
# (although this exposes the risk of GC removing the result before we
|
|
# manage to source it).
|
|
function buildNews() {
|
|
doBuildAttr --quiet \
|
|
--attr newsInfo \
|
|
--no-out-link \
|
|
--arg check false \
|
|
--argstr newsReadIdsFile "$(newsReadIdsFile)"
|
|
}
|
|
|
|
function doShowNews() {
|
|
local infoFile
|
|
infoFile=$(buildNews) || return 1
|
|
|
|
# shellcheck source=/dev/null
|
|
. "$infoFile"
|
|
|
|
case $1 in
|
|
--all)
|
|
${PAGER:-less} "$newsFileAll"
|
|
;;
|
|
--unread)
|
|
${PAGER:-less} "$newsFileUnread"
|
|
;;
|
|
*)
|
|
errorEcho "Unknown argument $1"
|
|
return 1
|
|
esac
|
|
|
|
if [[ -s "$newsUnreadIdsFile" ]]; then
|
|
local newsReadIdsFile
|
|
newsReadIdsFile="$(newsReadIdsFile)"
|
|
cat "$newsUnreadIdsFile" >> "$newsReadIdsFile"
|
|
fi
|
|
}
|
|
|
|
function doHelp() {
|
|
echo "Usage: $0 [OPTION] COMMAND"
|
|
echo
|
|
echo "Options"
|
|
echo
|
|
echo " -f FILE The home configuration file."
|
|
echo " Default is '~/.config/nixpkgs/home.nix'."
|
|
echo " -A ATTRIBUTE Optional attribute that selects a configuration"
|
|
echo " expression in the configuration file."
|
|
echo " -I PATH Add a path to the Nix expression search path."
|
|
echo " -v Verbose output"
|
|
echo " -n Do a dry run, only prints what actions would be taken"
|
|
echo " -h Print this help"
|
|
echo
|
|
echo "Commands"
|
|
echo " help Print this help"
|
|
echo " build Build configuration into result directory"
|
|
echo " switch Build and activate configuration"
|
|
echo " generations List all home environment generations"
|
|
echo " packages List all packages installed in home-manager-path"
|
|
echo " news Show news entries in a pager"
|
|
}
|
|
|
|
EXTRA_NIX_PATH=()
|
|
HOME_MANAGER_CONFIG_ATTRIBUTE=""
|
|
|
|
while getopts f:I:A:vnh opt; do
|
|
case $opt in
|
|
f)
|
|
HOME_MANAGER_CONFIG="$OPTARG"
|
|
;;
|
|
I)
|
|
EXTRA_NIX_PATH+=("$OPTARG")
|
|
;;
|
|
A)
|
|
HOME_MANAGER_CONFIG_ATTRIBUTE="$OPTARG"
|
|
;;
|
|
v)
|
|
export VERBOSE=1
|
|
;;
|
|
n)
|
|
export DRY_RUN=1
|
|
;;
|
|
h)
|
|
doHelp
|
|
exit 0
|
|
;;
|
|
*)
|
|
errorEcho "Unknown option -$OPTARG"
|
|
doHelp >&2
|
|
exit 1
|
|
;;
|
|
esac
|
|
done
|
|
|
|
# Get rid of the options.
|
|
shift "$((OPTIND-1))"
|
|
|
|
cmd="$*"
|
|
|
|
case "$cmd" in
|
|
build)
|
|
doBuild
|
|
;;
|
|
switch)
|
|
doSwitch
|
|
;;
|
|
generations)
|
|
doListGens
|
|
;;
|
|
packages)
|
|
doListPackages
|
|
;;
|
|
news)
|
|
doShowNews --all
|
|
;;
|
|
help|--help)
|
|
doHelp
|
|
;;
|
|
*)
|
|
errorEcho "Unknown command: $cmd"
|
|
doHelp >&2
|
|
exit 1
|
|
;;
|
|
esac
|