Skip to content

Instantly share code, notes, and snippets.

@ottidmes
Created December 1, 2018 23:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ottidmes/213af6c5f26c5d75c59bd42d67b43405 to your computer and use it in GitHub Desktop.
Save ottidmes/213af6c5f26c5d75c59bd42d67b43405 to your computer and use it in GitHub Desktop.
#!/usr/bin/env bash
nix-path() {
if (( $# < 1 )) || [[ $1 == --help ]]; then
echo "Usage: nix-path <pkg_name>..." >&2
return 1
fi
if [[ -z $NIX_PATH ]]; then return 1; fi
local ret=0 needle found name nix_path
for needle in "$@"; do
found=false
while IFS= read -r -d ':' nix_path; do
IFS='=' read -r name nix_path <<< "$nix_path"
if [[ $name == "$needle" ]]; then
found=true
echo "$nix_path"
break
fi
done <<< "$NIX_PATH:"
! $found && ret=1
done
return $ret
}
nixos-config() {
local nixos_config
if [[ -n $NIXOS_CONFIG ]]; then
nixos_config=$NIXOS_CONFIG
elif ! nixos_config=$(nix-path nixos-config); then
nixos_config=/etc/nixos/configuration.nix
fi
echo "$nixos_config"
}
grep-nix-store() {
find /nix/store -maxdepth 1 | grep "$@"
}
nix-store-path() {
if (( $# < 1 )) || [[ $1 == --help ]]; then
echo "Usage: nix-store-path <store_path_like>..." >&2
return 1
fi
local ret=0 store_path real_store_path
for store_path in "$@"; do
if [[ $store_path =~ ^[a-z0-9]{32} ]]; then
(( ${#store_path} == 32 )) && store_path=$(bash -c "echo /nix/store/'$store_path'-*") || store_path=/nix/store/$store_path
elif ! [[ $store_path == /nix/store/* ]]; then
if real_store_path=$(readlink --canonicalize-existing "$store_path") && [[ $real_store_path == /nix/store/* ]]; then
echo "$real_store_path"
continue
elif ! store_path=$(nix-out "$store_path"); then
ret=1
continue
fi
fi
[[ -e $store_path ]] && echo "$store_path" || ret=1
done
return $ret
}
nix-outs() {
if (( $# != 1 )) || [[ -z $1 || $1 == --help ]]; then
echo "Usage: nix-outs <pkg_name>" >&2
return 1
fi
local pkg_name=$1 pkg_drv
pkg_drv=$(nix-instantiate --quiet '<nixpkgs>' --attr "$pkg_name") &&
nix-store --query --outputs "$pkg_drv"
}
nix-out() {
if (( $# < 1 )) || [[ $1 == --help ]]; then
echo "Usage: nix-out <pkg_name>..." >&2
return 1
fi
local ret=0 pkg_name
for pkg_name in "$@"; do
[[ -n $pkg_name ]] && nix-outs "$pkg_name" > >(tail -1) || ret=1
done
return $ret
}
nix-drv-name() {
local arg
for arg in "$@"; do
arg=${arg%$'\n'}
echo -n "$arg" | sed 's/^\.*//' | tr -cs '+-._?=[:alnum:]' -
done
}
nix-drv() {
if (( $# < 1 )); then
echo "Usage: nix-drv <store_path>..." >&2
return 1
fi
local ret=0 store_path pkg_drv
for store_path in "$@"; do
store_path=$(nix-store-path "$store_path") &&
pkg_drv=$(nix-store --query --deriver "$store_path") &&
[[ $pkg_drv != unknown-deriver ]] && echo "$pkg_drv" || ret=1
done
return $ret
}
whichpkg() {
local store_path
while IFS= read -r store_path; do
pkgname "$store_path"
done < <(which "$@")
}
pkgname() {
if (( $# != 1 )) || [[ -z $1 ]]; then
echo "Usage: pkgname <name>" >&2
return 1
fi
search_name=$1
# /nix/store/k033y37bvx5npnrbg14b4rd5vrc0p7gr-rsync-3.1.3/bin/rsync ~> rsync-3.1.3
if [[ $search_name =~ ^/nix/store/ ]]; then
search_name=$(echo "$search_name" | sed 's|/nix/store/.\{32\}-\([^/]*\).*|\1|')
fi
# rsync-3.1.3 ~> rsync
grep_name=$(echo "$search_name" | sed 's/[-_]\?[0-9].*//')
# Remove characters that would worsen the results of grep's matching.
grep_name="${grep_name//[^a-zA-Z_-]/}"
# If word boundaries are defined, check all common formats, e.g. inotify-tools ~> (inotify-tools, inotify_tools, inotifytools)
if [[ $grep_name =~ [-_] ]]; then
grep_names=( "${grep_name//[-_]/-}" "${grep_name//[-_]/_}" "${grep_name//[-_]/}" )
else
grep_names=( "$grep_name" )
fi
# Find all package names that partially match the name package name being searched for.
tab=$'\t'
grep_regexp="[^ ${tab}]*($(echo "${grep_names[@]}" | tr ' ' '|'))[^ ]* = callPackage"
nixpkgs=$(nix-path nixpkgs)
if ! pkg_names=$(grep -E --ignore-case --only-matching "$grep_regexp" "$nixpkgs/pkgs/top-level/all-packages.nix"); then
echo "no matches found for '$*'" >&2
return 1
fi
pkg_names=${pkg_names// = callPackage/}
# Optimize the search name for regular expression matching.
# By removing all non-letters and non-digits and lowercasing the letters,
# we unify most naming conventions found in all-packages.nix.
re_search_name=$(tr 'A-Z' 'a-z' <<< "${search_name//[^a-zA-Z0-9]/}")
likely_matches=()
while IFS= read -r pkg_name; do
# Same optimizations as `re_search_name`.
re_pkg_name=$(tr 'A-Z' 'a-z' <<< "${pkg_name//[^a-zA-Z0-9]/}")
# We found an exact match, no need to continue searching.
if [[ $re_pkg_name == "$re_search_name" ]]; then
echo "exact match: $pkg_name"
return 0
# We already know the name matches, otherwise it would not have matched the grep's regexp.
elif [[ $re_search_name =~ [0-9] ]]; then
# Find a package name that exactly matches the name of the package being searched for
# and that has a version in the name that comes the closest to the version we are looking for.
if [[ $re_search_name =~ ^${re_pkg_name} ]]; then
if (( ${#re_pkg_name} > ${#re_best_match} )); then
best_match=$pkg_name
re_best_match=$re_pkg_name
fi
# A partial match of both name and version, so a likely candidate.
elif [[ $re_pkg_name =~ $re_search_name ]]; then
likely_matches+=( "$pkg_name" )
fi
fi
done <<< "$pkg_names"
if [[ -n $best_match ]]; then
echo "best match: $best_match"
elif (( ${#likely_matches[@]} > 0 )); then
echo 'likely matches:' "${likely_matches[@]}"
else
echo -n 'potential matches:'
while IFS= read -r pkg_name; do
echo -n " ${pkg_name}"
done <<< "$pkg_names"
echo
fi
}
pkgfile() {
if (( $# != 1 )) || [[ -z $1 ]]; then
echo "Usage: pkgfile <pkg_name>" >&2
return 1
fi
local grep_name=$1
local tab=$'\t'
local nixpkgs=$(nix-path nixpkgs)
local call_pkg
if ! call_pkg=$(grep -E --ignore-case --max-count=1 --only-matching "[ ${tab}]$grep_name = callPackage [^ ]*" "$nixpkgs/pkgs/top-level/all-packages.nix"); then
echo "No matches found for '$grep_name'" >&2
return 1
fi
local pkg_path
! pkg_path=$(realpath "$nixpkgs/pkgs/top-level/$(echo "$call_pkg" | sed 's/.*callPackage \(.*\)/\1/')") && return 1
if [[ -d $pkg_path ]]; then
echo "$pkg_path"/default.nix
else
echo "$pkg_path"
fi
}
nix-prefetch-src() {
if (( $# != 1 )) || [[ -z $1 ]]; then
echo "Usage: nix-prefetch-src <pkg_name>" >&2
return 1
fi
local pkg_name=$1
nix-prefetch-url '<nixpkgs>' --attr "${pkg_name}.src"
}
for call in build shell; do
source /dev/stdin <<EOF
nix-$call-call() {
local pkg_path
if (( \$# == 0 )); then
pkg_path=./.
else
pkg_path=\$1
if [[ ! -e \$pkg_path ]]; then
echo "derivation file or directory '\$pkg_path' does not exist" >&2
exit 1
fi
if [[ \$pkg_path != */* ]]; then
pkg_path=./\$pkg_path
fi
fi
nix-$call --expr "with import <nixpkgs> { }; callPackage \$pkg_path { }"
}
EOF
done
unset -v call
nixpkgs-update() {
local nixpkgs nixpkgs_unstable
nixpkgs=$(nix-path nixpkgs) &&
git -C "$nixpkgs" remote update channels &&
git -C "$nixpkgs" rebase channels/nixos-"$(< "$nixpkgs"/.version)" &&
nixpkgs_unstable=$(nix-path nixpkgs-unstable) &&
git -C "$nixpkgs_unstable" rebase channels/nixos-unstable
}
nixos-upgrade() {
command nix-env --uninstall '.*' &&
command sudo nix-env --uninstall '.*' &&
nixpkgs-update &&
sudo nixos-rebuild boot
}
nano-nix() {
nano-readonly /etc/nix/nix.conf &&
systemctl restart nix-daemon
}
lspkgs() {
local user_name
user_name=$(id --user --name) &&
nix-instantiate --eval --strict --json --expr \
'map (pkg: pkg.name) (let config = (import <nixpkgs/nixos> { }).config; in config.environment.systemPackages ++ config.users.users."'"$user_name"'".packages)' |
jq --raw-output 'unique | sort_by(ascii_downcase) | .[]'
}
nixos-system-diff() {
local old_drv new_drv
old_drv=$(nix-store --query --deriver "$(readlink --canonicalize-existing /nix/var/nix/profiles/system)") &&
new_drv=$(nix-instantiate --quiet '<nixpkgs/nixos>' --attr system) &&
nix-diff "$old_drv" "$new_drv"
}
nix-du() {
if (( $# < 1 )); then
echo "Usage: nix-du /nix/store/..." >&2
return 1
fi
du --human-readable --total --max=0 $(nix-store --query --requisites "$1") | sort --human-numeric-sort
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment