# 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

1. **Package Discovery**: Scans the repository for different package types
2. **Version Management**: Handles version.json, Python default.nix, and Home Assistant components
3. **Hash Computation**: Uses modern Nix commands for reliable hash generation
4. **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
```json
{
  "fetcher": "github",
  "owner": "owner",
  "repo": "repo",
  "tag": "v1.0.0",
  "rev": "commit-hash",
  "hash": "sha256-..."
}
```

### Git Fetcher
```json
{
  "fetcher": "git", 
  "url": "https://github.com/user/repo.git",
  "rev": "commit-hash",
  "hash": "sha256-..."
}
```

### URL Fetcher
```json
{
  "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**: 
1. Try `nix store prefetch-file` (modern, SRI output)
2. Fallback to `nix-prefetch-url` (legacy, needs conversion)
3. Convert to SRI format if needed

#### `nix_prefetch_git(url: str, rev: str)`
**Purpose**: Compute SHA256 SRI hash for Git repositories  
**Method**:
1. Use `nix eval` with `builtins.fetchGit` to get store path
2. Hash the store path with `nix hash path --type sha256`
3. Fallback to `nix-prefetch-git` if 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-remote` to get HEAD commit
- No API token required
- Fallback for when GitHub API fails

### Special Cases

#### Raspberry Pi Linux
- Prefers `stable_YYYYMMDD` tags 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
```json
{
  "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:
```nix
{
  pname = "package-name";
  version = "1.0.0";
  src = fetchFromGitHub {
    owner = "user";
    repo = "repo";
    rev = "v1.0.0";
    sha256 = "...";
  };
}
```

### Home Assistant Component Parsing
```nix
{
  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_TOKEN` environment 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**: `nix` command with experimental features
- **Optional**: `nix-prefetch-git`, `git` commands
- **Python**: Standard library + curses

## Troubleshooting

### Hash Mismatches
1. Check if using correct Nix version
2. Verify network connectivity to GitHub
3. Try manual hash computation:
   ```bash
   nix store prefetch-file --hash-type sha256 <url>
   ```

### Missing Candidates
1. Check GitHub token availability
2. Verify repository exists and is accessible
3. Check network connectivity
4. Try manual API calls with curl

### Display Issues
1. Ensure terminal supports colors and Unicode
2. Check terminal size (minimum 80x24 recommended)
3. Try resizing terminal window
4. Use `-r` flag to force redraw

## Development

### Adding New Fetcher Types
1. Update `fetch_candidates_for()` method
2. Add parsing logic to appropriate `parse_*()` function
3. Update hash computation methods
4. Add UI handling for new type

### Testing Changes
```bash
# 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-file` and `nix eval`
- Legacy systems use `nix-prefetch-url` and `nix-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.fetchGit` provides store paths, not hashes
- `nix hash path` works 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