Skip to content

Instantly share code, notes, and snippets.

@ottidmes

ottidmes/nux.sh Secret

Last active December 24, 2018 00:08
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/b1945daa7bd1303eb94650d59ee9c98c to your computer and use it in GitHub Desktop.
Save ottidmes/b1945daa7bd1303eb94650d59ee9c98c to your computer and use it in GitHub Desktop.
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