1
0
Files
nix-shared/pkgs/tb-scripts/rename_lower.py
Timo Bingmann bce9ece27b Add custom script packages with Nix dependency management
This commit introduces two new custom script packages: tb-scripts for
all systems and tb-dev-scripts for development machines. These packages
provide a maintainable way to distribute utility scripts across the
infrastructure with proper dependency management.

Created pkgs/ directory with two script collections:

1. **tb-scripts** - General utilities available on all systems:
   - ,jq_reformat: Reformat JSON files in-place with atomic file operations
   - ,rename_lower: Convert filenames to lowercase with validation

2. **tb-dev-scripts** - Development-specific tools:
   - ,cmake_update_fetchcontent: Update CMake FetchContent dependencies

All scripts have been significantly enhanced from their original versions:

- Proper quoting to handle filenames with spaces
- Secure temporary file creation using mktemp
- Atomic file replacement to prevent data loss
- Input validation and comprehensive error handling
- Usage help with -h/--help flag
- Extensive inline comments explaining each section
- Cleanup traps on error

- Complete rewrite in Python for consistency
- Validates files exist before attempting rename
- Checks if target lowercase filename already exists
- Skips files already lowercase (no-op)
- Descriptive error messages for each failure case
- Usage documentation with examples
- Proper exit codes

- Interactive CMake FetchContent dependency updater
- Recursively finds all CMakeLists.txt files via add_subdirectory()
- Queries GitHub API for latest releases/tags
- Compares semantic versions and commit hashes
- Shows available updates in formatted table
- Prompts for confirmation before applying updates
- Atomic file updates with validation

Scripts are packaged using writeShellApplication with proper dependency
injection via runtimeInputs:

- tb-scripts requires: jq, python3
- tb-dev-scripts requires: python3, git

Dependencies are automatically available in PATH when scripts run,
eliminating manual dependency checks.

Created system module files to import the script packages:

- system/default/scripts.nix: Adds tb-scripts to nixosModules.default
- system/develop/scripts.nix: Adds tb-dev-scripts to nixosModules.develop

Updated flake.nix to import these modules in the appropriate contexts.

- Scripts have proper Nix-managed dependencies
- No manual installation or PATH configuration needed
- Easy to extend with additional scripts
- Scripts are validated with shellcheck during build
- Clear separation between all-systems and dev-only utilities
- Comprehensive error handling and user documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-19 05:35:33 -08:00

116 lines
2.8 KiB
Python

#!/usr/bin/env python3
"""
rename_lower - Rename files to lowercase
Usage: rename_lower FILE [FILE...]
This script renames files by converting their filenames to lowercase.
It performs validation to ensure files exist and that the target lowercase
filename doesn't already exist before renaming.
Examples:
rename_lower MyFile.TXT
rename_lower *.JPG
rename_lower Document.PDF Image.PNG
"""
import os
import sys
from pathlib import Path
def usage():
"""Show usage information"""
print("""Usage: ,rename_lower FILE [FILE...]
Rename files to lowercase filenames.
This script converts filenames to lowercase. It validates that files
exist and checks for conflicts before renaming.
Arguments:
FILE One or more files to rename
Options:
-h, --help Show this help message
Examples:
,rename_lower MyFile.TXT
,rename_lower *.JPG
,rename_lower Document.PDF Image.PNG
Exit codes:
0 Success - all files renamed (or already lowercase)
1 Error - invalid arguments, missing files, or conflicts
""")
def rename_to_lowercase(filepath: str) -> bool:
"""
Rename a single file to lowercase.
Arguments:
filepath: Path to the file to rename
Returns:
True on success, False on error
"""
# Convert to Path object for easier manipulation
original = Path(filepath)
# Validate that the file exists
if not original.exists():
print(f"Error: File not found: {filepath}", file=sys.stderr)
return False
# Get the directory and filename components
directory = original.parent
original_name = original.name
lowercase_name = original_name.lower()
# Check if the filename is already lowercase
if original_name == lowercase_name:
# Already lowercase, nothing to do
return True
# Construct the target path
target = directory / lowercase_name
# Check if target already exists
if target.exists():
print(f"Error: Target file already exists: {target}", file=sys.stderr)
print(f" Cannot rename: {filepath}", file=sys.stderr)
return False
# Perform the rename
try:
original.rename(target)
print(f"Renamed: {original_name} -> {lowercase_name}")
return True
except OSError as e:
print(f"Error: Failed to rename {filepath}: {e}", file=sys.stderr)
return False
def main():
"""Main script logic"""
# Handle help flag or no arguments
if len(sys.argv) == 1 or sys.argv[1] in ("-h", "--help"):
usage()
return 0 if len(sys.argv) > 1 else 1
success = True
# Process each file argument
for filepath in sys.argv[1:]:
if not rename_to_lowercase(filepath):
success = False
# Continue processing other files even if one fails
return 0 if success else 1
if __name__ == "__main__":
sys.exit(main())