Initial commit; add toolchain
commit
45e1613787
|
@ -0,0 +1,4 @@
|
||||||
|
result
|
||||||
|
/.redo
|
||||||
|
**/.do_built*
|
||||||
|
**/*.did
|
|
@ -0,0 +1,18 @@
|
||||||
|
#+TITLE: Nix flake
|
||||||
|
#+AUTHOR: spacefrogg
|
||||||
|
#+EMAIL: git@spacefrogg.net
|
||||||
|
#+options: toc:nil
|
||||||
|
|
||||||
|
* Development
|
||||||
|
This comes with a self-contained redo toolchain to help in working with the
|
||||||
|
flake. It basically deploys any input flake into the =tmp= directory for easier
|
||||||
|
access.
|
||||||
|
|
||||||
|
redo targets under =tmp/= come in three kinds:
|
||||||
|
- =clean= :: will remove all build products under =tmp/=
|
||||||
|
- =<flake>= :: will make sure a store path to =<flake>= exists and puts an
|
||||||
|
indirect root into =tmp/<flake>=.
|
||||||
|
- =<flake>.rw= :: will make sure a store path to =<flake>= exists and will
|
||||||
|
copy its contents to =tmp/.<flake>.rw= and will link to it from
|
||||||
|
=tmp/<flake>.rw=. (Rationale: On Linux, directories cannot denote reliable
|
||||||
|
targets due to their non-trivial relation to modification time.)
|
|
@ -0,0 +1,446 @@
|
||||||
|
#!/usr/bin/env sh
|
||||||
|
#
|
||||||
|
# A minimal alternative to djb redo that doesn't support incremental builds.
|
||||||
|
# For the full version, visit http://github.com/apenwarr/redo
|
||||||
|
#
|
||||||
|
# The author disclaims copyright to this source file and hereby places it in
|
||||||
|
# the public domain. (2010 12 14; updated 2019 02 24)
|
||||||
|
#
|
||||||
|
USAGE="
|
||||||
|
usage: do [-d] [-x] [-v] [-c] <targets...>
|
||||||
|
-d print extra debug messages (mostly about dependency checks)
|
||||||
|
-v run .do files with 'set -v'
|
||||||
|
-x run .do files with 'set -x'
|
||||||
|
-c clean up all old targets before starting
|
||||||
|
|
||||||
|
Note: do is an implementation of redo that does *not* check dependencies.
|
||||||
|
It will never rebuild a target it has already built, unless you use -c.
|
||||||
|
"
|
||||||
|
|
||||||
|
# CDPATH apparently causes unexpected 'cd' output on some platforms.
|
||||||
|
unset CDPATH
|
||||||
|
|
||||||
|
# By default, no output coloring.
|
||||||
|
green=""
|
||||||
|
bold=""
|
||||||
|
plain=""
|
||||||
|
|
||||||
|
if [ -n "$TERM" -a "$TERM" != "dumb" ] && tty <&2 >/dev/null 2>&1; then
|
||||||
|
green="$(printf '\033[32m')"
|
||||||
|
bold="$(printf '\033[1m')"
|
||||||
|
plain="$(printf '\033[m')"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# The 'seq' command is not available on all platforms.
|
||||||
|
_seq() {
|
||||||
|
local x=0 max="$1"
|
||||||
|
while [ "$x" -lt "$max" ]; do
|
||||||
|
x=$((x + 1))
|
||||||
|
echo "$x"
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
# Split $1 into a dir part ($_dirsplit_dir) and base filename ($_dirsplit_base)
|
||||||
|
_dirsplit() {
|
||||||
|
_dirsplit_base=${1##*/}
|
||||||
|
_dirsplit_dir=${1%$_dirsplit_base}
|
||||||
|
}
|
||||||
|
|
||||||
|
# Like /usr/bin/dirname, but avoids a fork and uses _dirsplit semantics.
|
||||||
|
qdirname() (
|
||||||
|
_dirsplit "$1"
|
||||||
|
dir=${_dirsplit_dir%/}
|
||||||
|
echo "${dir:-.}"
|
||||||
|
)
|
||||||
|
|
||||||
|
_dirsplit "$0"
|
||||||
|
REDO=$(cd "$(env pwd -P)" &&
|
||||||
|
cd "${_dirsplit_dir:-.}" &&
|
||||||
|
echo "$PWD/$_dirsplit_base")
|
||||||
|
export REDO
|
||||||
|
_cmd=$_dirsplit_base
|
||||||
|
|
||||||
|
DO_TOP=
|
||||||
|
if [ -z "$DO_BUILT" ]; then
|
||||||
|
export _do_opt_debug=
|
||||||
|
export _do_opt_exec=
|
||||||
|
export _do_opt_verbose=
|
||||||
|
export _do_opt_clean=
|
||||||
|
fi
|
||||||
|
while getopts 'dxvcj:h?' _opt; do
|
||||||
|
case $_opt in
|
||||||
|
d) _do_opt_debug=1 ;;
|
||||||
|
x) _do_opt_exec=x ;;
|
||||||
|
v) _do_opt_verbose=v ;;
|
||||||
|
c) _do_opt_clean=1 ;;
|
||||||
|
j) ;; # silently ignore, for compat with real redo
|
||||||
|
\?|h|*) printf "%s" "$USAGE" >&2
|
||||||
|
exit 99
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
shift "$((OPTIND - 1))"
|
||||||
|
_debug() {
|
||||||
|
[ -z "$_do_opt_debug" ] || echo "$@" >&2
|
||||||
|
}
|
||||||
|
|
||||||
|
if [ -z "$DO_BUILT" -a "$_cmd" != "redo-whichdo" ]; then
|
||||||
|
DO_TOP=1
|
||||||
|
if [ "$#" -eq 0 ] && [ "$_cmd" = "do" -o "$_cmd" = "redo" ]; then
|
||||||
|
set all # only toplevel redo has a default target
|
||||||
|
fi
|
||||||
|
export DO_STARTDIR="$(env pwd -P)"
|
||||||
|
# If starting /bin/pwd != $PWD, this will fix it.
|
||||||
|
# That can happen when $PWD contains symlinks that the shell is
|
||||||
|
# trying helpfully (but unsuccessfully) to hide from the user.
|
||||||
|
cd "$DO_STARTDIR" || exit 99
|
||||||
|
export DO_BUILT="$PWD/.do_built"
|
||||||
|
if [ -z "$_do_opt_clean" -a -e "$DO_BUILT" ]; then
|
||||||
|
echo "do: Incremental mode. Use -c for clean rebuild." >&2
|
||||||
|
fi
|
||||||
|
: >>"$DO_BUILT"
|
||||||
|
sort -u "$DO_BUILT" >"$DO_BUILT.new"
|
||||||
|
while read f; do
|
||||||
|
[ -n "$_do_opt_clean" ] && printf "%s\0%s.did\0" "$f" "$f"
|
||||||
|
printf "%s.did.tmp\0" "$f"
|
||||||
|
done <"$DO_BUILT.new" |
|
||||||
|
xargs -0 rm -f 2>/dev/null
|
||||||
|
mv "$DO_BUILT.new" "$DO_BUILT"
|
||||||
|
export DO_PATH="$DO_BUILT.dir"
|
||||||
|
export PATH="$DO_PATH:$PATH"
|
||||||
|
rm -rf "$DO_PATH"
|
||||||
|
mkdir "$DO_PATH"
|
||||||
|
for d in redo redo-ifchange redo-whichdo; do
|
||||||
|
ln -s "$REDO" "$DO_PATH/$d"
|
||||||
|
done
|
||||||
|
for d in redo-ifcreate redo-stamp redo-always redo-ood \
|
||||||
|
redo-targets redo-sources; do
|
||||||
|
echo "#!/bin/sh" >"$DO_PATH/$d"
|
||||||
|
chmod a+rx "$DO_PATH/$d"
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
|
# Chop the "file" part off a /path/to/file pathname.
|
||||||
|
# Note that if the filename already ends in a /, we just remove the slash.
|
||||||
|
_updir()
|
||||||
|
{
|
||||||
|
local v="${1%/*}"
|
||||||
|
[ "$v" != "$1" ] && echo "$v"
|
||||||
|
# else "empty" which means we went past the root
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Returns true if $1 starts with $2.
|
||||||
|
_startswith()
|
||||||
|
{
|
||||||
|
[ "${1#"$2"}" != "$1" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Returns true if $1 ends with $2.
|
||||||
|
_endswith()
|
||||||
|
{
|
||||||
|
[ "${1%"$2"}" != "$1" ]
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Prints $1 if it's absolute, or $2/$1 if $1 is not absolute.
|
||||||
|
_abspath()
|
||||||
|
{
|
||||||
|
local here="$2" there="$1"
|
||||||
|
if _startswith "$1" "/"; then
|
||||||
|
echo "$1"
|
||||||
|
else
|
||||||
|
echo "$2/$1"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Prints $1 as a path relative to $PWD (not starting with /).
|
||||||
|
# If it already doesn't start with a /, doesn't change the string.
|
||||||
|
_relpath()
|
||||||
|
{
|
||||||
|
local here="$2" there="$1" out= hadslash=
|
||||||
|
#echo "RP start '$there' hs='$hadslash'" >&2
|
||||||
|
_startswith "$there" "/" || { echo "$there" && return; }
|
||||||
|
[ "$there" != "/" ] && _endswith "$there" "/" && hadslash=/
|
||||||
|
here=${here%/}/
|
||||||
|
while [ -n "$here" ]; do
|
||||||
|
#echo "RP out='$out' here='$here' there='$there'" >&2
|
||||||
|
[ "${here%/}" = "${there%/}" ] && there= && break;
|
||||||
|
[ "${there#$here}" != "$there" ] && break
|
||||||
|
out=../$out
|
||||||
|
_dirsplit "${here%/}"
|
||||||
|
here=$_dirsplit_dir
|
||||||
|
done
|
||||||
|
there=${there#$here}
|
||||||
|
if [ -n "$there" ]; then
|
||||||
|
echo "$out${there%/}$hadslash"
|
||||||
|
else
|
||||||
|
echo "${out%/}$hadslash"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Prints a "normalized relative" path, with ".." resolved where possible.
|
||||||
|
# For example, a/b/../c will be reduced to just a/c.
|
||||||
|
_normpath()
|
||||||
|
(
|
||||||
|
local path="$1" relto="$2" out= isabs=
|
||||||
|
#echo "NP start '$path'" >&2
|
||||||
|
if _startswith "$path" "/"; then
|
||||||
|
isabs=1
|
||||||
|
else
|
||||||
|
path="${relto%/}/$path"
|
||||||
|
fi
|
||||||
|
set -f
|
||||||
|
IFS=/
|
||||||
|
for d in ${path%/}; do
|
||||||
|
#echo "NP out='$out' d='$d'" >&2
|
||||||
|
if [ "$d" = ".." ]; then
|
||||||
|
out=$(_updir "${out%/}")/
|
||||||
|
else
|
||||||
|
out=$out$d/
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
#echo "NP out='$out' (done)" >&2
|
||||||
|
out=${out%/}
|
||||||
|
if [ -n "$isabs" ]; then
|
||||||
|
echo "${out:-/}"
|
||||||
|
else
|
||||||
|
_relpath "${out:-/}" "$relto"
|
||||||
|
fi
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Prints a "real" path, with all symlinks resolved where possible.
|
||||||
|
_realpath()
|
||||||
|
{
|
||||||
|
local path="$1" relto="$2" isabs= rest=
|
||||||
|
if _startswith "$path" "/"; then
|
||||||
|
isabs=1
|
||||||
|
else
|
||||||
|
path="${relto%/}/$path"
|
||||||
|
fi
|
||||||
|
(
|
||||||
|
for d in $(_seq 100); do
|
||||||
|
#echo "Trying: $PWD--$path" >&2
|
||||||
|
if cd -P "$path" 2>/dev/null; then
|
||||||
|
# success
|
||||||
|
pwd=$(env pwd -P)
|
||||||
|
#echo " chdir ok: $pwd--$rest" >&2
|
||||||
|
np=$(_normpath "${pwd%/}/$rest" "$relto")
|
||||||
|
if [ -n "$isabs" ]; then
|
||||||
|
echo "$np"
|
||||||
|
else
|
||||||
|
_relpath "$np" "$relto"
|
||||||
|
fi
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
_dirsplit "${path%/}"
|
||||||
|
path=$_dirsplit_dir
|
||||||
|
rest="$_dirsplit_base/$rest"
|
||||||
|
done
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# List the possible names for default*.do files in dir $1 matching the target
|
||||||
|
# pattern in $2. We stop searching when we find the first one that exists.
|
||||||
|
_find_dofiles_pwd()
|
||||||
|
{
|
||||||
|
local dodir="$1" dofile="$2"
|
||||||
|
_startswith "$dofile" "default." || dofile=${dofile#*.}
|
||||||
|
while :; do
|
||||||
|
dofile=default.${dofile#default.*.}
|
||||||
|
echo "$dodir$dofile"
|
||||||
|
[ -e "$dodir$dofile" ] && return 0
|
||||||
|
[ "$dofile" = default.do ] && break
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# List the possible names for default*.do files in $PWD matching the target
|
||||||
|
# pattern in $1. We stop searching when we find the first name that works.
|
||||||
|
# If there are no matches in $PWD, we'll search in .., and so on, to the root.
|
||||||
|
_find_dofiles()
|
||||||
|
{
|
||||||
|
local target="$1" dodir= dofile= newdir=
|
||||||
|
_debug "find_dofile: '$PWD' '$target'"
|
||||||
|
dofile="$target.do"
|
||||||
|
echo "$dofile"
|
||||||
|
[ -e "$dofile" ] && return 0
|
||||||
|
|
||||||
|
# Try default.*.do files, walking up the tree
|
||||||
|
_dirsplit "$dofile"
|
||||||
|
dodir=$_dirsplit_dir
|
||||||
|
dofile=$_dirsplit_base
|
||||||
|
[ -n "$dodir" ] && dodir=${dodir%/}/
|
||||||
|
[ -e "$dodir$dofile" ] && return 0
|
||||||
|
for i in $(_seq 100); do
|
||||||
|
[ -n "$dodir" ] && dodir=${dodir%/}/
|
||||||
|
#echo "_find_dofiles: '$dodir' '$dofile'" >&2
|
||||||
|
_find_dofiles_pwd "$dodir" "$dofile" && return 0
|
||||||
|
newdir=$(_realpath "${dodir}.." "$PWD")
|
||||||
|
[ "$newdir" = "$dodir" ] && break
|
||||||
|
dodir=$newdir
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Print the last .do file returned by _find_dofiles.
|
||||||
|
# If that file exists, returns 0, else 1.
|
||||||
|
_find_dofile()
|
||||||
|
{
|
||||||
|
local files="$(_find_dofiles "$1")"
|
||||||
|
rv=$?
|
||||||
|
#echo "files='$files'" >&2
|
||||||
|
[ "$rv" -ne 0 ] && return $rv
|
||||||
|
echo "$files" | {
|
||||||
|
while read -r linex; do line=$linex; done
|
||||||
|
printf "%s\n" "$line"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Actually run the given $dofile with the arguments in $@.
|
||||||
|
# Note: you should always run this in a subshell.
|
||||||
|
_run_dofile()
|
||||||
|
{
|
||||||
|
export DO_DEPTH="$DO_DEPTH "
|
||||||
|
export REDO_TARGET="$PWD/$target"
|
||||||
|
local line1
|
||||||
|
set -e
|
||||||
|
read line1 <"$PWD/$dofile" || true
|
||||||
|
cmd=${line1#"#!/"}
|
||||||
|
if [ "$cmd" != "$line1" ]; then
|
||||||
|
set -$_do_opt_verbose$_do_opt_exec
|
||||||
|
exec /$cmd "$PWD/$dofile" "$@"
|
||||||
|
else
|
||||||
|
set -$_do_opt_verbose$_do_opt_exec
|
||||||
|
# If $dofile is empty, "." might not change $? at
|
||||||
|
# all, so we clear it first with ":".
|
||||||
|
:; . "$PWD/$dofile"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Find and run the right .do file, starting in dir $1, for target $2,
|
||||||
|
# providing a temporary output file as $3. Renames the temp file to $2 when
|
||||||
|
# done.
|
||||||
|
_do()
|
||||||
|
{
|
||||||
|
local dir="$1" target="$1$2" tmp="$1$2.redo.tmp" tdir=
|
||||||
|
local dopath= dodir= dofile= ext=
|
||||||
|
if [ "$_cmd" = "redo" ] ||
|
||||||
|
( [ ! -e "$target" -o -d "$target" ] &&
|
||||||
|
[ ! -e "$target.did" ] ); then
|
||||||
|
printf '%sdo %s%s%s%s\n' \
|
||||||
|
"$green" "$DO_DEPTH" "$bold" "$target" "$plain" >&2
|
||||||
|
dopath=$(_find_dofile "$target")
|
||||||
|
if [ ! -e "$dopath" ]; then
|
||||||
|
echo "do: $target: no .do file ($PWD)" >&2
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_dirsplit "$dopath"
|
||||||
|
dodir=$_dirsplit_dir dofile=$_dirsplit_base
|
||||||
|
if _startswith "$dofile" "default."; then
|
||||||
|
ext=${dofile#default}
|
||||||
|
ext=${ext%.do}
|
||||||
|
else
|
||||||
|
ext=
|
||||||
|
fi
|
||||||
|
target=$PWD/$target
|
||||||
|
tmp=$PWD/$tmp
|
||||||
|
cd "$dodir" || return 99
|
||||||
|
target=$(_relpath "$target" "$PWD") || return 98
|
||||||
|
tmp=$(_relpath "$tmp" "$PWD") || return 97
|
||||||
|
base=${target%$ext}
|
||||||
|
tdir=$(qdirname "$target")
|
||||||
|
[ ! -e "$DO_BUILT" ] || [ ! -w "$tdir/." ] ||
|
||||||
|
: >>"$target.did.tmp"
|
||||||
|
# $qtmp is a temporary file used to capture stdout.
|
||||||
|
# Since it might be accidentally deleted as a .do file
|
||||||
|
# does its work, we create it, then open two fds to it,
|
||||||
|
# then immediately delete the name. We use one fd to
|
||||||
|
# redirect to stdout, and the other to read from after,
|
||||||
|
# because there's no way to fseek(fd, 0) in sh.
|
||||||
|
qtmp=$DO_PATH/do.$$.tmp
|
||||||
|
(
|
||||||
|
rm -f "$qtmp"
|
||||||
|
( _run_dofile "$target" "$base" "$tmp" >&3 3>&- 4<&- )
|
||||||
|
rv=$?
|
||||||
|
if [ $rv != 0 ]; then
|
||||||
|
printf "do: %s%s\n" "$DO_DEPTH" \
|
||||||
|
"$target: got exit code $rv" >&2
|
||||||
|
rm -f "$tmp.tmp" "$tmp.tmp2" "$target.did"
|
||||||
|
return $rv
|
||||||
|
fi
|
||||||
|
echo "$PWD/$target" >>"$DO_BUILT"
|
||||||
|
if [ ! -e "$tmp" ]; then
|
||||||
|
# if $3 wasn't created, copy from stdout file
|
||||||
|
cat <&4 >$tmp
|
||||||
|
# if that's zero length too, forget it
|
||||||
|
[ -s "$tmp" ] || rm -f "$tmp"
|
||||||
|
fi
|
||||||
|
) 3>$qtmp 4<$qtmp # can't use "|| return" here...
|
||||||
|
# ...because "|| return" would mess up "set -e" inside the ()
|
||||||
|
# on some shells. Running commands in "||" context, even
|
||||||
|
# deep inside, will stop "set -e" from functioning.
|
||||||
|
rv=$?
|
||||||
|
[ "$rv" = 0 ] || return "$rv"
|
||||||
|
mv "$tmp" "$target" 2>/dev/null
|
||||||
|
[ -e "$target.did.tmp" ] &&
|
||||||
|
mv "$target.did.tmp" "$target.did" ||
|
||||||
|
: >>"$target.did"
|
||||||
|
else
|
||||||
|
_debug "do $DO_DEPTH$target exists." >&2
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Implementation of the "redo" command.
|
||||||
|
_redo()
|
||||||
|
{
|
||||||
|
local i startdir="$PWD" dir base
|
||||||
|
set +e
|
||||||
|
for i in "$@"; do
|
||||||
|
i=$(_abspath "$i" "$startdir")
|
||||||
|
(
|
||||||
|
cd "$DO_STARTDIR" || return 99
|
||||||
|
i=$(_realpath "$(_relpath "$i" "$PWD")" "$PWD")
|
||||||
|
_dirsplit "$i"
|
||||||
|
dir=$_dirsplit_dir base=$_dirsplit_base
|
||||||
|
_do "$dir" "$base"
|
||||||
|
)
|
||||||
|
[ "$?" = 0 ] || return 1
|
||||||
|
done
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# Implementation of the "redo-whichdo" command.
|
||||||
|
_whichdo()
|
||||||
|
{
|
||||||
|
_find_dofiles "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
case $_cmd in
|
||||||
|
do|redo|redo-ifchange) _redo "$@" ;;
|
||||||
|
redo-whichdo) _whichdo "$1" ;;
|
||||||
|
do.test) ;;
|
||||||
|
*) printf "do: '%s': unexpected redo command" "$_cmd" >&2; exit 99 ;;
|
||||||
|
esac
|
||||||
|
[ "$?" = 0 ] || exit 1
|
||||||
|
|
||||||
|
if [ -n "$DO_TOP" ]; then
|
||||||
|
if [ -n "$_do_opt_clean" ]; then
|
||||||
|
echo "do: Removing stamp files..." >&2
|
||||||
|
[ ! -e "$DO_BUILT" ] ||
|
||||||
|
while read f; do printf "%s.did\0" "$f"; done <"$DO_BUILT" |
|
||||||
|
xargs -0 rm -f 2>/dev/null
|
||||||
|
fi
|
||||||
|
fi
|
|
@ -0,0 +1,3 @@
|
||||||
|
*
|
||||||
|
!*.do
|
||||||
|
!.gitignore
|
|
@ -0,0 +1,40 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# This do script creates an indirect root to an input flake
|
||||||
|
|
||||||
|
exec >&2
|
||||||
|
|
||||||
|
redo-ifchange ../flake.nix ../flake.lock || true
|
||||||
|
|
||||||
|
resolve_flake() {
|
||||||
|
STORE_PATH=$(nix flake info --json --inputs-from .. "$2" | jq -r .path)
|
||||||
|
|
||||||
|
# Do this after 'info' to avoid unnecessary network activity. nix flake
|
||||||
|
# archive may try to download a flake although the store path is available.
|
||||||
|
if [ ! -d "$STORE_PATH" ]; then
|
||||||
|
nix flake archive --inputs-from .. "$2"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
case $2 in
|
||||||
|
# Resolves cleanup targets by their softlinks
|
||||||
|
clean)
|
||||||
|
redo-always || true
|
||||||
|
find . -type l -print -exec realpath -P --relative-base="$PWD" {} \+ |
|
||||||
|
while read p; do
|
||||||
|
if [ "$p" = "${p#/}" ]; then
|
||||||
|
rm -rf -- "$p"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
;;
|
||||||
|
*.rw)
|
||||||
|
resolve_flake "$@"
|
||||||
|
rm -rf -- ".$2"
|
||||||
|
cp --reflink=auto -r --no-preserve=mode "$STORE_PATH" ".$2"
|
||||||
|
ln -sf ".$2" "$3"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
resolve_flake "$@"
|
||||||
|
nix-store -r "$STORE_PATH" --indirect --add-root "$2"
|
||||||
|
[ "$2" = "$3" ] || mv "$2" "$3"
|
||||||
|
;;
|
||||||
|
esac
|
Loading…
Reference in New Issue