7.8 KiB
Executable File
7.8 KiB
Executable File
Version TUI Documentation
Overview
The version_tui.py script is an interactive terminal interface for managing package versions in a NixOS repository. It provides a unified way to update version.json files, Python packages, and Home Assistant components.
Architecture
Core Components
- Package Discovery: Scans the repository for different package types
- Version Management: Handles version.json, Python default.nix, and Home Assistant components
- Hash Computation: Uses modern Nix commands for reliable hash generation
- Interactive Interface: Curses-based TUI with color support and keyboard navigation
Package Types Supported
1. Regular Packages (packages/**/version.json)
- Standard version.json format with variables and sources
- Support for variants (base + overrides)
- Multiple fetcher types: github, git, url
2. Python Packages (packages/python/*/default.nix)
- Parses version, pname, and source info from default.nix
- Supports fetchFromGitHub and fetchPypi patterns
- Updates version, hash, tag, and rev fields
3. Home Assistant Components (packages/homeassistant/*/default.nix)
- Specialized parsing for HA component structure
- Handles domain, version, owner, and repo extraction
- GitHub-aware source management
Fetcher Types
GitHub Fetcher
{
"fetcher": "github",
"owner": "owner",
"repo": "repo",
"tag": "v1.0.0",
"rev": "commit-hash",
"hash": "sha256-..."
}
Git Fetcher
{
"fetcher": "git",
"url": "https://github.com/user/repo.git",
"rev": "commit-hash",
"hash": "sha256-..."
}
URL Fetcher
{
"fetcher": "url",
"url": "https://example.com/file.tar.gz",
"hash": "sha256-..."
}
Key Functions
Hash Computation
nix_prefetch_url(url: str)
Purpose: Compute SHA256 SRI hash for URL sources Method:
- Try
nix store prefetch-file(modern, SRI output) - Fallback to
nix-prefetch-url(legacy, needs conversion) - Convert to SRI format if needed
nix_prefetch_git(url: str, rev: str)
Purpose: Compute SHA256 SRI hash for Git repositories
Method:
- Use
nix evalwithbuiltins.fetchGitto get store path - Hash the store path with
nix hash path --type sha256 - Fallback to
nix-prefetch-gitif available
API Functions
gh_latest_release(owner, repo, token)
- Gets latest release from GitHub API
- Returns tag_name of latest release
- Handles API errors gracefully
gh_latest_tag(owner, repo, token)
- Gets all tags and returns the first one
- Limited to 100 tags per page
- Sorts by GitHub's default ordering
gh_head_commit(owner, repo)
- Uses
git ls-remoteto get HEAD commit - No API token required
- Fallback for when GitHub API fails
Special Cases
Raspberry Pi Linux
- Prefers
stable_YYYYMMDDtags over latest - Falls back to series-specific tags (
rpi-X.Y) - Maintains compatibility with existing tagging schemes
CachyOS Linux
- Fetches latest version from upstream PKGBUILD
- Supports different suffixes (rc, hardened, lts)
- Handles both .SRCINFO and PKGBUILD parsing
UI Navigation
Main Package List
↑/k/j : Navigate up/down
g/G : Go to top/bottom
Enter : Open package details
f : Cycle filters (all → regular → python → all)
q/ESC : Quit
Package Details Screen
←/h/l : Switch variants (if available)
↑/k/j : Navigate sources
r : Refresh candidates
h : Recompute hash
e : Edit field (path=value)
s : Save changes
i : Show full URL (URL sources)
Enter : Action menu for selected source
Backspace : Return to package list
q/ESC : Quit
Action Menu
↑/k/j : Select option
Enter : Execute selected action
Backspace : Cancel
File Structure Analysis
version.json Format
{
"schemaVersion": 1,
"variables": {
"key": "value"
},
"sources": {
"name": {
"fetcher": "type",
"...": "..."
}
},
"variants": {
"variant-name": {
"sources": {
"name": {
"override": "value"
}
}
}
}
}
Python Package Parsing
The script extracts information from patterns like:
{
pname = "package-name";
version = "1.0.0";
src = fetchFromGitHub {
owner = "user";
repo = "repo";
rev = "v1.0.0";
sha256 = "...";
};
}
Home Assistant Component Parsing
{
domain = "component_name";
version = "1.0.0";
src = fetchFromGitHub {
owner = "user";
repo = "repo";
rev = "v1.0.0";
sha256 = "...";
};
}
Error Handling
Network Errors
- Timeouts: 10-second timeout on HTTP requests
- HTTP status codes: Proper handling of 4xx/5xx responses
- Retry logic: Graceful fallback when APIs fail
API Rate Limiting
- Uses
GITHUB_TOKENenvironment variable if available - Provides clear error messages when rate limited
- Falls back to git commands when API fails
Git Command Failures
- Robust error handling for git ls-remote
- Validation of git command output
- Clear error messages for debugging
Configuration
Environment Variables
GITHUB_TOKEN: GitHub personal access token (optional)- Increases API rate limits from 60/hour to 5000/hour
Dependencies
- Required:
nixcommand with experimental features - Optional:
nix-prefetch-git,gitcommands - Python: Standard library + curses
Troubleshooting
Hash Mismatches
- Check if using correct Nix version
- Verify network connectivity to GitHub
- Try manual hash computation:
nix store prefetch-file --hash-type sha256 <url>
Missing Candidates
- Check GitHub token availability
- Verify repository exists and is accessible
- Check network connectivity
- Try manual API calls with curl
Display Issues
- Ensure terminal supports colors and Unicode
- Check terminal size (minimum 80x24 recommended)
- Try resizing terminal window
- Use
-rflag to force redraw
Development
Adding New Fetcher Types
- Update
fetch_candidates_for()method - Add parsing logic to appropriate
parse_*()function - Update hash computation methods
- Add UI handling for new type
Testing Changes
# Test individual functions
python3 -c "
from scripts.version_tui import nix_prefetch_url
print(nix_prefetch_url('https://example.com/file.tar.gz'))
"
# Test package parsing
python3 -c "
from scripts.version_tui import parse_python_package
print(parse_python_package(Path('packages/python/example/default.nix')))
"
Architecture Decisions
Why Multiple Hash Methods?
- Different Nix versions have different available commands
- Modern Nix uses
nix store prefetch-fileandnix eval - Legacy systems use
nix-prefetch-urlandnix-prefetch-git - Script tries modern methods first, falls back gracefully
Why Template Rendering?
- Variables allow flexible version specifications
- Supports
${variable}substitution in URLs and tags - Enables consistent updates across variants
- Reduces duplication in version.json files
Why Two-Step Git Hash?
builtins.fetchGitprovides store paths, not hashesnix hash pathworks reliably on store paths- More consistent than trying to parse git command output
- Works with all git repository formats
File Organization
scripts/
├── version_tui.py # Main script
├── __pycache__/ # Python cache
└── README_tui.md # This documentation
Security Considerations
- No sensitive data is logged
- GitHub tokens are handled securely via environment
- Hash computation uses read-only operations
- No credentials are stored or transmitted unnecessarily
Performance
- Lazy loading of candidates (only when needed)
- Caching of computed hashes during session
- Parallel network requests where possible
- Efficient terminal rendering with minimal refreshes