Last active
February 10, 2025 03:41
-
-
Save aymanbagabas/96579c4c62f9e20066001a11cdd682fa to your computer and use it in GitHub Desktop.
Find all versions of a package that were available in a channel and the revision you can download it from using https://github.com/lazamar/nix-package-versions
This file contains hidden or 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
#!/usr/bin/env bash | |
# Check if gum is installed | |
if ! command -v gum &>/dev/null; then | |
echo "Error: gum is not installed. Please install it first." | |
exit 1 | |
fi | |
# Default values | |
CHANNEL="nixpkgs-unstable" | |
FORMAT="" | |
# Show help function | |
show_help() { | |
echo "Usage: $0 [-c channel] [-f format] package" >&2 | |
echo >&2 | |
echo "Options:" >&2 | |
echo " -h Show this help message" >&2 | |
echo " -c <channel> Specify the Nix channel (default: nixpkgs-unstable)" >&2 | |
echo " -f <format> Output format (env|shell|profile|in-shell)" >&2 | |
echo >&2 | |
echo "Examples:" >&2 | |
echo " $0 python # Search python in nixpkgs-unstable" >&2 | |
echo " $0 -c nixos-23.05 python # Search python in nixos-23.05" >&2 | |
echo " $0 -f shell python # Get nix shell command for python" >&2 | |
exit 1 | |
} | |
# Parse command line arguments | |
while getopts "c:f:h" opt; do | |
case $opt in | |
c) | |
CHANNEL="$OPTARG" | |
;; | |
f) | |
FORMAT="$OPTARG" | |
;; | |
h) | |
show_help | |
;; | |
\?) | |
echo "Invalid option: -$OPTARG" >&2 | |
show_help | |
;; | |
esac | |
done | |
# Shift off the options and optional -- | |
shift $((OPTIND - 1)) | |
# Get package name from argument or gum input if in TTY | |
PACKAGE=${1} | |
if [ -z "$PACKAGE" ]; then | |
if [ -t 0 ]; then # Check if running in a TTY | |
PACKAGE=$(gum input --placeholder "Enter package name" --header "Which package do you want to search?") | |
fi | |
if [ -z "$PACKAGE" ]; then | |
show_help | |
fi | |
fi | |
URL="https://lazamar.co.uk/nix-versions/?channel=${CHANNEL}&package=${PACKAGE}" | |
# Fetch data | |
echo "Fetching data for package '${PACKAGE}' from channel '${CHANNEL}'..." >&2 | |
HTML=$(curl -sL "$URL") | |
# Extract the table data | |
DATA=$(echo "$HTML" | grep -Eo '<tbody>.*</tbody>' || echo "") | |
if [ -z "$DATA" ]; then | |
echo "Error: No data found for package '${PACKAGE}' in channel '${CHANNEL}'" >&2 | |
exit 1 | |
fi | |
# Process the data into different formats | |
process_data() { | |
echo "$DATA" | grep -o '<tr[^>]*>.*</tr>' | sed 's/<tr[^<]*>/\n/g' | while read -r line; do | |
data=$(echo "$line" | grep -o '<td>[^<]*</td>' | sed 's/<td>\([^<]*\)<\/td>/\1/') | |
package=$(echo "$data" | sed -n '1p') | |
version=$(echo "$data" | sed -n '2p') | |
revision=$(echo "$line" | grep -o '<a[^<]*</a>' | sed 's/<a[^>]*>\([^<]*\)<\/a>/\1/' | sed -n '1p') | |
date=$(echo -n "$data" | sed -n '3p') | |
if [ "$package" != "$PACKAGE" ]; then | |
continue | |
fi | |
printf "%s %s %s\n" "$version" "$revision" "$date" | |
done | |
} | |
# Build data array | |
DATA=$(process_data | sort -k3,3r -k1,1r) | |
# Let user filter the versions sorted by date and without the revision in the output | |
CHOICE=$(echo "$DATA" | gum filter --height=20 --reverse --header "Select version" || echo "") | |
if [ -z "$CHOICE" ]; then | |
echo "Error: No version selected" >&2 | |
exit 1 | |
fi | |
VERSION=$(echo "$CHOICE" | cut -d' ' -f1) | |
REVISION=$(echo "$CHOICE" | cut -d' ' -f2) | |
TEMPLATE_ENV=$( | |
cat <<EOF | |
nix-env -iA $PACKAGE -f https://github.com/NixOS/nixpkgs/archive/$REVISION.tar.gz | |
EOF | |
) | |
TEMPLATE_IN_SHELL=$( | |
cat <<EOF | |
nix-shell -p $PACKAGE -I nixpkgs=https://github.com/NixOS/nixpkgs/archive/$REVISION.tar.gz | |
EOF | |
) | |
TEMPLATE_SHELL=$( | |
cat <<EOF | |
nix shell github:nixos/nixpkgs/$REVISION#$PACKAGE | |
EOF | |
) | |
TEMPLATE_PROFILE=$( | |
cat <<EOF | |
nix profile install nixpkgs/$REVISION#$PACKAGE | |
EOF | |
) | |
TEMPLATE=$( | |
cat <<EOF | |
# Install $PACKAGE with nix-env. | |
\`\`\`sh | |
$TEMPLATE_ENV | |
\`\`\` | |
# Use $PACKAGE in a nix-shell. | |
\`\`\`sh | |
$TEMPLATE_IN_SHELL | |
\`\`\` | |
# Use $PACKAGE with nix shell. | |
\`\`\`sh | |
$TEMPLATE_SHELL | |
\`\`\` | |
# Install $PACKAGE with nix profile. | |
\`\`\`sh | |
$TEMPLATE_PROFILE | |
\`\`\` | |
# Use $PACKAGE in a nix script via tarball | |
\`\`\`nix | |
let | |
pkgs = import (builtins.fetchTarball { | |
url = "https://github.com/NixOS/nixpkgs/archive/$REVISION.tar.gz"; | |
}) {}; | |
myPkg = pkgs.$PACKAGE; | |
in | |
... | |
\`\`\` | |
# Use $PACKAGE in a nix script via Git | |
\`\`\`nix | |
let | |
pkgs = import (builtins.fetchGit { | |
# Descriptive name to make the store path easier to identify | |
name = "my-old-revision"; | |
url = "https://github.com/NixOS/nixpkgs/"; | |
ref = "refs/heads/$CHANNEL"; | |
rev = "$REVISION"; | |
}) {}; | |
myPkg = pkgs.$PACKAGE; | |
in | |
... | |
\`\`\` | |
EOF | |
) | |
INFO=" | |
For more information, see the [Installation Instructions](https://lazamar.co.uk/nix-versions/?package=$PACKAGE&version=$VERSION&fullName=$PACKAGE-$VERSION&keyName=$PACKAGE&revision=$REVISION&channel=$CHANNEL) | |
" | |
# Format the output if format is not specified | |
case "$FORMAT" in | |
'env') | |
echo "$TEMPLATE_ENV" | |
;; | |
'shell') | |
echo "$TEMPLATE_SHELL" | |
;; | |
'profile') | |
echo "$TEMPLATE_PROFILE" | |
;; | |
'in-shell') | |
echo "$TEMPLATE_IN_SHELL" | |
;; | |
*) | |
gum format "$TEMPLATE$INFO" | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment