-
-
Save ottidmes/b1945daa7bd1303eb94650d59ee9c98c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 | |
} | |
nux-path() { | |
local help_ret=1 | |
if ! (( $# > 0 )) || { [[ $1 =~ ^(-h|--help)$ ]] && help_ret=0; }; then | |
help_stdin $help_ret <<'EOF' | |
Lookup a NIX_PATH prefix. | |
Usage: | |
nux path <prefix>... | |
nux path -h | --help | |
Options: | |
-h, --help Show help message. | |
EOF | |
return $help_ret | |
fi | |
[[ -z $NIX_PATH ]] && return 1 | |
local ret=0 prefix found item nix_path | |
for prefix in "$@"; do | |
found=0 | |
while IFS= read -rd ':' nix_path; do | |
IFS='=' read -r item nix_path <<< "$nix_path" | |
if [[ $item == "$prefix" ]]; then | |
found=1 | |
echo "$nix_path" | |
break | |
fi | |
done <<< "$NIX_PATH:" | |
(( ! found )) && ret=1 | |
done | |
return $ret | |
} | |
nux-nixos-config() { | |
if [[ $1 =~ ^(-h|--help)$ ]]; then | |
help_stdin <<'EOF' | |
Print the NixOS configuration path. | |
Usage: nux nixos-config [-h | --help] | |
Options: | |
-h, --help Show help message. | |
EOF | |
return 0 | |
fi | |
local nixos_config | |
if [[ -n $NIXOS_CONFIG ]]; then | |
nixos_config=$NIXOS_CONFIG | |
elif ! nixos_config=$(nux-path nixos-config); then | |
nixos_config=/etc/nixos/configuration.nix | |
fi | |
echo "$nixos_config" | |
} | |
nux-pkg-file() { | |
local help_ret=1 | |
if ! { { (( $# == 3 )) && [[ $1 == --user ]]; } || (( $# == 1 )); } || { [[ $1 =~ ^(-h|--help)$ ]] && help_ret=0; }; then | |
help_stdin $help_ret <<'EOF' | |
Print the file defining the package. | |
Usage: | |
nux pkg-file [--configuration <configuration>] <package> | |
nux pkg-file -h | --help | |
Options: | |
--configuration <configuration> The NixOS configuration used to determine the packages set. | |
-h, --help Show help message. | |
EOF | |
return $help_ret | |
fi | |
local configuration pkg | |
(( $# >= 2 )) && [[ $1 == --configuration ]] && configuration=$2 && shift && shift || configuration=$(nux-nixos-config) | |
[[ -e $configuration ]] && configuration="import $configuration" || configuration="'$configuration'" | |
pkg=$1 | |
local nixpkgs=$(nux-path nixpkgs) call_pkg pkg_path | |
if | |
call_pkg=$(grep -E --ignore-case --max-count=1 --only-matching $'[ \t]'"$pkg = callPackage [^ ]*" "$nixpkgs/pkgs/top-level/all-packages.nix") && | |
pkg_path=$(realpath -e "$nixpkgs/pkgs/top-level/$(sed 's/.*callPackage \(.*\)/\1/' <<< "$call_pkg")") | |
then | |
[[ -d $pkg_path ]] && echo "$pkg_path/default.nix" || echo "$pkg_path" | |
else | |
local result | |
if | |
result=$(nix-instantiate --eval --strict --json --expr ' | |
with builtins; | |
with import <nixpkgs/lib>; | |
let | |
inherit (import <nixpkgs/nixos> { configuration = '"$configuration"'; }) pkgs; | |
pkgPath = splitString "." "'"$pkg"'"; | |
pkg = getAttrFromPath pkgPath pkgs; | |
attrFiles = attrs: map (name: (unsafeGetAttrPos name attrs).file) (attrNames attrs); | |
uniqueFiles = unique (attrFiles pkg ++ attrFiles pkg.meta); | |
customisationFiles = filter (hasSuffix "/lib/customisation.nix") uniqueFiles; | |
nixpkgs = removeSuffix "/lib/customisation.nix" (head customisationFiles); | |
isPkgFile = file: !( | |
hasPrefix "/nix/store" file || | |
hasPrefix ("${nixpkgs}/lib") file || | |
hasPrefix ("${nixpkgs}/pkgs/build-support") file || | |
hasPrefix ("${nixpkgs}/pkgs/stdenv/generic") file || | |
hasPrefix ("${nixpkgs}/pkgs/stdenv/") file && builtins.match ".*/.*" (removePrefix ("${nixpkgs}/pkgs/stdenv/") file) == null); | |
pkgFiles = filter isPkgFile uniqueFiles; | |
findSingle = files: default: if length files == 1 then files else default; | |
in if hasAttrByPath pkgPath pkgs && length customisationFiles == 1 && length pkgFiles > 0 | |
then findSingle pkgFiles (findSingle (filter (file: !(hasPrefix nixpkgs file)) pkgFiles) pkgFiles) | |
else [] | |
' > >(jq --raw-output '.[]')) && [[ -n $result ]] | |
then | |
echo "$result" | |
(( $(wc -l <<< "$result") == 1 )) | |
else | |
return 1 | |
fi | |
fi | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment